bagit 0.3.5 → 0.4.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.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4b4fd9e3eb682521a82c7cd25ad0320088fba8fa907876a48c39320e2b245478
|
4
|
+
data.tar.gz: ec3971461e6304cc457e50323b369ce0d61a6b3df5f3ac445601c9f34d456f67
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78dff8b4378080349c13e9794302792e981f36db37f67e206658c554ecf0e025ba3c4332a5cd9f53f48a53935c5cbce9fb4435f28badccd0dacdf556b9ef30e7
|
7
|
+
data.tar.gz: 98828d498d5fdb72551587d4a4b766a579470e911d0056debe8098f9a59cd89c04cd2e1e204f02332b3a0813e2b3967a2ac7f6bae91895463bb7144590e54fb4
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "bundler/setup"
|
3
5
|
Bundler.setup(:default, :development, :test)
|
4
6
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
7
|
+
require "rake"
|
8
|
+
require "rdoc/task"
|
9
|
+
require "rspec/core/rake_task"
|
10
|
+
require "standard/rake"
|
8
11
|
|
9
12
|
Bundler::GemHelper.install_tasks
|
10
13
|
|
11
14
|
RSpec::Core::RakeTask.new do |t|
|
12
|
-
t.pattern =
|
13
|
-
t.rspec_opts = %w
|
15
|
+
t.pattern = "spec/**/*_spec.rb"
|
16
|
+
t.rspec_opts = %w[--format documentation --color]
|
14
17
|
end
|
15
18
|
|
16
|
-
task :
|
19
|
+
task default: [:standard, :spec]
|
data/bagit.gemspec
CHANGED
@@ -1,30 +1,34 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
5
|
+
require "bagit/version"
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name
|
8
|
-
spec.version
|
9
|
-
spec.summary
|
8
|
+
spec.name = "bagit"
|
9
|
+
spec.version = BagIt::VERSION
|
10
|
+
spec.summary = "BagIt package generation and validation"
|
10
11
|
spec.description = "Ruby Library and Command Line tools for bagit"
|
11
|
-
spec.email
|
12
|
-
spec.homepage
|
13
|
-
spec.authors
|
14
|
-
spec.license
|
12
|
+
spec.email = "jamie@jamielittle.org"
|
13
|
+
spec.homepage = "http://github.com/tipr/bagit"
|
14
|
+
spec.authors = ["Tom Johnson, Francesco Lazzarino, Jamie Little"]
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.required_ruby_version = "~> 2.0"
|
15
18
|
|
16
|
-
spec.
|
17
|
-
|
18
|
-
spec.add_dependency 'validatable', '~> 1.6'
|
19
|
-
spec.add_dependency 'docopt', '~> 0.5.0'
|
19
|
+
spec.add_dependency "validatable", "~> 1.6"
|
20
|
+
spec.add_dependency "docopt", "~> 0.5.0"
|
20
21
|
|
21
|
-
spec.add_development_dependency
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
22
|
+
spec.add_development_dependency "bundler"
|
23
|
+
spec.add_development_dependency "coveralls"
|
24
|
+
spec.add_development_dependency "pry"
|
25
|
+
spec.add_development_dependency "pry-byebug"
|
26
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3"
|
28
|
+
spec.add_development_dependency "standard"
|
25
29
|
|
26
|
-
spec.files
|
27
|
-
spec.executables
|
28
|
-
spec.test_files
|
30
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
31
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
32
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
29
33
|
spec.require_paths = ["lib"]
|
30
34
|
end
|
data/bin/bagit
CHANGED
@@ -1,24 +1,25 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'bagit'
|
4
5
|
require 'docopt'
|
5
6
|
require 'logger'
|
6
|
-
|
7
7
|
logger = Logger.new(STDOUT)
|
8
8
|
|
9
9
|
doc = <<DOCOPT
|
10
10
|
BagIt.
|
11
11
|
|
12
|
-
Usage:
|
13
|
-
bagit add [-f <file>...] [-t <tagfile>...] BAGPATH
|
12
|
+
Usage:
|
13
|
+
bagit add [-f <file>...] [-t <tagfile>...] [-a <algo>] BAGPATH
|
14
14
|
bagit delete [-f <file>...] [-t <tagfile>...] BAGPATH
|
15
15
|
bagit remove [-t <tagfile>...] BAGPATH
|
16
|
-
bagit validate [-o] BAGPATH
|
16
|
+
bagit validate [-o] BAGPATH
|
17
17
|
bagit manifest [-T] BAGPATH
|
18
|
-
bagit list [--tags | --all] BAGPATH
|
18
|
+
bagit list [--tags | --all] BAGPATH
|
19
19
|
bagit -h | --version
|
20
20
|
|
21
21
|
Options:
|
22
|
+
-a A selected hashing algorithm. (md5, sha1, sha256)
|
22
23
|
-h --help Show this help screen.
|
23
24
|
--version Show version.
|
24
25
|
-f <file> File to add to/delete from bag. Repeatable.
|
@@ -30,34 +31,36 @@ Options:
|
|
30
31
|
|
31
32
|
DOCOPT
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
# Possible commands for bag-info write
|
35
|
+
#
|
36
|
+
# bagit new [--source-organization <org>] [--organization-address <org-addr>] [--contact-name <contact>]
|
37
|
+
# [--contact-phone <phone>] [--contact-email <email>] [--external-description <ext-desc>]
|
38
|
+
# [--external-identifier <ext-id>] [--group-identifier <group-id>] [--count <count>]
|
39
|
+
# [--internal-sender-identifier <sender-id>] [--internal-sender-description <sender-desc>]
|
40
|
+
# [--bag-info-entry <label> <value>] [-f <file>...] [-t <tagfile>...] BAGPATH
|
40
41
|
|
41
42
|
begin
|
42
|
-
opts = Docopt
|
43
|
+
opts = Docopt.docopt(doc, version: BagIt::VERSION)
|
43
44
|
|
44
|
-
unless opts['validate']
|
45
|
-
bag = BagIt::Bag.new(opts['BAGPATH'])
|
46
|
-
end
|
45
|
+
bag = BagIt::Bag.new(opts['BAGPATH']) unless opts['validate']
|
47
46
|
#####################################
|
48
47
|
# commands that don't alter the bag #
|
49
48
|
#####################################
|
50
49
|
if opts['validate']
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
50
|
+
bag = BagIt::Bag.new(opts['BAGPATH'])
|
51
|
+
|
52
|
+
valid = if opts['--oxum']
|
53
|
+
bag.valid_oxum?
|
54
|
+
else
|
55
|
+
bag.valid?
|
56
|
+
end
|
57
|
+
|
58
|
+
if valid
|
59
|
+
logger.info(valid)
|
58
60
|
else
|
59
|
-
logger.error("
|
61
|
+
logger.error("#{valid}: #{bag.errors.full_messages.join(', ')}")
|
60
62
|
end
|
63
|
+
|
61
64
|
# validation commands MUST NOT change manifest or bag-info files
|
62
65
|
exit
|
63
66
|
end
|
@@ -74,59 +77,52 @@ begin
|
|
74
77
|
exit
|
75
78
|
end
|
76
79
|
|
77
|
-
|
78
80
|
######################################
|
79
81
|
# commands that may cause data loss! #
|
80
82
|
######################################
|
81
83
|
|
82
|
-
#TODO: implement delete for data and tag files; remove for tag files.
|
84
|
+
# TODO: implement delete for data and tag files; remove for tag files.
|
83
85
|
|
84
86
|
# handle add/delete bag data files
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
end
|
94
|
-
rescue Exception => e
|
95
|
-
logger.error("Failed operation on bag file: #{e.message}")
|
96
|
-
end
|
97
|
-
}
|
87
|
+
opts['-f']&.each do |datafile|
|
88
|
+
if opts['add'] || opts['new']
|
89
|
+
bag.add_file(File.basename(datafile), datafile)
|
90
|
+
elsif opts['delete']
|
91
|
+
bag.remove_file(File.basename(datafile))
|
92
|
+
end
|
93
|
+
rescue StandardError => e
|
94
|
+
logger.error("Failed operation on bag file: #{e.message}")
|
98
95
|
end
|
99
96
|
|
100
97
|
# handle adding tag files
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
# otherwise, add it
|
110
|
-
else
|
111
|
-
bag.add_tag_file(File.basename(tagfile), tagfile)
|
112
|
-
end
|
113
|
-
elsif opts['delete']
|
114
|
-
bag.delete_tag_file(File.basename(tagfile))
|
115
|
-
elsif opts['remove']
|
116
|
-
bag.remove_tag_file(File.basename(tagfile))
|
117
|
-
end
|
118
|
-
rescue Exception => e
|
119
|
-
logger.error("Failed operation on tag file: #{e.message}".red)
|
98
|
+
opts['-t']&.each do |tagfile|
|
99
|
+
if opts['add'] || opts['new']
|
100
|
+
# if it does, try to manifest it
|
101
|
+
if File.exist?(File.join(bag.bag_dir, File.basename(tagfile)))
|
102
|
+
bag.add_tag_file(tagfile)
|
103
|
+
# otherwise, add it
|
104
|
+
else
|
105
|
+
bag.add_tag_file(File.basename(tagfile), tagfile)
|
120
106
|
end
|
121
|
-
|
107
|
+
elsif opts['delete']
|
108
|
+
bag.delete_tag_file(File.basename(tagfile))
|
109
|
+
elsif opts['remove']
|
110
|
+
bag.remove_tag_file(File.basename(tagfile))
|
111
|
+
end
|
112
|
+
rescue StandardError => e
|
113
|
+
logger.error("Failed operation on tag file: #{e.message}".red)
|
122
114
|
end
|
123
115
|
|
124
116
|
# if we haven't quit yet, we need to re-manifest
|
125
|
-
# only do tags if tag files have been explictly added/removed or it is explictly called
|
126
|
-
bag.tagmanifest! if opts['-T']
|
127
|
-
|
117
|
+
# only do tags if tag files have been explictly added/removed or it is explictly called
|
118
|
+
bag.tagmanifest! if opts['-T'] || !opts['-t'].nil?
|
119
|
+
|
120
|
+
if opts['-a'].nil?
|
121
|
+
bag.manifest!
|
122
|
+
else
|
123
|
+
bag.manifest!(algo: opts['<algo>'])
|
124
|
+
end
|
128
125
|
|
129
126
|
rescue Docopt::Exit => e
|
130
127
|
logger.error(e.message.red)
|
131
128
|
end
|
132
|
-
|
data/lib/bagit.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# == About bagit.rb
|
2
4
|
# Author:: Francesco Lazzarino (mailto:flazzarino@gmail.com)
|
3
5
|
# Functionality conforms to the BagIt Spec v0.96:
|
4
6
|
# http://www.cdlib.org/inside/diglib/bagit/bagitspec.html
|
5
7
|
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
8
|
+
require "bagit/bag"
|
9
|
+
require "bagit/version"
|
10
|
+
require "fileutils"
|
11
|
+
require "date"
|
12
|
+
require "logger"
|
11
13
|
module BagIt
|
12
14
|
# The version of the BagIt specification the code is conforming to.
|
13
|
-
SPEC_VERSION =
|
15
|
+
SPEC_VERSION = "0.97"
|
14
16
|
end
|
data/lib/bagit/bag.rb
CHANGED
@@ -1,48 +1,43 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bagit/fetch"
|
4
|
+
require "bagit/file"
|
5
|
+
require "bagit/info"
|
6
|
+
require "bagit/manifest"
|
7
|
+
require "bagit/string"
|
8
|
+
require "bagit/valid"
|
7
9
|
|
8
10
|
module BagIt
|
9
11
|
# Represents the state of a bag on a filesystem
|
10
12
|
class Bag
|
11
13
|
attr_reader :bag_dir
|
12
14
|
|
13
|
-
include Validity
|
14
|
-
include Info
|
15
|
-
include Manifest
|
16
|
-
include Fetch
|
15
|
+
include Validity # Validity functionality
|
16
|
+
include Info # bagit & bag info functionality
|
17
|
+
include Manifest # manifest related functionality
|
18
|
+
include Fetch # fetch related functionality
|
17
19
|
|
18
20
|
# Make a new Bag based at path
|
19
|
-
def initialize(path, info={},
|
20
|
-
|
21
|
-
|
21
|
+
def initialize(path, info = {}, _create = false)
|
22
22
|
@bag_dir = path
|
23
23
|
# make the dir structure if it doesn't exist
|
24
|
-
FileUtils
|
25
|
-
FileUtils
|
24
|
+
FileUtils.mkdir bag_dir unless File.directory? bag_dir
|
25
|
+
FileUtils.mkdir data_dir unless File.directory? data_dir
|
26
26
|
|
27
27
|
# write some tag info if its not there
|
28
|
-
unless File.exist? bagit_txt_file
|
29
|
-
write_bagit("BagIt-Version" => SPEC_VERSION, "Tag-File-Character-Encoding" => "UTF-8")
|
30
|
-
end
|
28
|
+
write_bagit("BagIt-Version" => SPEC_VERSION, "Tag-File-Character-Encoding" => "UTF-8") unless File.exist? bagit_txt_file
|
31
29
|
|
32
|
-
unless File.exist? bag_info_txt_file
|
33
|
-
write_bag_info(info)
|
34
|
-
end
|
35
|
-
|
30
|
+
write_bag_info(info) unless File.exist? bag_info_txt_file
|
36
31
|
end
|
37
32
|
|
38
33
|
# Return the path to the data directory
|
39
34
|
def data_dir
|
40
|
-
File.join @bag_dir,
|
35
|
+
File.join @bag_dir, "data"
|
41
36
|
end
|
42
37
|
|
43
38
|
# Return the paths to each bag file relative to bag_dir
|
44
39
|
def bag_files
|
45
|
-
Dir[File.join(data_dir,
|
40
|
+
Dir[File.join(data_dir, "**", "*")].select { |f| File.file? f }
|
46
41
|
end
|
47
42
|
|
48
43
|
# Return the paths to each tag file relative to bag_dir
|
@@ -50,65 +45,66 @@ module BagIt
|
|
50
45
|
files = []
|
51
46
|
if tagmanifest_files != []
|
52
47
|
File.open(tagmanifest_files.first) do |f|
|
53
|
-
f.each_line{|line| files << File.join(@bag_dir, line.split(
|
48
|
+
f.each_line { |line| files << File.join(@bag_dir, line.split(" ")[1]) }
|
54
49
|
end
|
55
50
|
end
|
56
51
|
files
|
57
52
|
end
|
58
53
|
|
59
|
-
# Add a bag file
|
60
|
-
def add_file(
|
61
|
-
path = File.join(data_dir,
|
62
|
-
raise "Bag file exists: #{
|
63
|
-
FileUtils
|
54
|
+
# Add a bag file at the given path relative to data_dir
|
55
|
+
def add_file(relative_path, src_path = nil)
|
56
|
+
path = File.join(data_dir, relative_path)
|
57
|
+
raise "Bag file exists: #{relative_path}" if File.exist? path
|
58
|
+
FileUtils.mkdir_p File.dirname(path)
|
64
59
|
|
65
|
-
if src_path.nil?
|
66
|
-
|
60
|
+
f = if src_path.nil?
|
61
|
+
File.open(path, "w") { |io| yield io }
|
67
62
|
else
|
68
|
-
|
63
|
+
FileUtils.cp src_path, path
|
69
64
|
end
|
70
65
|
write_bag_info
|
71
|
-
|
66
|
+
f
|
72
67
|
end
|
73
68
|
|
74
|
-
# Remove a bag file
|
75
|
-
def remove_file(
|
76
|
-
path = File.join(data_dir,
|
77
|
-
raise "Bag file does not exist: #{
|
78
|
-
FileUtils
|
69
|
+
# Remove a bag file at the given path relative to data_dir
|
70
|
+
def remove_file(relative_path)
|
71
|
+
path = File.join(data_dir, relative_path)
|
72
|
+
raise "Bag file does not exist: #{relative_path}" unless File.exist? path
|
73
|
+
FileUtils.rm path
|
79
74
|
end
|
80
75
|
|
81
|
-
# Retrieve the IO handle for a file in the bag
|
82
|
-
|
83
|
-
|
76
|
+
# Retrieve the IO handle for a file in the bag at a given path relative to
|
77
|
+
# data_dir
|
78
|
+
def get(relative_path)
|
79
|
+
path = File.join(data_dir, relative_path)
|
84
80
|
return nil unless File.exist?(path)
|
85
81
|
File.open(path)
|
86
82
|
end
|
87
83
|
|
88
84
|
# Test if this bag is empty (no files)
|
89
85
|
def empty?
|
90
|
-
|
86
|
+
bag_files.empty?
|
91
87
|
end
|
92
88
|
|
93
89
|
# Get all bag file paths relative to the data dir
|
94
90
|
def paths
|
95
|
-
|
91
|
+
bag_files.collect { |f| f.sub(data_dir + "/", "") }
|
96
92
|
end
|
97
93
|
|
98
94
|
# Get the Oxum for the payload files
|
99
95
|
def payload_oxum
|
100
96
|
bytes = 0
|
101
97
|
bag_files.each do |f|
|
102
|
-
#TODO: filesystem quirks? Are we getting the stream size or the size on disk?
|
98
|
+
# TODO: filesystem quirks? Are we getting the stream size or the size on disk?
|
103
99
|
bytes += File.size(f)
|
104
100
|
end
|
105
|
-
|
101
|
+
bytes.to_s + "." + bag_files.count.to_s
|
106
102
|
end
|
107
103
|
|
108
104
|
# Remove all empty directory trees from the bag
|
109
105
|
def gc!
|
110
106
|
Dir.entries(data_dir).each do |f|
|
111
|
-
unless %w
|
107
|
+
unless %w[.. .].include? f
|
112
108
|
abs_path = File.join data_dir, f
|
113
109
|
File.clean abs_path
|
114
110
|
end
|