checksummer 0.1.2 → 0.1.4

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/README.rdoc CHANGED
@@ -1,6 +1,58 @@
1
1
  = checksummer
2
+ checksummer replaces all files in a given directory with symlinks to files named and hashed by MD5 checksum of each file.
2
3
 
3
- Description goes here.
4
+ = Usage
5
+
6
+ checksummer <directory_to_checksum> <directory_to_write_data> [OPTIONS]
7
+
8
+ Options:
9
+ --sleep TIME Sleep for TIME milliseconds after each symlink operation (for fair IO)
10
+
11
+ = Example
12
+
13
+ checksummer /music /data
14
+
15
+ == Jay-Z - The Blueprint 3
16
+ source destination
17
+ /music/jay-z/the_blueprint_3/01-what_we_talkin_about.mp3 => /data/3/6/a/5/36a5642b1613bf5589cb479332bddca6
18
+ /music/jay-z/the_blueprint_3/02-thank_you.mp3 => /data/5/1/e/8/51e896f5544b9372edbdf7ec853892a1
19
+ /music/jay-z/the_blueprint_3/03-doa.mp3 => /data/1/e/7/a/1e7aa593020b60e6b45d0178e49d0413 (duplicate)
20
+ /music/jay-z/the_blueprint_3/04-run_this_town.mp3 => /data/1/f/4/5/1f454817ee460e28ede71b5e5ee902bd (duplicate)
21
+ /music/jay-z/the_blueprint_3/05-empire_state_of_mind.mp3 => /data/4/9/d/3/49d39143e0c42e4c2b852f604938c0d0 (duplicate)
22
+ /music/jay-z/the_blueprint_3/06-real_as_it_gets.mp3 => /data/9/8/8/d/988d10054f0eceb5def18bbb2c453557
23
+ /music/jay-z/the_blueprint_3/07-on_to_the_next_one.mp3 => /data/e/f/8/0/ef80c8b3560b5e1c15c919f354d226f8
24
+ /music/jay-z/the_blueprint_3/08-off_that.mp3 => /data/3/6/a/8/36a8152e0d98ccd6a375a8ab489cd4a1
25
+ /music/jay-z/the_blueprint_3/09-a_star_is_born.mp3 => /data/4/f/0/f/4f0f8253196a98fb54bed89a3768fb8b
26
+ /music/jay-z/the_blueprint_3/10-venus_vs_mars.mp3 => /data/3/6/1/c/361cba2aaa0d42bc376187a49448fa45
27
+ /music/jay-z/the_blueprint_3/11-already_home.mp3 => /data/d/4/a/7/d4a7756791dbd6df6514c84262b9bb18
28
+ /music/jay-z/the_blueprint_3/12-hate.mp3 => /data/4/a/6/d/4a6d2a9d04778ead9b04d7f45be1e6bd
29
+ /music/jay-z/the_blueprint_3/13-reminder.mp3 => /data/c/e/7/4/ce74f6184af8acc3af232df9b9335a76
30
+ /music/jay-z/the_blueprint_3/14-so_ambitious.mp3 => /data/0/d/6/1/0d6140d1a1c681b1f9f5eba7dee523e9
31
+ /music/jay-z/the_blueprint_3/15-young_forever.mp3 => /data/f/0/2/1/f0212f638eea55b9d5815515d40e9787
32
+
33
+ == Jay-Z - The Hits Collection Volume One
34
+ source destination
35
+ /music/jay-z/the_hits_collection_volume_one/01-public_service_announcement_(interlude).mp3 => /data/a/c/1/a/ac1a8c0df8971e732f034a2c6efa6fc1
36
+ /music/jay-z/the_hits_collection_volume_one/02-run_this_town.mp3 => /data/1/f/4/5/1f454817ee460e28ede71b5e5ee902bd (duplicate)
37
+ /music/jay-z/the_hits_collection_volume_one/03-03_bonnie_&_clyde.mp3 => /data/d/9/6/5/d9659ed413e0be456c35521639953724
38
+ /music/jay-z/the_hits_collection_volume_one/04-encore.mp3 => /data/c/7/c/e/c7ce40508cb1cacf56cbd671bd1adfb8
39
+ /music/jay-z/the_hits_collection_volume_one/05-i_just_wanna_love_u_(give_it_2_me).mp3 => /data/e/1/9/f/e19fa1483b208e75792b30d8562aaed0
40
+ /music/jay-z/the_hits_collection_volume_one/06-izzo_(hova).mp3 => /data/1/a/a/a/1aaabf78c9d8e30745b3fc8b2e87e285
41
+ /music/jay-z/the_hits_collection_volume_one/07-doa_(death_of_auto-tune).mp3 => /data/1/e/7/a/1e7aa593020b60e6b45d0178e49d0413 (duplicate)
42
+ /music/jay-z/the_hits_collection_volume_one/08-99_problems.mp3 => /data/7/6/b/6/76b689ae2f65bc44340a4bc2831cd559
43
+ /music/jay-z/the_hits_collection_volume_one/09-empire_state_of_mind.mp3 => /data/4/9/d/3/49d39143e0c42e4c2b852f604938c0d0 (duplicate)
44
+ /music/jay-z/the_hits_collection_volume_one/10-dirt_off_your_shoulder.mp3 => /data/3/2/c/5/32c5218d1a460a6257ab6b7aad23add9
45
+ /music/jay-z/the_hits_collection_volume_one/11-hard_knock_life_(ghetto_anthem).mp3 => /data/3/5/9/9/3599648c6dfba16787a0f27b2593c624
46
+ /music/jay-z/the_hits_collection_volume_one/12-show_me_what_you_got.mp3 => /data/1/a/3/8/1a38f265b1e40d5fc7e1c1814eecc887
47
+ /music/jay-z/the_hits_collection_volume_one/13-roc_boys_(and_the_winner_is).mp3 => /data/f/8/7/5/f875b6de8e2f7fd5366a209a1ec225c2
48
+ /music/jay-z/the_hits_collection_volume_one/14-big_pimpin.mp3 => /data/e/9/e/b/e9ebaa49726d7ac990c4eb57fc8eee59
49
+
50
+ = Advantages
51
+
52
+ * Save space: dulicate files are replaced with symlinks to one file
53
+ * Partition data uniformly on multiple disks:
54
+ /data/[0-8] could be symlinked to e.g. /dev/disk1
55
+ /data/[9-f] could be symlinked to e.g. /dev/disk2
4
56
 
5
57
  == Contributing to checksummer
6
58
 
data/Rakefile CHANGED
@@ -13,7 +13,7 @@ require 'jeweler'
13
13
  Jeweler::Tasks.new do |gem|
14
14
  # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
15
  gem.name = "checksummer"
16
- gem.homepage = "http://github.com/tobstarr/checksummer"
16
+ gem.homepage = "http://github.com/dynport/checksummer"
17
17
  gem.license = "MIT"
18
18
  gem.summary = %Q{Replace files with links to md5 files}
19
19
  gem.description = %Q{Replace files with links to md5 files}
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.1.4
data/checksummer.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{checksummer}
8
- s.version = "0.1.2"
8
+ s.version = "0.1.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tobias Schwab"]
12
- s.date = %q{2011-01-26}
12
+ s.date = %q{2011-01-29}
13
13
  s.default_executable = %q{checksummer}
14
14
  s.description = %q{Replace files with links to md5 files}
15
15
  s.email = %q{tobias.schwab@dynport.de}
@@ -37,7 +37,7 @@ Gem::Specification.new do |s|
37
37
  "spec/checksummer_spec.rb",
38
38
  "spec/spec_helper.rb"
39
39
  ]
40
- s.homepage = %q{http://github.com/tobstarr/checksummer}
40
+ s.homepage = %q{http://github.com/dynport/checksummer}
41
41
  s.licenses = ["MIT"]
42
42
  s.require_paths = ["lib"]
43
43
  s.rubygems_version = %q{1.3.7}
@@ -46,7 +46,9 @@ class ChecksummerFile
46
46
  else
47
47
  :symlinked
48
48
  end
49
+ mtime = File.mtime(path)
49
50
  FileUtils.ln_sf(new_path, path)
51
+ FileUtils.touch(path, :mtime => mtime)
50
52
  status
51
53
  else
52
54
  :was_symlink
@@ -36,14 +36,17 @@ describe ChecksummerFile do
36
36
 
37
37
  describe "#checksum_to!" do
38
38
  let(:file) { ChecksummerFile.new(:path => "/some/text.csv") }
39
+ let(:time) { Time.local(2010, 9, 10, 11, 12, 13) }
39
40
  let(:md5) { "fde8dad8ea43640b00cdd1e92e532ca9" }
40
41
 
41
42
  before(:each) do
42
43
  FileUtils.stub!(:cp).and_return true
43
44
  FileUtils.stub!(:mkdir_p)
45
+ FileUtils.stub!(:touch)
44
46
  FileUtils.stub(:ln_sf).and_return true
45
47
  File.stub!(:exists?).and_return false
46
48
  File.stub(:symlink?).and_return false
49
+ File.stub!(:mtime).and_return time
47
50
  file.stub!(:md5).and_return md5
48
51
  end
49
52
 
@@ -82,6 +85,11 @@ describe ChecksummerFile do
82
85
  it "returns :copied when copied" do
83
86
  file.checksum_to!("/tmp/data").should == :copied
84
87
  end
88
+
89
+ it "changes the mtime of the symlink to the mtime of the original file" do
90
+ FileUtils.should_receive(:touch).with("/some/text.csv", :mtime => time)
91
+ file.checksum_to!("/tmp/data")
92
+ end
85
93
  end
86
94
 
87
95
  describe "with the file being checksummed already" do
@@ -107,6 +115,11 @@ describe ChecksummerFile do
107
115
  it "returns :symlinked" do
108
116
  file.checksum_to!("/tmp/data").should == :symlinked
109
117
  end
118
+
119
+ it "changes the mtime of the symlink to the mtime of the original file" do
120
+ FileUtils.should_receive(:touch).with("/some/text.csv", :mtime => time)
121
+ file.checksum_to!("/tmp/data")
122
+ end
110
123
  end
111
124
 
112
125
  describe "with the file being a symlink" do
@@ -132,6 +145,11 @@ describe ChecksummerFile do
132
145
  it "returns :exists" do
133
146
  file.checksum_to!("/tmp/data").should == :was_symlink
134
147
  end
148
+
149
+ it "changes the mtime of the symlink to the mtime of the original file" do
150
+ FileUtils.should_not_receive(:touch)
151
+ file.checksum_to!("/tmp/data")
152
+ end
135
153
  end
136
154
  end
137
155
 
@@ -151,29 +151,39 @@ describe "Checksummer" do
151
151
  describe "#integration" do
152
152
  let(:root) { File.expand_path("tmp", File.dirname(__FILE__)) }
153
153
 
154
+ def time_for_index(index)
155
+ Time.local(2010, 11, 12, 13, 14, index)
156
+ end
157
+
154
158
  before(:each) do
155
159
  FileUtils.rm_rf(root)
156
160
  FileUtils.mkdir_p("#{root}/source")
157
161
  FileUtils.mkdir_p("#{root}/data")
158
162
  FileUtils.mkdir_p("#{root}/data/a/b/c/d/abcdefg")
159
163
  1.upto(3).each do |i|
160
- File.open("#{root}/source/file#{i}.txt", "w") { |f| f.puts "file #{i}" }
164
+ path = "#{root}/source/file#{i}.txt"
165
+ File.open(path, "w") { |f| f.puts "file #{i}" }
166
+ FileUtils.touch("#{root}/source/file#{i}.txt", :mtime => time_for_index(i))
161
167
  end
162
168
  FileUtils.ln_sf("#{root}/data/a/b/c/d/abcdefg", "#{root}/source/file4.txt")
169
+ FileUtils.touch("#{root}/data/a/b/c/d/abcdefg", :mtime => time_for_index(4))
163
170
  end
164
171
 
165
172
  it "checksums all files" do
166
173
  cs = Checksummer.new("#{root}/data")
167
174
  cs.checksum_directory("#{root}/source")
168
- { "4/3/4/9/4349cfeff8e2eb74dffc369bb5fd084e" => "file2.txt", "9/c/3/8/9c38e8324dbf031557c89d53a39f0b26" => "file3.txt",
169
- "e/2/4/3/e243bb39c844b3543a7726576c869caf" => "file1.txt", "a/b/c/d/abcdefg" => "file4.txt"
170
- }.each do |data_file, original_file|
175
+ { "4/3/4/9/4349cfeff8e2eb74dffc369bb5fd084e" => ["file2.txt", time_for_index(2)],
176
+ "9/c/3/8/9c38e8324dbf031557c89d53a39f0b26" => ["file3.txt", time_for_index(3)],
177
+ "e/2/4/3/e243bb39c844b3543a7726576c869caf" => ["file1.txt", time_for_index(1)],
178
+ "a/b/c/d/abcdefg" => ["file4.txt", time_for_index(4)]
179
+ }.each do |data_file, (original_file, mtime)|
171
180
  original = Pathname.new("#{root}/source/#{original_file}")
172
181
  data = Pathname.new("#{root}/data/#{data_file}")
173
182
  File.should be_exists(original.to_s)
174
183
  File.should be_exists(data.to_s)
175
184
  original.realpath.to_s.should match(/\//)
176
185
  original.realpath.should == data
186
+ File.mtime(original).should == mtime
177
187
  end
178
188
  end
179
189
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 2
9
- version: 0.1.2
8
+ - 4
9
+ version: 0.1.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - Tobias Schwab
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-26 00:00:00 +01:00
17
+ date: 2011-01-29 00:00:00 +01:00
18
18
  default_executable: checksummer
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -142,7 +142,7 @@ files:
142
142
  - spec/checksummer_spec.rb
143
143
  - spec/spec_helper.rb
144
144
  has_rdoc: true
145
- homepage: http://github.com/tobstarr/checksummer
145
+ homepage: http://github.com/dynport/checksummer
146
146
  licenses:
147
147
  - MIT
148
148
  post_install_message:
@@ -155,7 +155,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
155
155
  requirements:
156
156
  - - ">="
157
157
  - !ruby/object:Gem::Version
158
- hash: -3983138821397024121
158
+ hash: 3104515524890018189
159
159
  segments:
160
160
  - 0
161
161
  version: "0"