fingerprint 1.4.0 → 3.0.1

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.
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:test)
5
+
6
+ task :default => :test
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # Copyright (c) 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
3
+ # Copyright, 2016, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -20,201 +20,10 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'optparse'
24
- require 'pathname'
25
- require 'fingerprint'
26
- require 'fileutils'
23
+ # This script takes a given path, and renames it with the given format.
24
+ # It then ensures that there is a symlink called "latest" that points
25
+ # to the renamed directory.
27
26
 
28
- OPTIONS = {
29
- :root => "./",
30
- :mode => :scan,
31
- :output => $stdout,
32
- :verbose => false,
33
- :force => false,
34
- :name => "index.fingerprint",
35
- :extended => false,
36
- :checksums => Fingerprint::DEFAULT_CHECKSUMS,
37
- :additions => false,
38
- :failures => :ignore,
39
- }
27
+ require_relative '../lib/fingerprint/command'
40
28
 
41
- ARGV.options do |o|
42
- script_name = File.basename($0)
43
-
44
- o.banner = "Usage: #{script_name} [options] [path]"
45
- o.define_head "This script is used to create and compare file system fingerprints."
46
-
47
- o.separator ""
48
- o.separator "Directory analysis and verification:"
49
-
50
- o.on("-a", "--analyze [path]", String, "Generage a fingerprint of the given path and save it for later verification.") do |path|
51
- OPTIONS[:mode] = :analyze
52
- OPTIONS[:root] = path if path
53
- end
54
-
55
- o.on("-v", "--verify [path]", String, "Verify a given path based on a previously saved fingerprint.") do |path|
56
- OPTIONS[:mode] = :verify
57
- OPTIONS[:root] = path if path
58
- end
59
-
60
- o.on("-n name", String, "Specify the name of the fingerprint file.", "Default: #{OPTIONS[:name]}") do |name|
61
- OPTIONS[:name] = name
62
- end
63
-
64
- o.on("-f", "Force any operation to complete despite warnings.") do
65
- OPTIONS[:force] = true
66
- end
67
-
68
- o.separator ""
69
-
70
- o.on("-x", "Include additional extended information about files and directories.") do
71
- OPTIONS[:extended] = true
72
- end
73
-
74
- o.on("-s [checksum1,checksum2]", "Provide a list of the checksum algorithms to use.", "Available: #{Fingerprint::CHECKSUMS.keys.join(', ')}; Default: #{OPTIONS[:checksums].join(', ')}") do |checksums|
75
- OPTIONS[:checksums] = checksums.split(/[\s,]+/)
76
- end
77
-
78
- o.separator ""
79
- o.separator "Compare fingerprints:"
80
-
81
- o.on("-c", "Compare the given fingerprints. Check that the second fingerprint is a superset of the first.") do
82
- OPTIONS[:mode] = :check
83
- end
84
-
85
- o.on("-A", "Report files that have been added to the second fingerprint.") do
86
- OPTIONS[:additions] = true
87
- end
88
-
89
- o.separator ""
90
- o.separator "Output manipulation:"
91
-
92
- o.on("-o [output-path]", String, "Write the fingerprint output to the given file.") do |path|
93
- OPTIONS[:output] = File.open(path, "w")
94
- end
95
-
96
- o.on("--verbose", "Verbose output, include additional details in the file transcript.") do
97
- OPTIONS[:verbose] = true
98
- end
99
-
100
- o.on("--progress", "Print percentage progress to standard error.") do
101
- OPTIONS[:progress] = true
102
- end
103
-
104
- o.on("--die", "Give a non-zero exit code if errors are detected by check or verify.") do
105
- OPTIONS[:failures] = :die
106
- end
107
-
108
- o.separator ""
109
- o.separator "Help and Copyright information:"
110
-
111
- o.on_tail("--copy", "Display copyright and warranty information") do
112
- $stderr.puts "#{script_name} v#{Fingerprint::VERSION}. Copyright (c) 2011 Samuel Williams."
113
- $stderr.puts "This software is released under the MIT license and comes with ABSOLUTELY NO WARRANTY."
114
- $stderr.puts "See http://www.oriontransfer.co.nz/ for more information."
115
- exit
116
- end
117
-
118
- o.on_tail("-h", "--help", "Show this help message.") do
119
- $stderr.puts o
120
- exit
121
- end
122
- end.parse!
123
-
124
- unless File.directory? OPTIONS[:root]
125
- $stderr.puts "Path #{OPTIONS[:root]} doesn't exist!"
126
- exit(255)
127
- end
128
-
129
- if OPTIONS[:checksums].size == 0
130
- OPTIONS[:checksums] = ['MD5', 'SHA2.256']
131
- end
132
-
133
- def finish_check(error_count)
134
- if error_count == 0
135
- $stderr.puts "Data verified, 0 errors found."
136
- exit(0)
137
- else
138
- $stderr.puts "Data inconsistent, #{error_count} errors found!"
139
- exit(OPTIONS[:failures] == :die ? 1 : 0)
140
- end
141
- end
142
-
143
- case (OPTIONS[:mode])
144
- when :analyze
145
- output_file = Pathname.new(OPTIONS[:root]) + OPTIONS[:name]
146
-
147
- if output_file.exist? && !OPTIONS[:force]
148
- $stderr.puts "Output file #{output_file} already exists. Aborting."
149
- exit(2)
150
- end
151
-
152
- options = OPTIONS.dup
153
- options[:excludes] = [OPTIONS[:name]]
154
-
155
- finished = false
156
- begin
157
- File.open(output_file, "w") do |io|
158
- options[:output] = io
159
-
160
- Fingerprint::Scanner.scan_paths([OPTIONS[:root]], options)
161
- end
162
- finished = true
163
- ensure
164
- FileUtils.rm(output_file) unless finished
165
- end
166
- when :verify
167
- error_count = 0
168
-
169
- input_file = Pathname.new(OPTIONS[:root]) + OPTIONS[:name]
170
-
171
- unless File.exist? input_file
172
- $stderr.puts "Can't find index #{input_file}. Aborting."
173
- exit(3)
174
- end
175
-
176
- options = OPTIONS.dup
177
-
178
- master = Fingerprint::RecordSet.new
179
-
180
- File.open(input_file, "r") do |io|
181
- master.parse(io)
182
- end
183
-
184
- if master.configuration
185
- options.merge!(master.configuration.options)
186
- end
187
-
188
- scanner = Fingerprint::Scanner.new([OPTIONS[:root]], options)
189
- copy = Fingerprint::SparseRecordSet.new(scanner)
190
-
191
- error_count += Fingerprint::Checker::verify(master, copy, options)
192
-
193
- finish_check(error_count)
194
- when :scan
195
- roots = ARGV
196
- roots << Dir.pwd if roots.size == 0
197
-
198
- # Check that all supplied paths exist
199
- roots.delete_if do |root|
200
- if File.exist? root
201
- false
202
- else
203
- $stderr.puts "Path #{root} doesn't exist, skipping!"
204
- true
205
- end
206
- end
207
-
208
- options = OPTIONS.dup
209
-
210
- # Discard output once it has been written to disk:
211
- options[:recordset] = nil
212
-
213
- Fingerprint::Scanner.scan_paths(roots, options)
214
- when :check
215
- options = OPTIONS.dup
216
-
217
- error_count = Fingerprint::Checker.check_files(ARGV[0], ARGV[1], options)
218
-
219
- finish_check(error_count)
220
- end
29
+ Fingerprint::Command.call
@@ -1,7 +1,5 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'fingerprint/version'
1
+
2
+ require_relative 'lib/fingerprint/version'
5
3
 
6
4
  Gem::Specification.new do |spec|
7
5
  spec.name = "fingerprint"
@@ -20,8 +18,11 @@ Gem::Specification.new do |spec|
20
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
19
  spec.require_paths = ["lib"]
22
20
 
23
- spec.add_development_dependency "bundler", "~> 1.3"
24
- spec.add_development_dependency "rake"
21
+ spec.add_dependency "samovar", "~> 2.0"
22
+ spec.add_dependency "build-files", "~> 1.2"
25
23
 
26
- spec.add_dependency "lockfile"
24
+ spec.add_development_dependency "covered"
25
+ spec.add_development_dependency "bundler"
26
+ spec.add_development_dependency "rspec", "~> 3.4"
27
+ spec.add_development_dependency "rake"
27
28
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
1
+ # Copyright, 2011, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the "Software"), to deal
@@ -25,7 +25,7 @@ require 'fingerprint/checker'
25
25
 
26
26
  module Fingerprint
27
27
  # A helper function to check two paths for consistency. Provides callback from +Fingerprint::Checker+.
28
- def self.check_paths(master_path, copy_path, &block)
28
+ def self.check_paths(master_path, copy_path, **options, &block)
29
29
  master = Scanner.new([master_path])
30
30
  copy = Scanner.new([copy_path])
31
31
 
@@ -34,10 +34,23 @@ module Fingerprint
34
34
 
35
35
  master.scan(master_recordset)
36
36
 
37
- checker = Checker.new(master_recordset, copy_recordset)
37
+ checker = Checker.new(master_recordset, copy_recordset, **options)
38
38
 
39
39
  checker.check(&block)
40
40
 
41
41
  return checker
42
42
  end
43
+
44
+ # Returns true if the given paths contain identical files. Useful for expectations, e.g. `expect(Fingerprint).to be_identical(source, destination)`
45
+ def self.identical?(source, destination, &block)
46
+ failures = 0
47
+
48
+ check_paths(source, destination) do |record, name, message|
49
+ failures += 1
50
+
51
+ yield(record) if block_given?
52
+ end
53
+
54
+ return failures == 0
55
+ end
43
56
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
1
+ # Copyright, 2011, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the "Software"), to deal
@@ -31,7 +31,7 @@ module Fingerprint
31
31
  #
32
32
  # Master and copy are +IO+ objects corresponding to the output produced by +Fingerprint::Scanner+.
33
33
  class Checker
34
- def initialize(master, copy, options = {})
34
+ def initialize(master, copy, **options)
35
35
  @master = master
36
36
  @copy = copy
37
37
 
@@ -42,7 +42,7 @@ module Fingerprint
42
42
  attr :copy
43
43
 
44
44
  # Run the checking process.
45
- def check (&block)
45
+ def check(&block)
46
46
  # For every file in the src, we check that it exists
47
47
  # in the destination:
48
48
  total_count = @master.records.count
@@ -95,7 +95,7 @@ module Fingerprint
95
95
  # A list of files which either did not exist in the copy, or had the wrong checksum.
96
96
  attr :failures
97
97
 
98
- def self.check_files(master, copy, options = {}, &block)
98
+ def self.check_files(master, copy, **options, &block)
99
99
  # New API that takes two RecordSets...
100
100
 
101
101
  File.open(master) do |master_file|
@@ -106,13 +106,13 @@ module Fingerprint
106
106
  copy_recordset = RecordSet.new
107
107
  copy_recordset.parse(copy_file)
108
108
 
109
- verify(master_recordset, copy_recordset, options, &block)
109
+ verify(master_recordset, copy_recordset, **options, &block)
110
110
  end
111
111
  end
112
112
  end
113
113
 
114
114
  # Helper function to check two fingerprint files.
115
- def self.verify(master, copy, options = {}, &block)
115
+ def self.verify(master, copy, **options, &block)
116
116
  error_count = 0
117
117
 
118
118
  errors = options.delete(:recordset) || RecordSet.new
@@ -120,7 +120,7 @@ module Fingerprint
120
120
  errors = RecordSetPrinter.new(errors, options[:output])
121
121
  end
122
122
 
123
- checker = Checker.new(master, copy, options)
123
+ checker = Checker.new(master, copy, **options)
124
124
 
125
125
  checker.check do |record, result, message|
126
126
  error_count += 1
@@ -0,0 +1,33 @@
1
+ # Copyright, 2016, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ # This script takes a given path, and renames it with the given format.
22
+ # It then ensures that there is a symlink called "latest" that points
23
+ # to the renamed directory.
24
+
25
+ require 'samovar'
26
+
27
+ module Fingerprint
28
+ module Checksums
29
+ def self.call(result)
30
+ result.split(/\s*,\s*/)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,90 @@
1
+ # Copyright, 2016, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ # This script takes a given path, and renames it with the given format.
22
+ # It then ensures that there is a symlink called "latest" that points
23
+ # to the renamed directory.
24
+
25
+ require 'samovar'
26
+
27
+ require_relative 'scanner'
28
+
29
+ require_relative 'command/scan'
30
+ require_relative 'command/analyze'
31
+ require_relative 'command/verify'
32
+ require_relative 'command/compare'
33
+ require_relative 'command/duplicates'
34
+
35
+ module Fingerprint
36
+ module Command
37
+ def self.call(*args)
38
+ Top.call(*args)
39
+ end
40
+
41
+ class Top < Samovar::Command
42
+ self.description = "A file checksum analysis and verification tool."
43
+
44
+ options do
45
+ option '--root <path>', "Work in the given root directory."
46
+
47
+ option '-o/--output <path>', "Output the transcript to a specific file rather than stdout."
48
+
49
+ option '-h/--help', "Print out help information."
50
+ option '-v/--version', "Print out the application version."
51
+ end
52
+
53
+ def chdir(&block)
54
+ if root = @options[:root]
55
+ Dir.chdir(root, &block)
56
+ else
57
+ yield
58
+ end
59
+ end
60
+
61
+ def output
62
+ if path = @options[:output]
63
+ File.open(path, "w")
64
+ else
65
+ $stdout
66
+ end
67
+ end
68
+
69
+ nested :command, {
70
+ 'scan' => Scan,
71
+ 'analyze' => Analyze,
72
+ 'verify' => Verify,
73
+ 'compare' => Compare,
74
+ 'duplicates' => Duplicates
75
+ }, default: 'analyze'
76
+
77
+ def call
78
+ if @options[:version]
79
+ puts "fingerprint v#{VERSION}"
80
+ elsif @options[:help]
81
+ self.print_usage(program_name)
82
+ else
83
+ chdir do
84
+ @command.call
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end