boatman 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.1.3
data/boatman.gemspec ADDED
@@ -0,0 +1,88 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{boatman}
8
+ s.version = "0.1.3"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Bruz Marzolf"]
12
+ s.date = %q{2011-04-19}
13
+ s.default_executable = %q{boatman}
14
+ s.description = %q{}
15
+ s.email = %q{bmarzolf@systemsbiology.org}
16
+ s.executables = ["boatman"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/boatman",
28
+ "lib/boatman.rb",
29
+ "lib/boatman/copyable.rb",
30
+ "lib/boatman/ext/class.rb",
31
+ "lib/boatman/ext/fixnum.rb",
32
+ "lib/boatman/ext/string.rb",
33
+ "lib/boatman/monitored_directory.rb",
34
+ "lib/boatman/monitored_file.rb",
35
+ "spec/boatman_spec.rb",
36
+ "spec/data/copy_exception.rb",
37
+ "spec/data/copy_exception.yml",
38
+ "spec/data/filename_ending.rb",
39
+ "spec/data/filename_ending.yml",
40
+ "spec/data/filename_ending_regexp.rb",
41
+ "spec/data/filename_ending_regexp.yml",
42
+ "spec/data/filename_regexp.rb",
43
+ "spec/data/filename_regexp.yml",
44
+ "spec/data/folder.rb",
45
+ "spec/data/folder.yml",
46
+ "spec/data/invalid_directory.rb",
47
+ "spec/data/invalid_directory.yml",
48
+ "spec/data/modify.rb",
49
+ "spec/data/modify.yml",
50
+ "spec/data/no_destination_folder.rb",
51
+ "spec/data/no_destination_folder.yml",
52
+ "spec/data/rename.rb",
53
+ "spec/data/rename.yml",
54
+ "spec/spec.opts",
55
+ "spec/spec_helper.rb"
56
+ ]
57
+ s.homepage = %q{http://github.com/bmarzolf/boatman}
58
+ s.require_paths = ["lib"]
59
+ s.rubygems_version = %q{1.3.6}
60
+ s.summary = %q{Ruby DSL for ferrying around and manipulating files}
61
+ s.test_files = [
62
+ "spec/boatman_spec.rb",
63
+ "spec/data/copy_exception.rb",
64
+ "spec/data/filename_ending.rb",
65
+ "spec/data/filename_ending_regexp.rb",
66
+ "spec/data/filename_regexp.rb",
67
+ "spec/data/folder.rb",
68
+ "spec/data/invalid_directory.rb",
69
+ "spec/data/modify.rb",
70
+ "spec/data/no_destination_folder.rb",
71
+ "spec/data/rename.rb",
72
+ "spec/spec_helper.rb"
73
+ ]
74
+
75
+ if s.respond_to? :specification_version then
76
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
77
+ s.specification_version = 3
78
+
79
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
80
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
81
+ else
82
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
83
+ end
84
+ else
85
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
86
+ end
87
+ end
88
+
data/lib/boatman.rb CHANGED
@@ -1,3 +1,10 @@
1
+ begin
2
+ require "ftputils"
3
+ rescue LoadError
4
+ require "rubygems"
5
+ require "ftputils"
6
+ end
7
+
1
8
  require "yaml"
2
9
  require "digest/md5"
3
10
 
@@ -68,9 +75,19 @@ class Boatman
68
75
 
69
76
  tasks.each do |task|
70
77
  if task[:last_run].nil? || Time.now - task[:last_run] > task[:time_interval]
71
- # do everything in the context of the working directory
72
- Dir.chdir(@working_directory) do
73
- task[:directory].instance_eval &task[:block]
78
+ begin
79
+ # do everything in the context of the working directory
80
+ puts "Going to check #{task[:directory].path} at #{Time.now}" if $DEBUG
81
+ Dir.chdir(@working_directory) do
82
+ task[:directory].instance_eval &task[:block]
83
+ end
84
+ puts "Leaving #{task[:directory].path} at #{Time.now}" if $DEBUG
85
+ rescue Exception => e
86
+ Boatman.logger.error "Task monitoring #{task[:directory].path} had an error: #{e.message}" rescue nil
87
+ Boatman.logger.error "Backtrace: #{e.backtrace.join("\n")}" if $DEBUG
88
+
89
+ # clear the FTP connection cache for good luck
90
+ FTPUtils::FTPConnection.clear_connection_cache
74
91
  end
75
92
 
76
93
  task[:last_run] = Time.now
@@ -2,20 +2,20 @@ class Boatman
2
2
  module Copyable
3
3
  def copy(file, params, remove_original=false, &block)
4
4
  source_path = file.path
5
- base_name = params[:rename] || File.basename(source_path)
5
+ base_name = params[:rename] || FTPUtils::FTPFile.basename(source_path)
6
6
 
7
- destination_path = File.expand_path(params[:to] + "/" + base_name)
7
+ destination_path = FTPUtils::FTPFile.expand_path(params[:to] + "/" + base_name)
8
8
 
9
- return if File.exists?(destination_path)
9
+ return if FTPUtils::FTPFile.exists?(destination_path)
10
10
 
11
11
  begin
12
12
  copy_entry(source_path, destination_path, &block)
13
- FileUtils.rm_r source_path if remove_original
13
+ FTPUtils.rm_r source_path if remove_original
14
14
 
15
15
  Boatman.logger.info "Successfully copied #{source_path} to #{destination_path}"
16
16
  rescue Exception => e
17
- # remove the possible incorrect destination file
18
- FileUtils.rm_r "#{destination_path}"
17
+ # remove the possibly incorrect destination file
18
+ FTPUtils.rm_r "#{destination_path}" rescue nil
19
19
  Boatman.logger.error "#{e.message} at #{e.backtrace[0]}"
20
20
  end
21
21
  end
@@ -25,20 +25,20 @@ class Boatman
25
25
  @minimum_age ||= false
26
26
  @maximum_age ||= false
27
27
 
28
- entry_paths = Dir.entries(@path).grep(/#{entry_pattern}/).collect do |name|
28
+ entry_paths = FTPUtils.ls(@path).grep(/#{entry_pattern}/).collect do |name|
29
29
  "#{@path}/#{name}"
30
30
  end
31
31
 
32
32
  Boatman.logger.debug "Found #{entry_paths.size} entries in #{@path}"
33
33
  entry_paths.each do |entry_path|
34
- next if type == :file && !File.file?(entry_path)
35
- next if type == :directory && !File.directory?(entry_path)
34
+ next if type == :file && !FTPUtils::FTPFile.file?(entry_path)
35
+ next if type == :directory && !FTPUtils::FTPFile.directory?(entry_path)
36
36
 
37
- age = Time.now - File.mtime(entry_path)
37
+ age = Time.now - FTPUtils::FTPFile.mtime(entry_path)
38
38
  next if @minimum_age && age < @minimum_age
39
39
  next if @maximum_age && age > @maximum_age
40
40
 
41
- match_data = File.basename(entry_path).match(entry_pattern) if entry_pattern.is_a?(Regexp)
41
+ match_data = FTPUtils::FTPFile.basename(entry_path).match(entry_pattern) if entry_pattern.is_a?(Regexp)
42
42
  case type
43
43
  when :file
44
44
  entry = MonitoredFile.new(entry_path, match_data)
@@ -69,13 +69,14 @@ class Boatman
69
69
  private
70
70
 
71
71
  def copy_entry(source_path, destination_path, &block)
72
- FileUtils.mkdir_p File.dirname(destination_path)
73
- FileUtils.cp_r source_path, destination_path
72
+ FTPUtils.mkdir_p FTPUtils::FTPFile.dirname(destination_path)
74
73
 
75
74
  if block_given?
76
- yield destination_path, "#{destination_path}.tmp"
77
- FileUtils.cp_r "#{destination_path}.tmp", destination_path
78
- FileUtils.rm_r "#{destination_path}.tmp"
75
+ yield source_path, "#{destination_path}.tmp"
76
+ FTPUtils.cp_r "#{destination_path}.tmp", destination_path
77
+ FTPUtils.rm_r "#{destination_path}.tmp"
78
+ else
79
+ FTPUtils.cp_r source_path, destination_path
79
80
  end
80
81
  end
81
82
 
@@ -17,24 +17,38 @@ class Boatman
17
17
  private
18
18
 
19
19
  def copy_entry(source_path, destination_path, &block)
20
- FileUtils.mkdir_p File.dirname(destination_path)
21
- FileUtils.cp source_path, destination_path
22
-
23
- unless @checksum_verification_disabled
24
- verify_checksum_matches(source_path, destination_path, &block)
25
- end
20
+ FTPUtils.mkdir_p FTPUtils::FTPFile.dirname(destination_path)
26
21
 
27
22
  if block_given?
28
- yield destination_path, "#{destination_path}.tmp"
29
- FileUtils.cp "#{destination_path}.tmp", destination_path
30
- FileUtils.rm "#{destination_path}.tmp"
23
+ yield source_path, "#{destination_path}.tmp"
24
+ FTPUtils.cp "#{destination_path}.tmp", destination_path
25
+ FTPUtils.rm "#{destination_path}.tmp"
26
+ else
27
+ FTPUtils.cp source_path, destination_path
28
+
29
+ unless @checksum_verification_disabled
30
+ verify_checksum_matches(source_path, destination_path)
31
+ end
31
32
  end
32
33
  end
33
34
 
34
35
  def verify_checksum_matches(file_1, file_2)
35
- file_1_digest = Digest::MD5.hexdigest( File.read(file_1) )
36
- file_2_digest = Digest::MD5.hexdigest( File.read(file_2) )
36
+ file_1_digest = incremental_digest(file_1)
37
+ file_2_digest = incremental_digest(file_2)
37
38
  raise "Checksum verification failed when copying #{base_name}" unless file_1_digest == file_2_digest
38
39
  end
40
+
41
+ def incremental_digest(file_name)
42
+ file = open(file_name, "r")
43
+
44
+ digester = Digest::MD5.new
45
+ file.each_line do |line|
46
+ digester << line
47
+ end
48
+
49
+ file.close
50
+
51
+ return digester.hexdigest
52
+ end
39
53
  end
40
54
  end
data/spec/boatman_spec.rb CHANGED
@@ -9,11 +9,11 @@ describe "Moving new files from one location to another" do
9
9
  end
10
10
 
11
11
  def run_boatman
12
- thread = Thread.new do
12
+ @thread = Thread.new do
13
13
  Boatman.run
14
14
  end
15
15
  sleep 2
16
- thread.exit
16
+ @thread.exit
17
17
  end
18
18
 
19
19
  it "should move based on filename ending" do
@@ -96,6 +96,16 @@ describe "Moving new files from one location to another" do
96
96
  File.exist?(@working_directory + '/tmp/destination/datafile.txt').should be_false
97
97
  end
98
98
 
99
+ it "should not raise and exception (and crash boatman) when a task raises and exception" do
100
+ FileUtils.touch(@working_directory + '/tmp/source/datafile.txt')
101
+
102
+ boatman = Boatman.load(["#{@working_directory}/invalid_directory.yml", @working_directory])
103
+ run_boatman
104
+
105
+ # nil status indicates an exception was thrown
106
+ @thread.status.should_not be_nil
107
+ end
108
+
99
109
  after(:each) do
100
110
  FileUtils.rm_rf(@working_directory + '/tmp')
101
111
  end
@@ -0,0 +1,7 @@
1
+ source_folder.check_every 1.second do
2
+ age :greater_than => 0.minutes
3
+
4
+ files_ending_with "txt" do |file|
5
+ copy file, :to => destination_folder
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ tasks:
2
+ - invalid_directory.rb
3
+ directories:
4
+ source_folder: tmp/nonexistent_source
5
+ destination_folder: tmp/destination
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: boatman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 3
9
+ version: 0.1.3
5
10
  platform: ruby
6
11
  authors:
7
12
  - Bruz Marzolf
@@ -9,19 +14,23 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2010-01-07 00:00:00 -08:00
17
+ date: 2011-04-19 00:00:00 -07:00
13
18
  default_executable: boatman
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: rspec
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
20
24
  requirements:
21
25
  - - ">="
22
26
  - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 2
30
+ - 9
23
31
  version: 1.2.9
24
- version:
32
+ type: :development
33
+ version_requirements: *id001
25
34
  description: ""
26
35
  email: bmarzolf@systemsbiology.org
27
36
  executables:
@@ -33,12 +42,12 @@ extra_rdoc_files:
33
42
  - README.rdoc
34
43
  files:
35
44
  - .document
36
- - .gitignore
37
45
  - LICENSE
38
46
  - README.rdoc
39
47
  - Rakefile
40
48
  - VERSION
41
49
  - bin/boatman
50
+ - boatman.gemspec
42
51
  - lib/boatman.rb
43
52
  - lib/boatman/copyable.rb
44
53
  - lib/boatman/ext/class.rb
@@ -57,6 +66,8 @@ files:
57
66
  - spec/data/filename_regexp.yml
58
67
  - spec/data/folder.rb
59
68
  - spec/data/folder.yml
69
+ - spec/data/invalid_directory.rb
70
+ - spec/data/invalid_directory.yml
60
71
  - spec/data/modify.rb
61
72
  - spec/data/modify.yml
62
73
  - spec/data/no_destination_folder.rb
@@ -70,37 +81,40 @@ homepage: http://github.com/bmarzolf/boatman
70
81
  licenses: []
71
82
 
72
83
  post_install_message:
73
- rdoc_options:
74
- - --charset=UTF-8
84
+ rdoc_options: []
85
+
75
86
  require_paths:
76
87
  - lib
77
88
  required_ruby_version: !ruby/object:Gem::Requirement
78
89
  requirements:
79
90
  - - ">="
80
91
  - !ruby/object:Gem::Version
92
+ segments:
93
+ - 0
81
94
  version: "0"
82
- version:
83
95
  required_rubygems_version: !ruby/object:Gem::Requirement
84
96
  requirements:
85
97
  - - ">="
86
98
  - !ruby/object:Gem::Version
99
+ segments:
100
+ - 0
87
101
  version: "0"
88
- version:
89
102
  requirements: []
90
103
 
91
104
  rubyforge_project:
92
- rubygems_version: 1.3.5
105
+ rubygems_version: 1.3.6
93
106
  signing_key:
94
107
  specification_version: 3
95
108
  summary: Ruby DSL for ferrying around and manipulating files
96
109
  test_files:
97
- - spec/spec_helper.rb
98
110
  - spec/boatman_spec.rb
99
- - spec/data/rename.rb
111
+ - spec/data/copy_exception.rb
100
112
  - spec/data/filename_ending.rb
101
- - spec/data/no_destination_folder.rb
102
- - spec/data/filename_regexp.rb
103
- - spec/data/modify.rb
104
113
  - spec/data/filename_ending_regexp.rb
114
+ - spec/data/filename_regexp.rb
105
115
  - spec/data/folder.rb
106
- - spec/data/copy_exception.rb
116
+ - spec/data/invalid_directory.rb
117
+ - spec/data/modify.rb
118
+ - spec/data/no_destination_folder.rb
119
+ - spec/data/rename.rb
120
+ - spec/spec_helper.rb
data/.gitignore DELETED
@@ -1,21 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC