bonobot 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 06ccb8b5b500887ae4d039b56d507d9c4c3b949ebf82c0b9213f154689832354
4
- data.tar.gz: 725a0102e557cde864e780396d2ac713ac6446059ab049a9c8acd555c9ea4e00
3
+ metadata.gz: 043e3c7bff916ce8127eb9e341d98f1749cd309fb76c0cabd279c3e0dc05c720
4
+ data.tar.gz: cc48089c16b0a0a6848b003206746b00afa45976c155845084c209d11ba03e6e
5
5
  SHA512:
6
- metadata.gz: 108229c0e785c832dbc0cc727348b6586ca860d110bf06e8f300b3658b9774c1edc15de024e63f0877328846c682484697998db3633422ea8e95d9ee9f2f480d
7
- data.tar.gz: 749c8b17db41e4c317dbaf5adca0ea13d770f09345e8fc787c7121c34d50c76a6f2eb357c42d4483189170e30e92f8a1d686651cf4b73151f82dffd569b0f54e
6
+ metadata.gz: ceaaab01aa8335bcf7b74cdea321e3f13c50b2cd1f69ac8fedebce56aa136b4da4957ac2a17da2d9def1f0c2227902d0fc39a9cad6a9ebfb3bc4d99a1e58e58d
7
+ data.tar.gz: 81e78cd4498b5eb12bbcdaeea95149adf7f4e5b0d95c3ec2ab518595b992f3c311100a3db4612ca555796263ab2833b1a8c0af28e3c5aa7254cfb190a00c9b68
data/README.md CHANGED
@@ -1,8 +1,31 @@
1
- # Bonobo
2
- Short description and motivation.
1
+ # Bonobot
2
+ ![ci_cd](https://github.com/armandfardeau/bonobot/actions/workflows/ci_cd.yml/badge.svg)
3
+ [![codecov](https://codecov.io/gh/armandfardeau/bonobot/branch/master/graph/badge.svg?token=274POQGBAK)](https://codecov.io/gh/armandfardeau/bonobot)
4
+
5
+ BonoBot is a Ruby gem that helps with Rails monkey patching.
3
6
 
4
7
  ## Usage
5
- How to use my plugin.
8
+ ### Status
9
+ #### Generate all status:
10
+ ```bash
11
+ bundle exec rake bonobot: status
12
+ ```
13
+ #### Generate a specific status:
14
+ ```bash
15
+ bundle exec rake bonobot:status:out_of_date
16
+ bundle exec rake bonobot:status:up_to_date
17
+ bundle exec rake bonobot:update_out_of_date
18
+ ```
19
+
20
+ ### Add missing
21
+ ```bash
22
+ bundle exec rake bonobot:add_missing
23
+ ```
24
+
25
+ ### Update out of date
26
+ ```bash
27
+ bundle exec rake bonobot:update_out_of_date
28
+ ```
6
29
 
7
30
  ## Installation
8
31
  Add this line to your application's Gemfile:
@@ -11,18 +34,16 @@ Add this line to your application's Gemfile:
11
34
  gem 'bonobot'
12
35
  ```
13
36
 
14
- And then execute:
15
- ```bash
16
- $ bundle
17
- ```
18
-
19
37
  Or install it yourself as:
38
+
20
39
  ```bash
21
- $ gem install bonobot
40
+ gem install bonobot
22
41
  ```
23
42
 
24
43
  ## Contributing
44
+
25
45
  Contribution directions go here.
26
46
 
27
47
  ## License
28
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
48
+
49
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bonobot
4
+ class Annotator
5
+ def self.add_annotation(path, fingerprint)
6
+ new(path, fingerprint).add_annotation
7
+ end
8
+
9
+ def self.update_annotation(path, fingerprint)
10
+ new(path, fingerprint).update_annotation
11
+ end
12
+
13
+ def initialize(path, fingerprint)
14
+ @path = path
15
+ @fingerprint = fingerprint
16
+ end
17
+
18
+ def add_annotation
19
+ f = File.read(@path).split("\n")
20
+
21
+ if f.first == "# frozen_string_literal: true"
22
+ f.insert(1, "\n#{annotation}")
23
+ else
24
+ f.insert(0, "\n#{annotation}")
25
+ end
26
+
27
+ File.write(@path, "#{f.join("\n")}\n")
28
+ end
29
+
30
+ def update_annotation
31
+ f = File.read(@path).split("\n")
32
+
33
+ f.each_with_index do |line, index|
34
+ f[index] = annotation if match_line(line)
35
+ end
36
+
37
+ File.write(@path, "#{f.join("\n")}\n")
38
+ end
39
+
40
+ def annotation
41
+ if @path.to_s.end_with?(".erb")
42
+ "<%# bonobot_fingerprint: #{@fingerprint} %>"
43
+ else
44
+ "# bonobot_fingerprint: #{@fingerprint}"
45
+ end
46
+ end
47
+
48
+ def match_line(line)
49
+ line.include?("# bonobot_fingerprint") || line.include?("<%# bonobot_fingerprint")
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bonobot
4
+ class EngineFile
5
+ attr_reader :path, :engine_name, :short_path, :root_path
6
+
7
+ def initialize(path, engine)
8
+ @path = path
9
+ @root_path = engine.instance.root
10
+ @engine_name = engine_to_name(engine)
11
+ @short_path = path.sub("#{@root_path}/", "")
12
+ end
13
+
14
+ def fingerprint
15
+ Digest::MD5.hexdigest(File.read(@path))
16
+ end
17
+
18
+ def to_hash
19
+ instance_values.merge({ "fingerprint" => fingerprint })
20
+ end
21
+
22
+ private
23
+
24
+ def engine_to_name(engine_class)
25
+ if engine_class.respond_to?(:railtie_namespace) && engine_class.railtie_namespace
26
+ engine_class.railtie_namespace.to_s.split("::").map(&:underscore).join("/")
27
+ else
28
+ engine_class.engine_name.sub("_engine", "")
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bonobot
4
+ class EnginesFilesRegistry
5
+ def self.all
6
+ @all ||= deduplicate(generate)
7
+ end
8
+
9
+ def self.generate
10
+ Parallel.flat_map(::Rails::Engine.subclasses) do |klass|
11
+ Dir.glob(root(klass.instance.root).join("**", "*.{erb,rb}")).map do |path|
12
+ EngineFile.new(path, klass)
13
+ end
14
+ end
15
+ end
16
+
17
+ def self.deduplicate(engine_files)
18
+ engine_files.group_by(&:path).map { |_, files| files.min_by(&:engine_name) }
19
+ end
20
+
21
+ def self.find_by(attributes)
22
+ all.select do |local_file|
23
+ attributes.all? do |key, value|
24
+ local_file.try(key) == value
25
+ end
26
+ end
27
+ end
28
+
29
+ def self.output
30
+ all.map(&:as_json)
31
+ end
32
+
33
+ def self.root(path)
34
+ Pathname.new(path).join("app")
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bonobot/overloads_registry"
4
+ require "bonobot/annotator"
5
+
6
+ module Bonobot
7
+ class FilesOp
8
+ def self.missing
9
+ OverloadsRegistry.find_by(status: :missing)
10
+ end
11
+
12
+ def self.out_of_date
13
+ OverloadsRegistry.find_by(status: :out_of_date)
14
+ end
15
+
16
+ def self.add_missing
17
+ missing.each do |overload|
18
+ Annotator.annotate(root.join(overload.path), overload.engine_file.fingerprint)
19
+ end
20
+ end
21
+
22
+ def self.update_out_of_date
23
+ out_of_date.each do |overload|
24
+ Annotator.update_annotation(root.join(overload.path), overload.engine_file.fingerprint)
25
+ end
26
+ end
27
+
28
+ def self.root
29
+ ::Rails.root
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bonobot
4
+ class LocalFile
5
+ attr_reader :path
6
+
7
+ def initialize(path, root)
8
+ @path = path.sub("#{root}/", "")
9
+ end
10
+
11
+ def annotation
12
+ File.readlines(@path).map do |line|
13
+ line.sub(/# bonobot_fingerprint:/, "").sub("<%", "").sub("%>", "").strip if line.match?(/# bonobot_fingerprint:/) || line.match?(/<%# bonobot_fingerprint:/)
14
+ end.compact.first.presence
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parallel"
4
+
5
+ module Bonobot
6
+ class LocalFilesRegistry
7
+ def self.all
8
+ @all ||= Parallel.map(Dir.glob(root.join("**", "*.{erb,rb}"))) do |path|
9
+ LocalFile.new(path, rails_root)
10
+ end
11
+ end
12
+
13
+ def self.root
14
+ rails_root.join("app")
15
+ end
16
+
17
+ def self.rails_root
18
+ ::Rails.root
19
+ end
20
+
21
+ def self.output
22
+ all.map(&:as_json)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bonobot
4
+ class Overload
5
+ attr_reader :engine_file
6
+
7
+ def initialize(local_file, engine_file)
8
+ @local_file = local_file
9
+ @engine_file = engine_file
10
+ end
11
+
12
+ def path
13
+ @local_file.path
14
+ end
15
+
16
+ def status
17
+ return :missing if @local_file.annotation.nil?
18
+ return :up_to_date if @local_file.annotation == @engine_file.fingerprint
19
+
20
+ :out_of_date
21
+ end
22
+
23
+ def to_hash
24
+ instance_values.merge({ "status" => status, "path" => path })
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bonobot
4
+ module OverloadsRegistry
5
+ def self.all
6
+ @all ||= LocalFilesRegistry.all.flat_map do |local_file|
7
+ EnginesFilesRegistry.find_by(short_path: local_file.path).map do |engine_file|
8
+ Overload.new(local_file, engine_file)
9
+ end
10
+ end
11
+ end
12
+
13
+ # TODO: Extract to module
14
+ def self.find_by(attributes)
15
+ all.select do |item|
16
+ attributes.all? do |key, value|
17
+ item.try(key) == value
18
+ end
19
+ end
20
+ end
21
+
22
+ def self.output
23
+ all.map(&:as_json)
24
+ end
25
+ end
26
+ end
@@ -4,43 +4,52 @@ require "json"
4
4
 
5
5
  module Bonobot
6
6
  class Status
7
- def self.generate
7
+ STATUS = { up_to_date: "🥳", out_of_date: "😱", missing: "🤬" }.freeze
8
+
9
+ def self.generate(status = nil)
8
10
  puts "-----"
9
11
  puts "🙈 🙉 🙊 Bonobot 🙈 🙉 🙊"
10
12
  puts "-----"
11
13
  puts "🛠 Generating status"
12
- File.write("status.json", JSON.pretty_generate({ rails_files: LocalFiles.files, engines_files: EnginesFiles.files, overloads: Overloads.files }))
14
+ File.write("status.json", status_json)
13
15
  puts File.expand_path("status.json")
14
16
  puts "-----"
15
17
 
16
- unless Overloads.status(:up_to_date).empty?
17
- puts "🥳 Up to date fingerprint count: #{Overloads.status(:up_to_date).count}"
18
- puts "-> Up to date fingerprint: #{present(Overloads.status(:up_to_date))}"
19
- puts ""
20
- end
21
-
22
- unless Overloads.status(:out_of_date).empty?
23
- puts "😱 Out of date fingerprint count: #{Overloads.status(:out_of_date).count}"
24
- puts "-> Out of date fingerprint: #{present(Overloads.status(:out_of_date))}"
25
- puts ""
26
- end
27
-
28
- unless Overloads.status(:missing).empty?
29
- puts "🤬 Files missing fingerprint count: #{Overloads.status(:missing).count}"
30
- puts "-> Missing fingerprint: #{present(Overloads.status(:missing))}"
31
- puts ""
18
+ if status
19
+ generate_status(status.to_sym, STATUS[status.to_sym])
20
+ else
21
+ STATUS.each do |status_type, emoji|
22
+ generate_status(status_type, emoji)
23
+ end
32
24
  end
33
25
 
34
26
  puts "-----"
35
- Overloads.status(:out_of_date).empty? && Overloads.status(:missing).empty?
27
+ OverloadsRegistry.find_by(status: :out_of_date).empty? && OverloadsRegistry.find_by(status: :missing).empty?
36
28
  end
37
29
 
38
- def self.present(entry)
39
- entries = entry.map do |(engine_name, source_path)|
40
- " - #{engine_name}: #{source_path[:short_path]} (#{source_path[:fingerprint]})"
30
+ def self.present(entries)
31
+ entries.map do |entry|
32
+ " - #{entry.engine_file.engine_name}: #{entry.engine_file.short_path} (#{entry.engine_file.fingerprint})"
41
33
  end.join("\n")
34
+ end
35
+
36
+ def self.generate_status(status, emoji)
37
+ return if OverloadsRegistry.find_by(status: status).empty?
38
+
39
+ overload_status = OverloadsRegistry.find_by(status: status)
40
+ status_to_text = status.to_s.capitalize.gsub("_", " ")
41
+
42
+ puts "-> #{emoji} #{status_to_text} fingerprint (#{overload_status.count}):"
43
+ puts present(OverloadsRegistry.find_by(status: status))
44
+ puts ""
45
+ end
42
46
 
43
- "\n#{entries}"
47
+ def self.status_json
48
+ JSON.pretty_generate({
49
+ rails_files: LocalFilesRegistry.output,
50
+ engines_files: EnginesFilesRegistry.output,
51
+ overloads: OverloadsRegistry.output
52
+ })
44
53
  end
45
54
  end
46
55
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bonobot
4
- VERSION = "0.0.5"
4
+ VERSION = "0.0.7"
5
5
  end
data/lib/bonobot.rb CHANGED
@@ -4,7 +4,12 @@ require "bonobot/railtie"
4
4
 
5
5
  module Bonobot
6
6
  autoload :Status, "bonobot/status"
7
- autoload :LocalFiles, "bonobot/local_files"
8
- autoload :EnginesFiles, "bonobot/engines_files"
9
- autoload :Overloads, "bonobot/overloads"
7
+ autoload :LocalFilesRegistry, "bonobot/local_files_registry"
8
+ autoload :LocalFile, "bonobot/local_file"
9
+ autoload :EnginesFilesRegistry, "bonobot/engines_files_registry"
10
+ autoload :EngineFile, "bonobot/engine_file"
11
+ autoload :OverloadsRegistry, "bonobot/overloads_registry"
12
+ autoload :Overload, "bonobot/overload"
13
+ autoload :FilesOp, "bonobot/files_op"
14
+ autoload :Annotator, "bonobot/annotator"
10
15
  end
@@ -6,4 +6,38 @@ namespace :bonobot do
6
6
  status = Bonobot::Status.generate
7
7
  exit 1 unless status
8
8
  end
9
+
10
+ namespace :status do
11
+ desc "Generate status for out of date"
12
+ task out_of_date: :environment do
13
+ Bonobot::Status.generate(:out_of_date)
14
+ end
15
+
16
+ task outdated: :out_of_date
17
+
18
+ desc "Generate status for missing"
19
+ task missing: :environment do
20
+ Bonobot::Status.generate(:missing)
21
+ end
22
+
23
+ desc "Generate status for up to date"
24
+ task up_to_date: :environment do
25
+ Bonobot::Status.generate(:up_to_date)
26
+ end
27
+
28
+ task uptodate: :up_to_date
29
+ end
30
+
31
+ desc "Add missing fingerprint to local files"
32
+ task add_missing: :environment do
33
+ Bonobot::FilesOp.add_missing
34
+ end
35
+
36
+ desc "Update out of date fingerprint to local files"
37
+ task update_out_of_date: :environment do
38
+ Bonobot::FilesOp.update_out_of_date
39
+ end
40
+
41
+ task update_outdated: :update_out_of_date
42
+ task update: :update_out_of_date
9
43
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bonobot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - armandfardeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-06 00:00:00.000000000 Z
11
+ date: 2023-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: parallel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.22.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.22.1
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rails
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,20 +52,34 @@ dependencies:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
54
  version: '11.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: factory_bot
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 6.2.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 6.2.1
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rspec
43
71
  requirement: !ruby/object:Gem::Requirement
44
72
  requirements:
45
- - - ">="
73
+ - - "~>"
46
74
  - !ruby/object:Gem::Version
47
- version: '0'
75
+ version: 3.12.0
48
76
  type: :development
49
77
  prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
- - - ">="
80
+ - - "~>"
53
81
  - !ruby/object:Gem::Version
54
- version: '0'
82
+ version: 3.12.0
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: rubocop
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -98,16 +126,30 @@ dependencies:
98
126
  name: simplecov
99
127
  requirement: !ruby/object:Gem::Requirement
100
128
  requirements:
101
- - - ">="
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.21.2
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.21.2
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov-cobertura
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
102
144
  - !ruby/object:Gem::Version
103
- version: '0'
145
+ version: 2.1.0
104
146
  type: :development
105
147
  prerelease: false
106
148
  version_requirements: !ruby/object:Gem::Requirement
107
149
  requirements:
108
- - - ">="
150
+ - - "~>"
109
151
  - !ruby/object:Gem::Version
110
- version: '0'
152
+ version: 2.1.0
111
153
  description: Description of Bonobot.
112
154
  email:
113
155
  - fardeauarmand@gmail.com
@@ -119,9 +161,14 @@ files:
119
161
  - README.md
120
162
  - Rakefile
121
163
  - lib/bonobot.rb
122
- - lib/bonobot/engines_files.rb
123
- - lib/bonobot/local_files.rb
124
- - lib/bonobot/overloads.rb
164
+ - lib/bonobot/annotator.rb
165
+ - lib/bonobot/engine_file.rb
166
+ - lib/bonobot/engines_files_registry.rb
167
+ - lib/bonobot/files_op.rb
168
+ - lib/bonobot/local_file.rb
169
+ - lib/bonobot/local_files_registry.rb
170
+ - lib/bonobot/overload.rb
171
+ - lib/bonobot/overloads_registry.rb
125
172
  - lib/bonobot/railtie.rb
126
173
  - lib/bonobot/status.rb
127
174
  - lib/bonobot/version.rb
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EnginesFiles
4
- def self.files
5
- @files ||= ::Rails::Engine.subclasses.each_with_object({}) do |klass, hash|
6
- paths = Dir.glob("#{klass.instance.root}/app/**/*.{erb,rb}")
7
- next if paths.empty?
8
-
9
- hash[engine_to_name(klass)] = engine_paths(paths)
10
- end
11
- end
12
-
13
- def self.engine_to_name(engine_class)
14
- if engine_class.respond_to?(:railtie_namespace) && engine_class.railtie_namespace
15
- engine_class.railtie_namespace.to_s.split("::").map(&:underscore).join("/")
16
- else
17
- engine_class.engine_name.sub("_engine", "")
18
- end
19
- end
20
-
21
- def self.engine_paths(paths)
22
- paths.each_with_object({}) do |path, hash|
23
- _name, *short_path = path.sub(gems_dir, "").split("/")
24
- hash[short_path.join("/")] = { path: path, fingerprint: fingerprint(path) }
25
- end
26
- end
27
-
28
- def self.gems_dir
29
- @gems_dir ||= "#{Bundler.rubygems.gem_dir}/gems/"
30
- end
31
-
32
- def self.fingerprint(path)
33
- Digest::MD5.hexdigest(File.read(path))
34
- end
35
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module LocalFiles
4
- def self.files
5
- @files ||= Dir.glob(::Rails.root.join("app", "**", "*.{erb,rb}")).map { |path| path.sub("#{::Rails.root}/", "") }.each_with_object({}) do |path, hash|
6
- hash[path] = read_annotation(path)
7
- end
8
- end
9
-
10
- def self.read_annotation(path)
11
- File.readlines(path).map do |line|
12
- line.sub(/# bonobot_fingerprint:/, "").sub("<%", "").sub("%>", "").strip if line.match?(/# bonobot_fingerprint:/) || line.match?(/<%# bonobot_fingerprint:/)
13
- end.compact.first.presence
14
- end
15
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Overloads
4
- def self.files
5
- @files ||= LocalFiles.files.each_with_object({}) do |(path, fingerprint), hash|
6
- EnginesFiles.files.keys.each do |engine_name|
7
- next unless path.include? engine_name
8
-
9
- source_path = EnginesFiles.files[engine_name].fetch(path, nil)
10
- next unless source_path
11
-
12
- result = [engine_name, source_path.merge(short_path: path)]
13
-
14
- key = status_key(source_path[:fingerprint], fingerprint)
15
- if hash[key].nil?
16
- hash[key] = [result]
17
- else
18
- hash[key] << result
19
- end
20
- end
21
- end
22
- end
23
-
24
- def self.status_key(source_fingerprint, target_fingerprint)
25
- return :up_to_date if source_fingerprint == target_fingerprint
26
- return :missing if target_fingerprint.nil?
27
-
28
- :out_of_date
29
- end
30
-
31
- def self.status(status)
32
- files.fetch(status, [])
33
- end
34
- end