bagit 0.4.2 → 0.4.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.
@@ -3,21 +3,19 @@ require 'digest/sha1'
3
3
  require 'digest/md5'
4
4
 
5
5
  module BagIt
6
-
7
6
  # Requires response to bag_dir, tag_files, bag_files
8
7
  module Manifest
9
8
  def encode_filename(s)
10
- s = s.gsub(/\r/, '%0D')
11
- s = s.gsub(/\n/,'%0A')
12
- return s
9
+ s = s.gsub(/\r/, '%0D')
10
+ s = s.gsub(/\n/, '%0A')
11
+ s
13
12
  end
14
13
 
15
-
16
14
  # All tag files that are bag manifest files (manifest-[algorithm].txt)
17
15
  def manifest_files
18
- files = Dir[File.join(@bag_dir, '*')].select { |f|
19
- File.file? f and File.basename(f) =~ /^manifest-.*.txt$/
20
- }
16
+ files = Dir[File.join(@bag_dir, '*')].select do |f|
17
+ File.file?(f) && File.basename(f) =~ /^manifest-.*.txt$/
18
+ end
21
19
  files
22
20
  end
23
21
 
@@ -28,31 +26,34 @@ module BagIt
28
26
 
29
27
  # Generate manifest files for all the bag files
30
28
  def manifest!(algo: 'default')
31
-
32
29
  # nuke all the existing manifest files
33
- manifest_files.each { |f| FileUtils::rm f }
30
+ manifest_files.each { |f| FileUtils.rm f }
34
31
 
35
32
  # manifest each tag file for each algorithm
36
33
  bag_files.each do |f|
37
34
  rel_path = encode_filename(Pathname.new(f).relative_path_from(Pathname.new(bag_dir)).to_s)
38
35
 
39
- case algo
40
- when 'sha1'
41
- write_sha1(f, rel_path)
42
- when 'md5'
43
- write_md5(f, rel_path)
44
- when 'sha256'
45
- write_sha256(f, rel_path)
46
- when 'sha512'
47
- write_sha256(f, rel_path)
48
- when 'default'
49
- write_sha1(f, rel_path)
50
- write_md5(f, rel_path)
51
- end
36
+ write_checksum(checksum_algo: algo, relative_path: rel_path, file: f)
52
37
  end
53
38
  tagmanifest!
54
39
  end
55
40
 
41
+ def write_checksum(checksum_algo:, relative_path:, file:)
42
+ case checksum_algo
43
+ when 'sha1'
44
+ write_sha1(file, relative_path)
45
+ when 'md5'
46
+ write_md5(file, relative_path)
47
+ when 'sha256'
48
+ write_sha256(file, relative_path)
49
+ when 'sha512'
50
+ write_sha256(file, relative_path)
51
+ when 'default'
52
+ write_sha1(file, relative_path)
53
+ write_md5(file, relative_path)
54
+ end
55
+ end
56
+
56
57
  def write_sha1(f, rel_path)
57
58
  sha1 = Digest::SHA1.file f
58
59
  File.open(manifest_file(:sha1), 'a') { |io| io.puts "#{sha1} #{rel_path}" }
@@ -75,9 +76,9 @@ module BagIt
75
76
 
76
77
  # All tag files that are bag manifest files (tagmanifest-[algorithm].txt)
77
78
  def tagmanifest_files
78
- files = Dir[File.join(@bag_dir, '*')].select { |f|
79
- File.file? f and File.basename(f) =~ /^tagmanifest-.*.txt$/
80
- }
79
+ files = Dir[File.join(@bag_dir, '*')].select do |f|
80
+ File.file?(f) && File.basename(f) =~ /^tagmanifest-.*.txt$/
81
+ end
81
82
  files
82
83
  end
83
84
 
@@ -88,12 +89,11 @@ module BagIt
88
89
 
89
90
  # Generate manifest files for all the tag files (except the tag
90
91
  # manifest files)
91
- def tagmanifest!(tags=nil)
92
-
93
- tags = tag_files if tags == nil
92
+ def tagmanifest!(tags = nil)
93
+ tags = tag_files if tags.nil?
94
94
 
95
95
  # nuke all the existing tagmanifest files
96
- tagmanifest_files.each { |f| FileUtils::rm f }
96
+ tagmanifest_files.each { |f| FileUtils.rm f }
97
97
 
98
98
  # ensure presence of manfiest files
99
99
  manifest_files.each do |manifest|
@@ -111,29 +111,28 @@ module BagIt
111
111
  tag_files
112
112
  end
113
113
 
114
- def add_tag_file(path, src_path=nil)
115
-
114
+ def add_tag_file(path, src_path = nil)
116
115
  f = File.join(@bag_dir, path)
117
116
  raise "Tag file already in manifest: #{path}" if tag_files.include?(f)
118
117
 
119
- if not File.exist? f
120
- FileUtils::mkdir_p File.dirname(f)
118
+ if !File.exist? f
119
+ FileUtils.mkdir_p File.dirname(f)
121
120
 
122
121
  # write file
123
122
  if src_path.nil?
124
123
  File.open(f, 'w') { |io| yield io }
125
124
  else
126
- FileUtils::cp src_path, f
125
+ FileUtils.cp src_path, f
127
126
  end
128
127
  # this adds the manifest and bag info files on initial creation
129
128
  # it must only run when the manifest doesn't already exist or it will
130
129
  # infinitely recall add_tag_file. Better way of doing this?
131
130
  tagmanifest!
132
- elsif not src_path.nil?
131
+ elsif !src_path.nil?
133
132
  raise "Tag file already exists, will not overwrite: #{path}\n Use add_tag_file(path) to add an existing tag file."
134
133
  end
135
134
 
136
- data = File.open(f) { |io| io.read }
135
+ data = File.open(f, &:read)
137
136
  rel_path = Pathname.new(f).relative_path_from(Pathname.new(bag_dir)).to_s
138
137
 
139
138
  # sha1
@@ -157,7 +156,7 @@ module BagIt
157
156
  filepath = File.join(@bag_dir, path)
158
157
  raise "Tag file does not exist: #{path}" unless File.exist? filepath
159
158
  remove_tag_file(path) if tag_files.include?(path)
160
- FileUtils::rm filepath
159
+ FileUtils.rm filepath
161
160
  end
162
161
 
163
162
  # Returns true if all present manifested files' message digests
@@ -167,7 +166,7 @@ module BagIt
167
166
  # extract the algorithm
168
167
  mf =~ /manifest-(.+).txt$/
169
168
 
170
- algo = case $1
169
+ algo = case Regexp.last_match(1)
171
170
  when /sha1/i
172
171
  Digest::SHA1
173
172
  when /md5/i
@@ -177,23 +176,19 @@ module BagIt
177
176
  end
178
177
 
179
178
  # check it, an unknown algorithm is always true
180
- unless algo == :unknown
181
- lines = File.open(mf) { |io| io.readlines }
179
+ if algo == :unknown
180
+ true
181
+ else
182
+ lines = File.open(mf, &:readlines)
182
183
 
183
184
  lines.all? do |line|
184
- manifested_digest, path = line.chomp.split /\s+/, 2
185
+ manifested_digest, path = line.chomp.split(/\s+/, 2)
185
186
  actual_digest = File.open(File.join(@bag_dir, path)) { |io| algo.hexdigest io.read }
186
187
  actual_digest == manifested_digest
187
188
  end
188
189
 
189
- else
190
- true
191
190
  end
192
-
193
191
  end
194
-
195
192
  end
196
-
197
193
  end
198
-
199
194
  end
@@ -1,6 +1,5 @@
1
1
  # Some mixed in functionality for String
2
2
  class String
3
-
4
3
  # Wrap a string to lines of a specified width. All existing newlines
5
4
  # are not guaranteed to be preserved
6
5
  def wrap(width)
@@ -11,7 +10,6 @@ class String
11
10
  else
12
11
  s
13
12
  end
14
-
15
13
  end
16
14
 
17
15
  # Indent each line of a string by n spaces
@@ -20,8 +18,8 @@ class String
20
18
  gsub '\n', "\n#{indent}"
21
19
  end
22
20
 
23
- # Colorize logs
24
- def color(color_code)
21
+ # Colorize logs
22
+ def color(color_code)
25
23
  "\e[#{color_code}m#{self}\e[0m"
26
24
  end
27
25
 
@@ -4,29 +4,26 @@ require 'cgi'
4
4
  require 'logger'
5
5
 
6
6
  module BagIt
7
-
8
7
  class Bag
9
8
  include Validatable
10
- validates_true_for :consistency, :logic => Proc.new { consistent? }
11
- validates_true_for :completeness, :logic => Proc.new { complete? }
9
+ validates_true_for :consistency, logic: proc { consistent? }
10
+ validates_true_for :completeness, logic: proc { complete? }
12
11
  end
13
12
 
14
13
  module Validity
15
14
  def decode_filename(s)
16
- s = s.gsub('%0D',"\r")
17
- s = s.gsub('%0A',"\n")
18
- return s
15
+ s = s.gsub('%0D', "\r")
16
+ s = s.gsub('%0A', "\n")
17
+ s
19
18
  end
20
-
19
+
21
20
  # Return true if the manifest cover all files and all files are
22
21
  # covered.
23
22
  def complete?
24
23
  logger = Logger.new(STDOUT)
25
24
 
26
- if manifest_files == []
27
- errors.add :completeness, "there are no manifest files"
28
- end
29
-
25
+ errors.add :completeness, "there are no manifest files" if manifest_files == []
26
+
30
27
  unmanifested_files.each do |file|
31
28
  logger.error("#{file} is present but not manifested".red)
32
29
  errors.add :completeness, "#{file} is present but not manifested"
@@ -44,38 +41,39 @@ module BagIt
44
41
  errors.on(:completeness).nil?
45
42
  end
46
43
 
44
+ def manifest_type(type)
45
+ case type
46
+ when /sha1/i
47
+ Digest::SHA1
48
+ when /md5/i
49
+ Digest::MD5
50
+ when /sha256/i
51
+ Digest::SHA256
52
+ when /sha384/i
53
+ Digest::SHA384
54
+ when /sha512/i
55
+ Digest::SHA512
56
+ else
57
+ raise ArgumentError, "Algorithm #{manifest_type} is not supported."
58
+ end
59
+ end
60
+
47
61
  # Return true if all manifested files message digests match.
48
62
  def consistent?
49
- (manifest_files|tagmanifest_files).each do |mf|
63
+ (manifest_files | tagmanifest_files).each do |mf|
50
64
  # get the algorithm implementation
51
65
  File.basename(mf) =~ /manifest-(.+).txt$/
52
- manifest_type = $1
53
- algo = case manifest_type
54
- when /sha1/i
55
- Digest::SHA1
56
- when /md5/i
57
- Digest::MD5
58
- when /sha256/i
59
- Digest::SHA256
60
- when /sha384/i
61
- Digest::SHA384
62
- when /sha512/i
63
- Digest::SHA512
64
- else
65
- raise ArgumentError.new("Algorithm #{manifest_type} is not supported.")
66
- end
66
+ type = Regexp.last_match(1)
67
+ algo = manifest_type(type)
67
68
  # Check every file in the manifest
68
69
  File.open(mf) do |io|
69
70
  io.each_line do |line|
70
- expected, path = line.chomp.split /\s+/, 2
71
+ expected, path = line.chomp.split(/\s+/, 2)
71
72
  file = File.join(bag_dir, decode_filename(path))
72
73
 
73
- if File.exist? file
74
- actual = algo.file(file).hexdigest
75
- if expected.downcase != actual
76
- errors.add :consistency, "expected #{file} to have #{algo}: #{expected}, actual is #{actual}"
77
- end
78
- end
74
+ next unless File.exist? file
75
+ actual = algo.file(file).hexdigest
76
+ errors.add :consistency, "expected #{file} to have #{algo}: #{expected}, actual is #{actual}" if expected.downcase != actual
79
77
  end
80
78
  end
81
79
  end
@@ -89,59 +87,53 @@ module BagIt
89
87
  end
90
88
 
91
89
  protected
92
-
93
- # Returns all files in the instance that are not manifested
94
- def unmanifested_files
95
- mfs = manifested_files.map { |f| File.join bag_dir, f }
96
- bag_files.reject { |f| mfs.member? f }
97
- end
98
90
 
99
- # Returns a list of manifested files that are not present
100
- def empty_manifests
101
- bfs = bag_files
102
- manifested_files.reject { |f| bfs.member? File.join(bag_dir, f) }
103
- end
104
- # Returns a list of tag manifested files that are not present
105
- def tag_empty_manifests
106
- empty = []
107
- tag_manifested_files.each do |f|
108
- if !File.exists?(File.join(bag_dir,f))
109
- empty.push f
110
- end
91
+ # Returns all files in the instance that are not manifested
92
+ def unmanifested_files
93
+ mfs = manifested_files.map { |f| File.join bag_dir, f }
94
+ bag_files.reject { |f| mfs.member? f }
111
95
  end
112
- return empty
113
- end
114
- # Returns a list of all files present in the manifest files
115
- def manifested_files
116
96
 
117
- manifest_files.inject([]) do |acc, mf|
97
+ # Returns a list of manifested files that are not present
98
+ def empty_manifests
99
+ bfs = bag_files
100
+ manifested_files.reject { |f| bfs.member? File.join(bag_dir, f) }
101
+ end
118
102
 
119
- files = File.open(mf) do |io|
103
+ # Returns a list of tag manifested files that are not present
104
+ def tag_empty_manifests
105
+ empty = []
106
+ tag_manifested_files.each do |f|
107
+ empty.push f unless File.exist?(File.join(bag_dir, f))
108
+ end
109
+ empty
110
+ end
120
111
 
121
- io.readlines.map do |line|
122
- digest, path = line.chomp.split /\s+/, 2
123
- decode_filename(path)
112
+ # Returns a list of all files present in the manifest files
113
+ def manifested_files
114
+ manifest_files.inject([]) do |acc, mf|
115
+ files = File.open(mf) do |io|
116
+ io.readlines.map do |line|
117
+ _digest, path = line.chomp.split(/\s+/, 2)
118
+ decode_filename(path)
119
+ end
124
120
  end
125
121
 
122
+ (acc + files).uniq
126
123
  end
127
-
128
- (acc + files).uniq
129
124
  end
130
125
 
131
- end
132
- # Returns a list of all files in the tag manifest files
133
- def tag_manifested_files
134
- tagmanifest_files.inject([]) do |acc, mf|
135
- files = File.open(mf) do |io|
136
- io.readlines.map do |line|
137
- digest, path = line.chomp.split /\s+/, 2
138
- path
126
+ # Returns a list of all files in the tag manifest files
127
+ def tag_manifested_files
128
+ tagmanifest_files.inject([]) do |acc, mf|
129
+ files = File.open(mf) do |io|
130
+ io.readlines.map do |line|
131
+ _digest, path = line.chomp.split(/\s+/, 2)
132
+ path
133
+ end
139
134
  end
135
+ (acc + files).uniq
140
136
  end
141
- (acc+files).uniq
142
137
  end
143
- end
144
-
145
138
  end
146
-
147
139
  end
@@ -1,3 +1,3 @@
1
1
  module BagIt
2
- VERSION = "0.4.2"
2
+ VERSION = "0.4.3".freeze
3
3
  end
@@ -2,31 +2,31 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  # based on v0.96 http://www.cdlib.org/inside/diglib/bagit/bagitspec.html
5
- describe BagIt::Bag do
5
+ RSpec.describe BagIt::Bag do
6
6
  describe 'empty bag' do
7
- before(:each) do
7
+ before do
8
8
  @sandbox = Sandbox.new
9
9
  # make the bag
10
10
  @bag_path = File.join @sandbox.to_s, 'the_bag'
11
- @bag = BagIt::Bag.new @bag_path
11
+ @bag = described_class.new @bag_path
12
12
  end
13
13
 
14
- after(:each) do
14
+ after do
15
15
  @sandbox.cleanup!
16
16
  end
17
17
 
18
- it "should be empty" do
18
+ it "is empty" do
19
19
  expect(@bag).to be_empty
20
20
  end
21
21
  end
22
22
 
23
23
  describe 'bag with files' do
24
- before(:each) do
24
+ before do
25
25
  @sandbox = Sandbox.new
26
26
 
27
27
  # make the bag
28
28
  @bag_path = File.join @sandbox.to_s, 'the_bag'
29
- @bag = BagIt::Bag.new @bag_path
29
+ @bag = described_class.new @bag_path
30
30
 
31
31
  # add some files
32
32
  File.open('/dev/urandom') do |rio|
@@ -37,47 +37,49 @@ describe BagIt::Bag do
37
37
  end
38
38
  end
39
39
 
40
- after(:each) do
40
+ after do
41
41
  @sandbox.cleanup!
42
42
  end
43
43
 
44
- it "should be a directory" do
44
+ it "is a directory" do
45
45
  expect(File.directory?(@bag_path)).to be true
46
46
  end
47
47
 
48
- it "should not be empty" do
48
+ it "is not be empty" do
49
49
  expect(@bag).not_to be_empty
50
50
  end
51
51
 
52
- it "should have a sub-directory called data" do
52
+ it "has a sub-directory called data" do
53
53
  data_path = File.join @bag_path, 'data'
54
54
  expect(File.directory?(data_path)).to be true
55
55
  end
56
56
 
57
57
  describe "#add_file" do
58
- it "should allow addition of files via io" do
58
+ it "allows addition of files via io" do
59
59
  @bag.add_file("foo") { |io| io.puts 'all alone' }
60
60
  expect(File.join(@bag_path, "data", "foo")).to exist_on_fs
61
61
  end
62
62
 
63
- it "should allow addition of files via copy" do
63
+ it "allows addition of files via copy" do
64
64
  src_path = File.join @sandbox.to_s, 'somefile'
65
65
  File.open(src_path, 'w') { |io| io.puts "something" }
66
66
  @bag.add_file("foo", src_path) { |io| io.puts 'all alone' }
67
67
  expect(File.join(@bag_path, "data", "foo")).to exist_on_fs
68
68
  end
69
69
 
70
- it "should allow addition of files with deep paths" do
70
+ it "allows addition of files with deep paths" do
71
71
  @bag.add_file("deep/dir/structure/file") { |io| io.puts 'all alone' }
72
72
  expect(File.join(@bag_path, "data", "deep/dir/structure/file")).to exist_on_fs
73
73
  end
74
74
 
75
- it "should not allow overwriting of files" do
76
- expect { @bag.add_file("file-0-💩
77
- ") { |io| io.puts 'overwrite!' } }.to raise_error(RuntimeError)
75
+ it "does not allow overwriting of files" do
76
+ expect do
77
+ @bag.add_file("file-0-💩
78
+ ") { |io| io.puts 'overwrite!' }
79
+ end.to raise_error(RuntimeError)
78
80
  end
79
81
 
80
- it "should update payload oxum" do
82
+ it "updates the payload oxum" do
81
83
  oxum_count = @bag.bag_info["Payload-Oxum"].split('.')[1].to_i
82
84
  @bag.add_file("foo") { |io| io.puts 'all alone' }
83
85
  expect(@bag.bag_info["Payload-Oxum"].split('.')[1].to_i).to eq(oxum_count + 1)
@@ -85,14 +87,14 @@ describe BagIt::Bag do
85
87
  end
86
88
 
87
89
  describe "#remove_file" do
88
- it "should raise an error when deleing non existant files" do
90
+ it "raises an error when deleing non existant files" do
89
91
  expect { @bag.remove_file("file-x") }.to raise_error(RuntimeError)
90
92
  end
91
93
  end
92
94
 
93
95
  describe "#get" do
94
96
  describe "file not in bag" do
95
- it "should return nil" do
97
+ it "returns nil" do
96
98
  expect(@bag.get('foobar')).to be_nil
97
99
  end
98
100
  end
@@ -104,15 +106,15 @@ describe BagIt::Bag do
104
106
  @file = @bag.get("foo")
105
107
  end
106
108
 
107
- it "should return an IO object for the given path" do
109
+ it "returns an IO object for the given path" do
108
110
  expect(@file).to be_a_kind_of(IO)
109
111
  end
110
112
 
111
- it "should have the same content as the file added" do
113
+ it "has the same content as the file added" do
112
114
  expect(@file.read).to eq(@contents)
113
115
  end
114
116
 
115
- it "should accept an optional leading slash or ./" do
117
+ it "accepts an optional leading slash or ./" do
116
118
  expect(@bag.get("/foo").read).to eq(@contents)
117
119
  expect(@bag.get("./foo").read).to eq(@contents)
118
120
  end
@@ -124,7 +126,7 @@ describe BagIt::Bag do
124
126
  @paths = @bag.paths
125
127
  end
126
128
 
127
- it "should return a non-empty Array of Strings" do
129
+ it "returns a non-empty Array of Strings" do
128
130
  expect(@paths).to be_a_kind_of(Array)
129
131
  expect(@paths).not_to be_empty
130
132
  @paths.each do |p|
@@ -132,25 +134,27 @@ describe BagIt::Bag do
132
134
  end
133
135
  end
134
136
 
135
- it "should return relative paths to all files in the data directory" do
136
- expect(@paths).to match_array((0..9).collect { |x| "file-#{x}-💩
137
- " })
137
+ it "returns relative paths to all files in the data directory" do
138
+ expect(@paths).to match_array((0..9).collect do |x|
139
+ "file-#{x}-💩
140
+ "
141
+ end)
138
142
  end
139
143
  end
140
144
 
141
145
  describe "#payload-oxum" do
142
- it "should return a valid oxum" do
146
+ it "returns a valid oxum" do
143
147
  expect(@bag.payload_oxum).to match(/^[0-9]+\.[0-9]+$/)
144
148
  end
145
149
 
146
- it "should accurately specify the number of payload files" do
150
+ it "accurately specifys the number of payload files" do
147
151
  @bag.add_tag_file('non-payload') { |f| f.puts "I shouldn't count in the oxum" }
148
152
  @bag.payload_oxum.split('.')[1] == @bag.bag_files.count
149
153
  end
150
154
  end
151
155
 
152
156
  describe "#gc!" do
153
- it "should clean up empty directories" do
157
+ it "cleans up empty directories" do
154
158
  f = File.join "1", "2", "3", "file"
155
159
  @bag.add_file(f) { |io| io.puts 'all alone' }
156
160
  @bag.remove_file f