bagit 0.3.5 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +2 -1
- data/.travis.yml +1 -2
- data/Gemfile +4 -2
- data/README.md +1 -1
- data/Rakefile +11 -8
- data/bagit.gemspec +25 -21
- data/bin/bagit +59 -63
- data/lib/bagit.rb +8 -6
- data/lib/bagit/bag.rb +43 -47
- data/lib/bagit/fetch.rb +23 -27
- data/lib/bagit/file.rb +11 -14
- data/lib/bagit/info.rb +39 -51
- data/lib/bagit/manifest.rb +72 -49
- data/lib/bagit/string.rb +6 -6
- data/lib/bagit/valid.rb +51 -57
- data/lib/bagit/version.rb +3 -1
- data/spec/bagit_spec.rb +59 -54
- data/spec/fetch_spec.rb +33 -38
- data/spec/manifest_spec.rb +107 -111
- data/spec/spec_helper.rb +12 -12
- data/spec/tag_info_spec.rb +101 -108
- data/spec/tag_spec.rb +47 -49
- data/spec/util/bagit_matchers.rb +5 -14
- data/spec/validation_spec.rb +108 -110
- metadata +50 -9
data/spec/manifest_spec.rb
CHANGED
@@ -1,148 +1,144 @@
|
|
1
|
-
#
|
2
|
-
require 'spec_helper'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
require "spec_helper"
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
5
|
+
describe BagIt::Bag do
|
6
|
+
describe "BagIt Manifests" do
|
7
|
+
before do
|
8
|
+
@sandbox = Sandbox.new
|
9
|
+
|
10
|
+
# make the bag
|
11
|
+
@bag_path = File.join @sandbox.to_s, "the_bag"
|
12
|
+
@bag = described_class.new @bag_path
|
13
|
+
|
14
|
+
# add some files
|
15
|
+
File.open("/dev/urandom") do |rio|
|
16
|
+
10.times do |n|
|
17
|
+
@bag.add_file("file-#{n}-💩
|
18
|
+
") { |io| io.write rio.read(16) }
|
19
|
+
@bag.add_tag_file("tag-#{n}") { |io| io.write rio.read(16) }
|
20
|
+
end
|
20
21
|
end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
22
|
end
|
26
23
|
|
27
|
-
|
28
|
-
|
29
|
-
after(:each) do
|
30
|
-
@sandbox.cleanup!
|
31
|
-
end
|
32
|
-
|
33
|
-
shared_examples_for "a manifest file" do
|
34
|
-
|
35
|
-
before do
|
36
|
-
pattern = File.join @bag_path, '*manifest-*.txt'
|
37
|
-
@manifest_files = Dir.glob pattern
|
24
|
+
after do
|
25
|
+
@sandbox.cleanup!
|
38
26
|
end
|
39
27
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
28
|
+
shared_examples_for "a manifest file" do
|
29
|
+
before do
|
30
|
+
pattern = File.join @bag_path, "*manifest-*.txt"
|
31
|
+
@manifest_files = Dir.glob pattern
|
32
|
+
end
|
44
33
|
|
45
|
-
|
46
|
-
|
47
|
-
|
34
|
+
it "has a valid algorithm in the name (at least md5 or sha1)" do
|
35
|
+
algorithms = @manifest_files.map { |mf|
|
36
|
+
mf =~ /manifest-(.*).txt$/
|
37
|
+
Regexp.last_match(1)
|
38
|
+
}
|
39
|
+
algorithms.each { |a| expect(a).to be_in("md5", "sha1") }
|
40
|
+
end
|
41
|
+
|
42
|
+
it "is not an empty file" do
|
43
|
+
@manifest_files.each { |mf| expect(File.size(mf)).not_to eq(0) }
|
44
|
+
end
|
48
45
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
46
|
+
it "only contains lines of the format CHECKSUM FILENAME" do
|
47
|
+
@manifest_files.each do |file|
|
48
|
+
File.open(file) do |io|
|
49
|
+
io.each_line { |line| expect(line).to match(/^[a-fA-F0-9]+\s+[^\s].+$/) }
|
50
|
+
end
|
53
51
|
end
|
54
52
|
end
|
55
|
-
end
|
56
53
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
54
|
+
it "validates after adding a file and remanifesting" do
|
55
|
+
@bag.add_file("newfile.txt") { |io| io.puts("new file to remanifest") }
|
56
|
+
@bag.manifest!
|
57
|
+
expect(@bag).to be_valid
|
58
|
+
end
|
61
59
|
end
|
62
60
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
before do
|
68
|
-
@bag.manifest!
|
69
|
-
end
|
61
|
+
describe "bag manifest files" do
|
62
|
+
before do
|
63
|
+
@bag.manifest!
|
64
|
+
end
|
70
65
|
|
71
|
-
|
66
|
+
it_behaves_like "a manifest file"
|
72
67
|
|
73
|
-
|
74
|
-
|
75
|
-
|
68
|
+
it "has a manifest file" do
|
69
|
+
expect(@bag.manifest_files).not_to be_empty
|
70
|
+
end
|
76
71
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
72
|
+
it "only contains bag files" do
|
73
|
+
@bag.manifest_files.each do |mf|
|
74
|
+
File.open(mf) do |io|
|
75
|
+
io.each_line do |line|
|
76
|
+
expect(line.chomp).to match(/^[a-f0-9]+\s+data\/[^\s].+$/)
|
77
|
+
end
|
82
78
|
end
|
83
79
|
end
|
84
80
|
end
|
85
81
|
end
|
86
82
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
before do
|
92
|
-
@bag.add_tag_file("test-tag") { |f| f.puts "all alone" }
|
93
|
-
end
|
83
|
+
describe "tag manifest files" do
|
84
|
+
before do
|
85
|
+
@bag.add_tag_file("test-tag") { |f| f.puts "all alone" }
|
86
|
+
end
|
94
87
|
|
95
|
-
|
88
|
+
it_should_behave_like "a manifest file"
|
96
89
|
|
97
|
-
|
98
|
-
|
99
|
-
end
|
100
|
-
it "should only contain tag files" do
|
101
|
-
@bag.tagmanifest_files.each do |mf|
|
102
|
-
File.open(mf) do |io|
|
103
|
-
io.each_line do |line|
|
104
|
-
expect(line.chomp).to match(/^[a-fA-F0-9]+\s+(?!data\/)[^\s].+$/)
|
105
|
-
end
|
106
|
-
end
|
90
|
+
it "has a tag manifest file" do
|
91
|
+
expect(@bag.tagmanifest_files).not_to be_empty
|
107
92
|
end
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
93
|
+
it "only contains tag files" do
|
94
|
+
@bag.tagmanifest_files.each do |mf|
|
95
|
+
File.open(mf) do |io|
|
96
|
+
io.each_line do |line|
|
97
|
+
expect(line.chomp).to match(/^[a-fA-F0-9]+\s+(?!data\/)[^\s].+$/)
|
98
|
+
end
|
99
|
+
end
|
115
100
|
end
|
116
101
|
end
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
102
|
+
it "contains manifest and bag info files" do
|
103
|
+
@bag.tagmanifest_files.each do |mf|
|
104
|
+
expect(File.open(mf).read).to include(File.basename(@bag.bag_info_txt_file))
|
105
|
+
expect(File.open(mf).read).to include(File.basename(@bag.bagit_txt_file))
|
106
|
+
@bag.manifest_files.each do |man|
|
107
|
+
expect(File.open(mf).read).to include(man)
|
108
|
+
end
|
122
109
|
end
|
123
110
|
end
|
124
|
-
|
125
|
-
describe "removing tracked files" do
|
126
|
-
before(:each) do
|
127
|
-
@bag.remove_tag_file "tag-1"
|
128
|
-
@bag.delete_tag_file "tag-2"
|
129
|
-
end
|
130
|
-
it "should still have the untracked tag file on the file system" do
|
131
|
-
expect(File.join(@bag_path, "tag-1")).to exist_on_fs
|
132
|
-
end
|
133
|
-
it "should not have the deleted tag file on the file system" do
|
134
|
-
expect(File.join(@bag_path, "tag-2")).not_to exist_on_fs
|
135
|
-
end
|
136
|
-
it "should not have the removed or deleted tag files in the manifest" do
|
111
|
+
it "does not contain the untracked tag file" do
|
137
112
|
@bag.tagmanifest_files.each do |mf|
|
138
113
|
File.open(mf) do |io|
|
139
|
-
expect(io.read).not_to include "tag-
|
140
|
-
expect(io.read).not_to include "tag-2"
|
114
|
+
expect(io.read).not_to include "tag-notrack"
|
141
115
|
end
|
142
116
|
end
|
143
117
|
end
|
144
|
-
end
|
145
|
-
end
|
146
118
|
|
119
|
+
describe "removing tracked files" do
|
120
|
+
before do
|
121
|
+
@bag.remove_tag_file "tag-1"
|
122
|
+
@bag.delete_tag_file "tag-2"
|
123
|
+
end
|
124
|
+
|
125
|
+
it "still has the untracked tag file on the file system" do
|
126
|
+
expect(File.join(@bag_path, "tag-1")).to exist_on_fs
|
127
|
+
end
|
147
128
|
|
129
|
+
it "doesn't have the deleted tag file on the file system" do
|
130
|
+
expect(File.join(@bag_path, "tag-2")).not_to exist_on_fs
|
131
|
+
end
|
132
|
+
|
133
|
+
it "doesn't have the removed or deleted tag files in the manifest" do
|
134
|
+
@bag.tagmanifest_files.each do |mf|
|
135
|
+
File.open(mf) do |io|
|
136
|
+
expect(io.read).not_to include "tag-1"
|
137
|
+
expect(io.read).not_to include "tag-2"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
148
144
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,37 +1,37 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "bundler"
|
5
|
+
require "coveralls"
|
4
6
|
|
5
7
|
Bundler.require(:default, :test)
|
6
8
|
|
7
9
|
Coveralls.wear!
|
8
10
|
|
9
|
-
require File.expand_path(
|
11
|
+
require File.expand_path("./util/bagit_matchers", File.dirname(__FILE__))
|
10
12
|
|
11
13
|
RSpec.configure do |config|
|
12
14
|
config.include(BagitMatchers)
|
13
15
|
end
|
14
16
|
|
15
|
-
|
16
|
-
require
|
17
|
+
$LOAD_PATH.unshift File.expand_path("../lib", File.dirname(__FILE__))
|
18
|
+
require "bagit"
|
17
19
|
|
18
|
-
require
|
20
|
+
require "tempfile"
|
19
21
|
|
20
22
|
class Sandbox
|
21
|
-
|
22
23
|
def initialize
|
23
|
-
tf = Tempfile.open
|
24
|
+
tf = Tempfile.open "sandbox"
|
24
25
|
@path = tf.path
|
25
26
|
tf.close!
|
26
|
-
FileUtils
|
27
|
+
FileUtils.mkdir @path
|
27
28
|
end
|
28
29
|
|
29
30
|
def cleanup!
|
30
|
-
FileUtils
|
31
|
+
FileUtils.rm_rf @path
|
31
32
|
end
|
32
33
|
|
33
34
|
def to_s
|
34
35
|
@path
|
35
36
|
end
|
36
|
-
|
37
37
|
end
|
data/spec/tag_info_spec.rb
CHANGED
@@ -1,133 +1,126 @@
|
|
1
|
-
#
|
2
|
-
require 'spec_helper'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
require "spec_helper"
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
describe BagIt::Bag do
|
6
|
+
describe "Tag Info Files" do
|
7
|
+
before do
|
8
|
+
@sandbox = Sandbox.new
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
# make the bag
|
11
|
+
@bag_path = File.join @sandbox.to_s, "the_bag"
|
12
|
+
@bag = described_class.new @bag_path
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
# add some files
|
15
|
+
File.open("/dev/urandom") do |rio|
|
16
|
+
10.times do |n|
|
17
|
+
@bag.add_file("file-#{n}-💩
|
18
|
+
end
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
after(:each) do
|
24
|
-
@sandbox.cleanup!
|
25
|
-
end
|
26
|
-
|
27
|
-
describe "bagit.txt" do
|
28
|
-
|
29
|
-
before do
|
30
|
-
path = File.join @bag_path, 'bagit.txt'
|
31
|
-
@lines = File.open(path) { |io| io.readlines }
|
22
|
+
after do
|
23
|
+
@sandbox.cleanup!
|
32
24
|
end
|
33
25
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
expect(@lines.size).to eq(2)
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should have a bagit version" do
|
43
|
-
a = @lines.select { |line| line.chomp =~ /BagIt-Version:\s*\d+\.\d+/ }
|
44
|
-
expect(a).not_to be_empty
|
45
|
-
end
|
26
|
+
describe "bagit.txt" do
|
27
|
+
before do
|
28
|
+
path = File.join @bag_path, "bagit.txt"
|
29
|
+
@lines = File.open(path, &:readlines)
|
30
|
+
end
|
46
31
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
32
|
+
it "creates a file bagit.txt on bag initialization" do
|
33
|
+
expect(File.join(@bag_path, "bagit.txt")).to exist_on_fs
|
34
|
+
end
|
51
35
|
|
52
|
-
|
36
|
+
it "has exactly two lines" do
|
37
|
+
expect(@lines.size).to eq(2)
|
38
|
+
end
|
53
39
|
|
54
|
-
|
40
|
+
it "has a bagit version" do
|
41
|
+
a = @lines.select { |line| line.chomp =~ /BagIt-Version:\s*\d+\.\d+/ }
|
42
|
+
expect(a).not_to be_empty
|
43
|
+
end
|
55
44
|
|
56
|
-
|
57
|
-
|
58
|
-
|
45
|
+
it "has a tag file encoding" do
|
46
|
+
a = @lines.select { |line| line.chomp =~ /Tag-File-Character-Encoding:\s*.+/ }
|
47
|
+
expect(a).not_to be_empty
|
48
|
+
end
|
59
49
|
end
|
60
50
|
|
61
|
-
|
62
|
-
|
63
|
-
|
51
|
+
describe "bag-info.txt" do
|
52
|
+
before do
|
53
|
+
path = File.join @bag_path, "bag-info.txt"
|
54
|
+
@lines = File.open(path, &:readlines)
|
55
|
+
end
|
64
56
|
|
65
|
-
|
66
|
-
|
67
|
-
|
57
|
+
it "isn't empty" do
|
58
|
+
expect(@lines).not_to be_empty
|
59
|
+
end
|
68
60
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
61
|
+
it "contains lines of the format LABEL: VALUE (like an email header)" do
|
62
|
+
@lines.each { |line| expect(line.chomp).to match(/^[^\s]+\s*:\s+.*$/) }
|
63
|
+
end
|
73
64
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad
|
78
|
-
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
|
79
|
-
aliquip ex ea commodo consequat. Duis aute irure dolor in
|
80
|
-
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
|
81
|
-
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
|
82
|
-
culpa qui officia deserunt mollit anim id est laborum.
|
83
|
-
LOREM
|
84
|
-
@bag.write_bag_info 'Lorem' => longline
|
85
|
-
expect(@bag.bag_info.keys.length).to eq(4) # this isn't a great test. Changed it from 1 to 4 because unrelated changes caused failure.
|
86
|
-
end
|
65
|
+
it "is case insensitive with respect to LABELs" do
|
66
|
+
expect { @bag.write_bag_info "foo" => "lowercase", "Foo" => "capital" }.to raise_error(/Multiple labels/)
|
67
|
+
end
|
87
68
|
|
88
|
-
|
89
|
-
|
90
|
-
|
69
|
+
it "folds long VALUEs" do
|
70
|
+
longline = <<~LOREM
|
71
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
|
72
|
+
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad
|
73
|
+
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
|
74
|
+
aliquip ex ea commodo consequat. Duis aute irure dolor in
|
75
|
+
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
|
76
|
+
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
|
77
|
+
culpa qui officia deserunt mollit anim id est laborum.
|
78
|
+
LOREM
|
79
|
+
@bag.write_bag_info "Lorem" => longline
|
80
|
+
expect(@bag.bag_info.keys.length).to eq(4) # this isn't a great test. Changed it from 1 to 4 because unrelated changes caused failure.
|
81
|
+
end
|
91
82
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
83
|
+
it "specifys a bag software agent" do
|
84
|
+
expect(@bag.bag_info.keys).to include("Bag-Software-Agent")
|
85
|
+
end
|
96
86
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
it "should not override any previous values" do
|
101
|
-
path = File.join @bag_path, 'bag-info.txt'
|
102
|
-
@bag.write_bag_info 'Bag-Software-Agent' => 'Some Other Agent'
|
103
|
-
@bag.write_bag_info 'Source-Organization' => 'Awesome Inc.'
|
104
|
-
@bag.write_bag_info 'Bagging-Date' => '1901-01-01'
|
105
|
-
@bag.write_bag_info
|
106
|
-
contents = File.open(path).read
|
107
|
-
expect(contents).to include "Some Other Agent"
|
108
|
-
expect(contents).to include "Awesome Inc."
|
109
|
-
expect(contents).to include "1901-01-01"
|
110
|
-
end
|
111
|
-
it "should override previous tags when they collide with new ones" do
|
112
|
-
path = File.join @bag_path, 'bag-info.txt'
|
113
|
-
@bag.write_bag_info 'Source-Organization' => 'Awesome Inc.'
|
114
|
-
@bag.write_bag_info 'Source-Organization' => 'Awesome LLC.'
|
115
|
-
contents = File.open(path).read
|
116
|
-
expect(contents).to include "Awesome LLC."
|
117
|
-
expect(contents).not_to include "Awesome Inc."
|
118
|
-
end
|
119
|
-
it "should contain values passed to bag" do
|
120
|
-
hash = {"Bag-Software-Agent" => "rspec",
|
121
|
-
"Bagging-Date" => "2012-11-21",
|
122
|
-
"Contact-Name" => "Willis Corto",
|
123
|
-
"Some-Tag" => "Some Value"
|
124
|
-
}
|
125
|
-
bag_with_info = BagIt::Bag.new(@bag_path + '2', hash)
|
126
|
-
hash.each do |key, value|
|
127
|
-
expect(bag_with_info.bag_info[key]).to eq(value)
|
87
|
+
it "contains a valid bagging date" do
|
88
|
+
expect(@bag.bag_info.keys).to include("Bagging-Date")
|
89
|
+
@bag.bag_info["Bagging-Date"] =~ /^^[0-9]{4}-[0-9]{2}-[0-9]{2}$/
|
128
90
|
end
|
129
|
-
end
|
130
91
|
|
92
|
+
it "contains a payload oxum" do
|
93
|
+
expect(@bag.bag_info.keys).to include("Payload-Oxum")
|
94
|
+
end
|
95
|
+
it "does not override any previous values" do
|
96
|
+
path = File.join @bag_path, "bag-info.txt"
|
97
|
+
@bag.write_bag_info "Bag-Software-Agent" => "Some Other Agent"
|
98
|
+
@bag.write_bag_info "Source-Organization" => "Awesome Inc."
|
99
|
+
@bag.write_bag_info "Bagging-Date" => "1901-01-01"
|
100
|
+
@bag.write_bag_info
|
101
|
+
contents = File.open(path).read
|
102
|
+
expect(contents).to include "Some Other Agent"
|
103
|
+
expect(contents).to include "Awesome Inc."
|
104
|
+
expect(contents).to include "1901-01-01"
|
105
|
+
end
|
106
|
+
it "overrides previous tags when they collide with new ones" do
|
107
|
+
path = File.join @bag_path, "bag-info.txt"
|
108
|
+
@bag.write_bag_info "Source-Organization" => "Awesome Inc."
|
109
|
+
@bag.write_bag_info "Source-Organization" => "Awesome LLC."
|
110
|
+
contents = File.open(path).read
|
111
|
+
expect(contents).to include "Awesome LLC."
|
112
|
+
expect(contents).not_to include "Awesome Inc."
|
113
|
+
end
|
114
|
+
it "contains values passed to bag" do
|
115
|
+
hash = {"Bag-Software-Agent" => "rspec",
|
116
|
+
"Bagging-Date" => "2012-11-21",
|
117
|
+
"Contact-Name" => "Willis Corto",
|
118
|
+
"Some-Tag" => "Some Value"}
|
119
|
+
bag_with_info = described_class.new(@bag_path + "2", hash)
|
120
|
+
hash.each do |key, value|
|
121
|
+
expect(bag_with_info.bag_info[key]).to eq(value)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
131
125
|
end
|
132
|
-
|
133
126
|
end
|