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 +53 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/checksummer.gemspec +3 -3
- data/lib/checksummer_file.rb +2 -0
- data/spec/checksummer_file_spec.rb +18 -0
- data/spec/checksummer_spec.rb +14 -4
- metadata +5 -5
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
|
-
|
|
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/
|
|
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.
|
|
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.
|
|
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-
|
|
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/
|
|
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}
|
data/lib/checksummer_file.rb
CHANGED
|
@@ -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
|
|
data/spec/checksummer_spec.rb
CHANGED
|
@@ -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
|
-
|
|
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",
|
|
169
|
-
"
|
|
170
|
-
|
|
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
|
-
-
|
|
9
|
-
version: 0.1.
|
|
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-
|
|
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/
|
|
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:
|
|
158
|
+
hash: 3104515524890018189
|
|
159
159
|
segments:
|
|
160
160
|
- 0
|
|
161
161
|
version: "0"
|