text-checkm 0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +312 -0
- data/.idea/$CACHE_FILE$ +26 -0
- data/.idea/.gitignore +6 -0
- data/.idea/go.imports.xml +6 -0
- data/.idea/inspectionProfiles/Project_Default.xml +17 -0
- data/.idea/inspectionProfiles/profiles_settings.xml +7 -0
- data/.idea/misc.xml +9 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/.rubocop.yml +144 -0
- data/.ruby-version +1 -0
- data/.simplecov +7 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +98 -0
- data/LICENSE.md +23 -0
- data/README.md +23 -0
- data/Rakefile +36 -0
- data/SPEC.txt +468 -0
- data/lib/text/checkm.rb +2 -0
- data/lib/text/checkm/checksum.rb +40 -0
- data/lib/text/checkm/entry.rb +77 -0
- data/lib/text/checkm/manifest.rb +115 -0
- data/lib/text/checkm/module_info.rb +16 -0
- data/rakelib/bundle.rake +8 -0
- data/rakelib/coverage.rake +5 -0
- data/rakelib/rubocop.rake +16 -0
- data/spec/.rubocop.yml +19 -0
- data/spec/data/merritt-manifest.checkm +9 -0
- data/spec/data/myfirst.checkm +5 -0
- data/spec/data/test_1/1 +1 -0
- data/spec/data/two-level-manifest.checkm +8 -0
- data/spec/lib/text/checkm/checksum_spec.rb +24 -0
- data/spec/lib/text/checkm/entry_spec.rb +52 -0
- data/spec/lib/text/checkm/manifest_spec.rb +157 -0
- data/spec/spec_helper.rb +23 -0
- data/text-checkm.gemspec +29 -0
- data/text-checkm.iml +51 -0
- metadata +236 -0
data/lib/text/checkm.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
module Text
|
4
|
+
module Checkm
|
5
|
+
class << self
|
6
|
+
# Size (in bytes) to read (in chunks) to compute checksums
|
7
|
+
CHUNK_SIZE = 8 * 1024 * 1024
|
8
|
+
|
9
|
+
# Compute the checksum 'alg' for a file
|
10
|
+
# @param [File] file
|
11
|
+
# @param [String] alg md5, sha1, sha256, dir
|
12
|
+
def checksum(file, alg) # TODO: don't pass file handles around
|
13
|
+
return true unless alg # TODO: something less counterintuitive
|
14
|
+
return File.directory?(file) if alg =~ /dir/
|
15
|
+
|
16
|
+
digest_alg = digest_for(alg)
|
17
|
+
return false unless digest_alg # TODO: something less counterintuitive
|
18
|
+
|
19
|
+
while !file.eof? && (chunk = file.readpartial(CHUNK_SIZE))
|
20
|
+
digest_alg << chunk
|
21
|
+
end
|
22
|
+
digest_alg.hexdigest
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def digest_for(alg)
|
28
|
+
case alg
|
29
|
+
when /md5/
|
30
|
+
Digest::MD5.new
|
31
|
+
when /sha1/
|
32
|
+
Digest::SHA1.new
|
33
|
+
when /sha256/
|
34
|
+
Digest::SHA2.new(256)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
require 'text/checkm/checksum'
|
5
|
+
|
6
|
+
module Text
|
7
|
+
module Checkm
|
8
|
+
class Entry
|
9
|
+
BASE_FIELDS = %w[sourcefileorurl alg digest length modtime targetfileorurl].freeze
|
10
|
+
attr_reader :values
|
11
|
+
|
12
|
+
def self.create(path, args = {}) # TODO: why is this in this class?
|
13
|
+
base = args[:base] || Dir.pwd
|
14
|
+
alg = args[:alg] || 'md5'
|
15
|
+
file = File.new File.join(base, path)
|
16
|
+
|
17
|
+
format('%s | %s | %s | %s | %s | %s', path, alg, Checkm.checksum(file, alg), File.size(file.path), file.mtime.utc.xmlschema, nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(line, manifest = nil)
|
21
|
+
@line = line.strip
|
22
|
+
@include = false
|
23
|
+
@fields = BASE_FIELDS
|
24
|
+
@fields = manifest.fields if manifest && manifest.fields
|
25
|
+
@values = line.split('|').map(&:strip)
|
26
|
+
@manifest = manifest
|
27
|
+
end
|
28
|
+
|
29
|
+
# rubocop:disable Style/MethodMissingSuper
|
30
|
+
def method_missing(sym, *_args)
|
31
|
+
# TODO: something less extreme
|
32
|
+
@values[@fields.index(sym.to_s.downcase) || BASE_FIELDS.index(sym.to_s.downcase)]
|
33
|
+
end
|
34
|
+
# rubocop:enable Style/MethodMissingSuper
|
35
|
+
|
36
|
+
def respond_to_missing?(sym, *)
|
37
|
+
@fields.include?(sym.to_s.downcase) || BASE_FIELDS.include?(sym.to_s.downcase)
|
38
|
+
end
|
39
|
+
|
40
|
+
def valid?
|
41
|
+
source_exists? && valid_checksum? && valid_multilevel? # xxx && valid_length? && valid_modtime?
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def source
|
47
|
+
file = sourcefileorurl
|
48
|
+
file = file[1..] if file =~ /^@/
|
49
|
+
File.join(@manifest.path, file)
|
50
|
+
end
|
51
|
+
|
52
|
+
def source_exists?
|
53
|
+
File.exist? source
|
54
|
+
end
|
55
|
+
|
56
|
+
def valid_checksum?
|
57
|
+
file = File.new source
|
58
|
+
checksum = Checkm.checksum(file, alg)
|
59
|
+
[true, digest].include?(checksum) # TODO: something less counterintuitive
|
60
|
+
end
|
61
|
+
|
62
|
+
# def valid_length?
|
63
|
+
# throw NotImplementedError
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# def valid_modtime?
|
67
|
+
# throw NotImplementedError
|
68
|
+
# end
|
69
|
+
|
70
|
+
def valid_multilevel?
|
71
|
+
return true unless sourcefileorurl =~ /^@/
|
72
|
+
|
73
|
+
Manifest.parse(URI.open(source).read, path: File.dirname(source))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'text/checkm/entry'
|
2
|
+
|
3
|
+
module Text
|
4
|
+
module Checkm
|
5
|
+
class Manifest
|
6
|
+
def self.parse(str, args = {})
|
7
|
+
Manifest.new str, args
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :version
|
11
|
+
attr_reader :entries
|
12
|
+
attr_reader :fields
|
13
|
+
attr_reader :path
|
14
|
+
|
15
|
+
# rubocop:disable Metrics/MethodLength
|
16
|
+
def initialize(checkm, args = {})
|
17
|
+
@args = args
|
18
|
+
@version = nil
|
19
|
+
@checkm = checkm
|
20
|
+
@lines = checkm.split "\n"
|
21
|
+
@entries = []
|
22
|
+
@eof = false
|
23
|
+
@fields = nil
|
24
|
+
@path = args[:path] # TODO: something less hacky
|
25
|
+
@path ||= Dir.pwd
|
26
|
+
|
27
|
+
parse_lines
|
28
|
+
# xxx error on empty entries?
|
29
|
+
@lines.unshift('#%checkm_0.7') and (@version = '0.7') if @version.nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
# rubocop:enable Metrics/MethodLength
|
33
|
+
|
34
|
+
def valid?
|
35
|
+
return true if @entries.empty?
|
36
|
+
|
37
|
+
@entries.map(&:valid?).none? { |b| b == false }
|
38
|
+
end
|
39
|
+
|
40
|
+
def add(path, args = {})
|
41
|
+
line = Entry.create path, args
|
42
|
+
|
43
|
+
Manifest.new [@lines, line].flatten.join("\n"), @args
|
44
|
+
end
|
45
|
+
|
46
|
+
def remove(path)
|
47
|
+
Manifest.new @lines.reject { |x| x =~ /^@?#{path}/ }.join("\n"), @args
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
@lines.join("\n")
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_h
|
55
|
+
{}.tap do |h|
|
56
|
+
entries.each do |e|
|
57
|
+
source = e.sourcefileorurl
|
58
|
+
(h[source] ||= []) << e
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# rubocop:disable Metrics/MethodLength
|
66
|
+
def parse_lines
|
67
|
+
@lines.each do |line|
|
68
|
+
case line
|
69
|
+
when /^#%/
|
70
|
+
parse_header line
|
71
|
+
when /^#/
|
72
|
+
parse_comment line
|
73
|
+
when /^$/
|
74
|
+
# do nothing
|
75
|
+
when /^@/
|
76
|
+
parse_line line
|
77
|
+
else
|
78
|
+
parse_line line
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# rubocop:enable Metrics/MethodLength
|
84
|
+
|
85
|
+
# rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
86
|
+
def parse_header(line)
|
87
|
+
case line
|
88
|
+
when /^#%checkm/
|
89
|
+
match = /^#%checkm_(\d+)\.(\d+)/.match line
|
90
|
+
@version = "#{match[1]}.#{match[2]}" if match
|
91
|
+
when /^#%eof/
|
92
|
+
@eof = true
|
93
|
+
when /^#%fields/
|
94
|
+
list = line.split('|')
|
95
|
+
list.shift
|
96
|
+
@fields = list.map { |v| v.strip.downcase }
|
97
|
+
when /^#%prefix/
|
98
|
+
# do nothing
|
99
|
+
when /^#%profile/
|
100
|
+
# do nothing
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
105
|
+
|
106
|
+
def parse_comment(_line)
|
107
|
+
# do nothing
|
108
|
+
end
|
109
|
+
|
110
|
+
def parse_line(line)
|
111
|
+
@entries << Entry.new(line, self)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Text
|
2
|
+
module Checkm
|
3
|
+
class ModuleInfo
|
4
|
+
NAME = 'text-checkm'.freeze
|
5
|
+
AUTHOR = 'David Moles'.freeze
|
6
|
+
AUTHOR_EMAIL = 'dmoles@berkeley.edu'.freeze
|
7
|
+
SUMMARY = 'Ruby implementation of the Checkm text manifest format'.freeze
|
8
|
+
DESCRIPTION = 'A Ruby implementation of the Checkm checksum-based text manifest format'.freeze
|
9
|
+
LICENSE = 'MIT'.freeze
|
10
|
+
VERSION = '0.7'.freeze
|
11
|
+
HOMEPAGE = 'https://github.com/dmolesUC/checkm'.freeze
|
12
|
+
|
13
|
+
private_class_method :new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/rakelib/bundle.rake
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubocop'
|
2
|
+
require 'rubocop/rake_task'
|
3
|
+
|
4
|
+
desc 'Run rubocop with HTML output'
|
5
|
+
RuboCop::RakeTask.new(:rubocop) do |cop|
|
6
|
+
output = ENV['RUBOCOP_OUTPUT'] || 'artifacts/reports/rubocop/index.html'
|
7
|
+
|
8
|
+
cop.formatters = ['html']
|
9
|
+
cop.options = ['--out', output]
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Run RuboCop with auto-correct, and output results to console'
|
13
|
+
task :ra do
|
14
|
+
# b/c we want console output, we can't just use `rubocop:auto_correct`
|
15
|
+
RuboCop::CLI.new.run(['--auto-correct'])
|
16
|
+
end
|
data/spec/.rubocop.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
inherit_from: ../.rubocop.yml
|
2
|
+
|
3
|
+
Style/ClassAndModuleChildren:
|
4
|
+
Enabled: false
|
5
|
+
|
6
|
+
Layout/LineLength:
|
7
|
+
Enabled: false
|
8
|
+
|
9
|
+
Metrics/BlockLength:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Metrics/ClassLength:
|
13
|
+
Enabled: false
|
14
|
+
|
15
|
+
Metrics/ModuleLength:
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
Metrics/MethodLength:
|
19
|
+
Enabled: false
|
@@ -0,0 +1,9 @@
|
|
1
|
+
#%checkm_0.7
|
2
|
+
#%profile | http://uc3.cdlib.org/registry/ingest/manifest/mrt-single-file-batch-manifest
|
3
|
+
#%prefix | mrt: | http://merritt.cdlib.org/terms#
|
4
|
+
#%prefix | nfo: | http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#
|
5
|
+
#%fields | nfo:fileUrl | nfo:hashAlgorithm | nfo:hashValue | nfo:fileSize | nfo:fileLastModified | nfo:fileName | mrt:primaryIdentifier | mrt:localIdentifier | mrt:creator | mrt:title | mrt:date
|
6
|
+
http://merritt.cdlib.org/samples/goldenDragon.jpg | md5 | aa59e145dfb2237ecd8cb5ce4f4953ea | | | goldenDragon.jpg | | | Tracy Seneca | Golden Dragon Restaurant Sign | 2009-09-01T00:00:00
|
7
|
+
http://merritt.cdlib.org/samples/tumbleBug.jpg | md5 | 61224ef4f2a8dad552ff57980ed0bf49 | | | tumbleBug.jpg | | | Tracy Seneca | Tumble Bug, Luna Park. Sydney
|
8
|
+
http://merritt.cdlib.org/samples/generalDrapery.jpg | | | | | generalDrapery.jpg | | | | General Drapery
|
9
|
+
#%eof
|
data/spec/data/test_1/1
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1
|
@@ -0,0 +1,8 @@
|
|
1
|
+
#%checkm_0.7
|
2
|
+
# A two-level manifest.
|
3
|
+
|
4
|
+
#Filename|Alg |Checksum |Length
|
5
|
+
foo.bar |sha1|2eacd0da7aa89b094f5121eb2901bf4de2219ef1 | 366
|
6
|
+
foo.bar |md5 |3e83471320227c0797a0c251f28db0c5 | 366
|
7
|
+
# This next line "includes" the manifest in file "myfirst".
|
8
|
+
@myfirst.checkm |md5 |1ad6bcd5e4c49420ead2df43406d37fb | 218
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Text
|
4
|
+
module Checkm
|
5
|
+
describe :checksum do
|
6
|
+
it 'calculates the checksum' do
|
7
|
+
file = 'spec/data/test_1/1'
|
8
|
+
expected = {
|
9
|
+
'md5' => 'b026324c6904b2a9cb4b88d6d61c81d1',
|
10
|
+
'sha1' => 'e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e',
|
11
|
+
'sha256' => '4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865'
|
12
|
+
}
|
13
|
+
aggregate_failures 'checksums' do
|
14
|
+
expected.each do |alg, checksum|
|
15
|
+
File.open(file, 'r') do |f|
|
16
|
+
actual = Checkm.checksum(f, alg)
|
17
|
+
expect(actual).to eq(checksum), "Wrong #{alg} checksum for #{file}, expected #{checksum}, was #{actual}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Text
|
4
|
+
module Checkm
|
5
|
+
describe Entry do
|
6
|
+
describe :create do
|
7
|
+
it 'should return a manifest line' do
|
8
|
+
res = Entry.create('LICENSE.md')
|
9
|
+
expect(res).to match(/LICENSE\.md | md5 | a02e647a5dcd1fe38abf74f9f0d44dae | 1149 | \d{4}/)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe :respond_to_missing? do
|
14
|
+
it 'should return true for all base fields' do
|
15
|
+
entry = Entry.new('book/Chapter9.xml | md5 | 49afbd86a1ca9f34b677a3f09655eae9')
|
16
|
+
Entry::BASE_FIELDS.each do |f|
|
17
|
+
expect(entry.respond_to?(f.to_sym)).to eq(true)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should return true for all custom fields' do
|
22
|
+
expected_fields = %w[
|
23
|
+
nfo:fileUrl
|
24
|
+
nfo:hashAlgorithm
|
25
|
+
nfo:hashValue
|
26
|
+
nfo:fileSize
|
27
|
+
nfo:fileLastModified
|
28
|
+
nfo:fileName
|
29
|
+
mrt:primaryIdentifier
|
30
|
+
mrt:localIdentifier
|
31
|
+
mrt:creator
|
32
|
+
mrt:title
|
33
|
+
mrt:date
|
34
|
+
]
|
35
|
+
manifest = Manifest.parse(File.read('spec/data/merritt-manifest.checkm'))
|
36
|
+
entry = manifest.entries[0]
|
37
|
+
expected_fields.each do |f|
|
38
|
+
expect(entry.respond_to?(f.to_sym)).to eq(true)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe :valid do
|
44
|
+
it 'handles multi-level manifests' do
|
45
|
+
manifest = Manifest.parse(File.read('spec/data/two-level-manifest.checkm'), path: 'spec/data')
|
46
|
+
entry = manifest.entries[2]
|
47
|
+
expect(entry.valid?).to be_truthy # TODO: something less hacky
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Text
|
4
|
+
module Checkm
|
5
|
+
describe Manifest do
|
6
|
+
it 'should be valid if empty' do
|
7
|
+
checkm = ''
|
8
|
+
res = Manifest.parse(checkm)
|
9
|
+
expect(res.entries).to be_empty
|
10
|
+
expect(res).to be_valid
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should ignore comments' do
|
14
|
+
checkm = '#'
|
15
|
+
res = Manifest.parse(checkm)
|
16
|
+
expect(res.entries).to be_empty
|
17
|
+
expect(res).to be_valid
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should parse the checkm version' do
|
21
|
+
checkm = '#%checkm_0.7'
|
22
|
+
res = Manifest.parse(checkm)
|
23
|
+
expect(res.entries).to be_empty
|
24
|
+
expect(res).to be_valid
|
25
|
+
expect(res.version).to eq('0.7')
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'simple checkm line' do
|
29
|
+
before(:each) do
|
30
|
+
@checkm = 'book/Chapter9.xml | md5 | 49afbd86a1ca9f34b677a3f09655eae9'
|
31
|
+
@result = Manifest.parse(@checkm)
|
32
|
+
@line = @result.entries.first
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should parse one entry' do
|
36
|
+
expect(@result.entries.size).to eq(1)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should parse a checkm line' do
|
40
|
+
expect(@line.values[0]).to eq('book/Chapter9.xml')
|
41
|
+
expect(@line.values[1]).to eq('md5')
|
42
|
+
expect(@line.values[2]).to eq('49afbd86a1ca9f34b677a3f09655eae9')
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should allow name-based lookups' do
|
46
|
+
expect(@line.sourcefileorurl).to eq('book/Chapter9.xml')
|
47
|
+
expect(@line.alg).to eq('md5')
|
48
|
+
expect(@line.digest).to eq('49afbd86a1ca9f34b677a3f09655eae9')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should support custom field names' do
|
53
|
+
checkm = <<~CHECKM
|
54
|
+
#%fields | testa | test b
|
55
|
+
book/Chapter9.xml | md5 | 49afbd86a1ca9f34b677a3f09655eae9
|
56
|
+
CHECKM
|
57
|
+
checkm.strip!
|
58
|
+
|
59
|
+
res = Manifest.parse(checkm)
|
60
|
+
|
61
|
+
line = res.entries.first
|
62
|
+
|
63
|
+
expect(line.sourcefileorurl).to eq('book/Chapter9.xml')
|
64
|
+
expect(line.testa).to eq('book/Chapter9.xml')
|
65
|
+
expect(line.alg).to eq('md5')
|
66
|
+
expect(line.send(:'test b')).to eq('md5')
|
67
|
+
expect(line.digest).to eq('49afbd86a1ca9f34b677a3f09655eae9')
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'validity check' do
|
71
|
+
it 'should be valid if the file exists' do
|
72
|
+
checkm = '1 | md5 | b026324c6904b2a9cb4b88d6d61c81d1'
|
73
|
+
res = Manifest.parse(checkm, path: 'spec/data/test_1')
|
74
|
+
expect(res.entries.size).to eq(1)
|
75
|
+
expect(res).to be_valid
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should be valid if the directory exists' do
|
79
|
+
checkm = 'test_1 | dir'
|
80
|
+
res = Manifest.parse(checkm, path: 'spec/data')
|
81
|
+
expect(res.entries.size).to eq(1)
|
82
|
+
expect(res).to be_valid
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should be invalid if a file is missing' do
|
86
|
+
checkm = '2 | md5 | b026324c6904b2a9cb4b88d6d61c81d1'
|
87
|
+
res = Manifest.parse(checkm, path: 'spec/data/test_1')
|
88
|
+
expect(res.entries.size).to eq(1)
|
89
|
+
expect(res).not_to be_valid
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should be invalid if the checksum is different' do
|
93
|
+
checkm = '1 | md5 | zzz'
|
94
|
+
res = Manifest.parse(checkm, path: 'spec/data/test_1')
|
95
|
+
expect(res.entries.size).to eq(1)
|
96
|
+
expect(res).not_to be_valid
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe 'manipulate manifest' do
|
101
|
+
it 'should allow files to be added to an existing manifest' do
|
102
|
+
m = Manifest.parse('')
|
103
|
+
res = m.add('LICENSE.md')
|
104
|
+
expect(res.entries.size).to eq(1)
|
105
|
+
expect(res).to be_valid
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should be serializable to a string' do
|
110
|
+
m = Manifest.parse('')
|
111
|
+
n = m.add('LICENSE.md')
|
112
|
+
lines = n.to_s.split "\n"
|
113
|
+
expect(lines[0]).to eq('#%checkm_0.7')
|
114
|
+
expect(lines[1]).to match(/^LICENSE\.md/)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'parses a two-level manifest' do
|
118
|
+
m = Manifest.parse(File.read('spec/data/two-level-manifest.checkm'))
|
119
|
+
entries = m.entries
|
120
|
+
expect(entries.size).to eq(3)
|
121
|
+
entry = entries[2]
|
122
|
+
expect(entry.sourcefileorurl).to eq('@myfirst.checkm')
|
123
|
+
end
|
124
|
+
|
125
|
+
describe :remove do
|
126
|
+
attr_reader :original
|
127
|
+
attr_reader :modified
|
128
|
+
|
129
|
+
before(:each) do
|
130
|
+
@original = Manifest.parse(File.read('spec/data/two-level-manifest.checkm'))
|
131
|
+
@modified = original.remove('foo.bar')
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'removes entries by name' do
|
135
|
+
expect(modified.entries.size).to eq(1)
|
136
|
+
expect(modified.entries[0].sourcefileorurl).to eq('@myfirst.checkm')
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'does not modify the original' do
|
140
|
+
expect(original.entries.size).to eq(3)
|
141
|
+
expect(original.entries[0].sourcefileorurl).to eq('foo.bar')
|
142
|
+
expect(original.entries[1].sourcefileorurl).to eq('foo.bar')
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe :to_h do
|
147
|
+
it 'returns a hash of entries by source' do
|
148
|
+
manifest = Manifest.parse(File.read('spec/data/two-level-manifest.checkm'))
|
149
|
+
h = manifest.to_h
|
150
|
+
manifest.entries.each do |e|
|
151
|
+
expect(h[e.sourcefileorurl]).to include(e)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|