boatman 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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