bonobot 0.0.5 → 0.0.7

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 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