rodiff 1.1.1 → 1.2.0

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: cfe33a330e01762950e63f01ab0aa8483ab977fd2f8bf877569d3316d123a485
4
- data.tar.gz: f55f992a4d310079ef48662e18ed3c1263737e5d819f218327428ab285e0e907
3
+ metadata.gz: 864417eae37667c26264ea7de3365d12511c4069d89e83c859641de7c00c22cc
4
+ data.tar.gz: 5cc69618a1b4893e10d428a387e85f813b26278496f2601abc5315113726e3a3
5
5
  SHA512:
6
- metadata.gz: c1fe536f649c2d11ab3a40d9f4dc1eb1697e04c9fa281553e4eb9663f0ab2fef0e575b461a5535c81a639014ad74a2a7727ac54b50d26235b7299f0d78c624ce
7
- data.tar.gz: 4fd2a372a6e419ecd9fd660704d210f33bdc6a82c09be655475607086bc9f0f7da828d35839e75862f7aa1eaa062986ea64c2a095d22ca5bd91c5e3406020e8c
6
+ metadata.gz: f77b00f02f5f934de75c153c82c8000641a8e1f6e8edebab6f56c0f42af3a34179ca3796a49f82506747934d6f1cc1d34fed2e027290febad530ca92e5630321
7
+ data.tar.gz: 3551ea66e08e3c8f65bd7ed32fc47f5a3b0681ebd08646edc313284dc9260e04c855a7a9c2cb7d3c7fc1e878f56d40c8fe1b95c06a51a9076a52296bec778357
data/README.md CHANGED
@@ -9,10 +9,9 @@ A ruby image comparison tool powered by [Odiff](https://github.com/dmtrKovalenko
9
9
 
10
10
  ## Motivation
11
11
 
12
- A strong candidate against the veteran players on the internet like [pixelmatch](https://github.com/mapbox/pixelmatch) and [ImageMagick](https://github.com/ImageMagick/ImageMagick)
13
-
14
12
  Impressive [benchmarks](https://github.com/dmtrKovalenko/odiff#benchmarks) from `Odiff`.
15
13
 
14
+ A strong candidate against the veteran players like [pixelmatch](https://github.com/mapbox/pixelmatch) and [ImageMagick](https://github.com/ImageMagick/ImageMagick)
16
15
 
17
16
  ## Getting Started
18
17
 
@@ -51,6 +50,63 @@ or, for relative paths like `./node_modules/.bin/odiff`:
51
50
  ODIFF_INSTALL_DIR=node_modules/.bin
52
51
  ```
53
52
 
53
+ ## Configuration
54
+
55
+ Rodiff automatically discovers and loads configuration from `.rodiff.yml` files in your project.
56
+
57
+ ### Configuration File Discovery
58
+
59
+ Rodiff searches for `.rodiff.yml` starting from the current directory and traversing upward to your home directory:
60
+
61
+ ```
62
+ /home/username/projects/myapp/src/tests/.rodiff.yml ← checks here first
63
+ /home/username/projects/myapp/src/.rodiff.yml
64
+ /home/username/projects/myapp/.rodiff.yml ← typically found here
65
+ /home/username/projects/.rodiff.yml
66
+ /home/username/.rodiff.yml ← stops here (home directory)
67
+ ```
68
+
69
+ ### Configuration Options
70
+
71
+ Create a `.rodiff.yml` file in your project root:
72
+
73
+ ```yaml
74
+ # File patterns for image comparison (supports glob patterns)
75
+ include_pattern: "screenshots/**/*.png"
76
+ exclude_pattern: "screenshots/archived/**"
77
+
78
+ # Comparison settings
79
+ color_threshold: 0.1 # 0.0 - 1.0 (lower = stricter)
80
+ ignore_antialiasing: false # Ignore antialiasing differences
81
+ output_diff_mask: false # Output black/white mask instead of diff image
82
+
83
+ # Error handling
84
+ fail_if_no_comparison: false # Exit with error if no images found
85
+ exit_code_error: 1 # Exit code for errors (not image differences)
86
+ ```
87
+
88
+ ### Programmatic Configuration
89
+
90
+ You can also configure Rodiff programmatically:
91
+
92
+ ```ruby
93
+ Rodiff.configure do |config|
94
+ config.include_pattern = "**/*.png"
95
+ config.color_threshold = 0.15
96
+ config.ignore_antialiasing = true
97
+ end
98
+ ```
99
+
100
+ Or override specific values:
101
+
102
+ ```ruby
103
+ config = Rodiff::Configuration.new
104
+ config.overrides(
105
+ color_threshold: 0.2,
106
+ output_diff_mask: true
107
+ )
108
+ ```
109
+
54
110
  ## Development
55
111
 
56
112
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "yaml"
3
4
  require "rodiff/error"
4
5
  require "rodiff/executable"
6
+ require "rodiff/helpers/file_finder"
5
7
 
6
8
  module Rodiff
7
9
  def self.configuration
@@ -15,6 +17,15 @@ module Rodiff
15
17
  class Configuration
16
18
  class UnknownConfiguration < Rodiff::Error; end
17
19
 
20
+ DOTFILE = ".rodiff.yml"
21
+ GEM_ROOT = if RUBY_VERSION >= "3.1"
22
+ File.dirname(__FILE__, 3).freeze
23
+ else
24
+ File.expand_path(File.join(File.dirname(__FILE__), "..", "..")).freeze
25
+ end
26
+ DEFAULT_CONFIG = File.join(GEM_ROOT, "config", "default.yml").freeze
27
+ SEARCH_ROOT = Dir.home.freeze
28
+
18
29
  ATTRS = Module.new.tap { |mod| include mod }
19
30
  READER_ATTRS = {
20
31
  default_dir: "/"
@@ -67,6 +78,9 @@ module Rodiff
67
78
 
68
79
  READER_ATTRS.each { |key, value| instance_variable_set("@#{key}", value) }
69
80
  ACCESSOR_ATTRS.each { |key, value| instance_variable_set("@#{key}", value) }
81
+
82
+ load_from_file(DEFAULT_CONFIG)
83
+ load_from_file(config_file_override) if config_file_override
70
84
  end
71
85
 
72
86
  def odiff_exe_path
@@ -84,6 +98,38 @@ module Rodiff
84
98
 
85
99
  private
86
100
 
101
+ def config_file_override(start_dir: Dir.pwd)
102
+ @config_file_override ||= begin
103
+ finder = Helpers::FileFinder.new("/")
104
+ finder.find_upwards(DOTFILE, start_dir, SEARCH_ROOT)
105
+ end
106
+ end
107
+
108
+ def load_from_file(path)
109
+ yml_config = YAML.load_file(path) if File.exist?(path)
110
+
111
+ if yml_config.is_a?(Hash)
112
+ yml_config.each do |key, value|
113
+ validate_config_key!(key.to_sym)
114
+ public_send("#{key}=", value) if respond_to?("#{key}=")
115
+ end
116
+ elsif empty_yml?(yml_config)
117
+ warn "Configuration file #{path} is empty"
118
+ else
119
+ warn "Configuration file #{path} must contain a Hash, got #{yml_config.class}"
120
+ end
121
+ rescue Psych::SyntaxError => e
122
+ raise Rodiff::Error, "Invalid YAML in #{path}: #{e.message}"
123
+ end
124
+
125
+ def empty_yml?(data)
126
+ # Ruby 2.7-3.0 with Psych 3.x
127
+ return data == false if RUBY_VERSION < "3.1"
128
+
129
+ # Ruby 3.1+ with Psych 4.x
130
+ data.nil?
131
+ end
132
+
87
133
  def validate_config_key!(key)
88
134
  return if READER_ATTRS.key?(key) || ACCESSOR_ATTRS.key?(key)
89
135
 
@@ -94,5 +140,40 @@ module Rodiff
94
140
  validate_config_key!(key)
95
141
  @config_overrides.fetch(key, &block)
96
142
  end
143
+
144
+ def files_from_dir(dir)
145
+ included_files = files_from_glob(file_glob_pattern(dir, include_pattern))
146
+ excluded_files = files_from_glob(file_glob_pattern(dir, exclude_pattern))
147
+ (included_files - excluded_files).uniq
148
+ end
149
+
150
+ def files_from_glob(file_glob)
151
+ files = Dir.glob(file_glob)
152
+ files.map { |file| File.expand_path(file) }.sort
153
+ end
154
+
155
+ def file_glob_pattern(path, pattern)
156
+ trimmed = "{#{pattern.gsub(%r{\s*,\s*}, ",")}}"
157
+ return trimmed if pattern =~ %r{^(\./)?#{Regexp.escape(path)}} || absolute_pattern?(pattern)
158
+
159
+ File.join(path, trimmed)
160
+ end
161
+
162
+ def absolute_pattern?(pattern)
163
+ return pattern.start_with?(File::Separator) unless windows?
164
+ return false unless File::ALT_SEPARATOR
165
+
166
+ win_absolute_pattern = %r{\A\w+:#{Regexp.escape(File::ALT_SEPARATOR)}}.match?(pattern)
167
+ win_network_pattern = pattern.start_with?(File::ALT_SEPARATOR * 2)
168
+ win_absolute_pattern || win_network_pattern
169
+ end
170
+
171
+ def windows?
172
+ @windows ||= begin
173
+ require "rbconfig"
174
+ os = RbConfig::CONFIG["host_os"]
175
+ os.match?(%r{mingw})
176
+ end
177
+ end
97
178
  end
98
179
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rodiff
4
+ module Helpers
5
+ class FileFinder
6
+ attr_reader :root_dir
7
+
8
+ def initialize(root)
9
+ @root_dir = root
10
+ end
11
+
12
+ def find_upwards(filename, start_dir, stop_dir = nil)
13
+ traverse_upwards(filename, start_dir, stop_dir) { |file| return file if file } # return first result
14
+ end
15
+
16
+ def find_top_most(filename, start_dir, stop_dir = nil)
17
+ top_most_file = nil
18
+ traverse_upwards(filename, start_dir, stop_dir) { |file| top_most_file = file }
19
+ top_most_file
20
+ end
21
+
22
+ private
23
+
24
+ def traverse_upwards(filename, start_dir, stop_dir)
25
+ start = Pathname.new(start_dir).expand_path
26
+ root = Pathname.new(root_dir).expand_path
27
+ return unless start.to_s.start_with?(root.to_s)
28
+
29
+ stop = Pathname.new(stop_dir).expand_path if stop_dir
30
+ start.ascend do |dir|
31
+ file = File.join(dir, filename)
32
+ yield(file) if File.exist?(file)
33
+
34
+ break if dir == stop || dir == root
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rodiff
4
- VERSION = "1.1.1"
4
+ VERSION = "1.2.0"
5
5
  end
metadata CHANGED
@@ -1,30 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rodiff
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Chang
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-09-27 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: thor
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - "~>"
16
+ - - ">="
18
17
  - !ruby/object:Gem::Version
19
18
  version: 1.3.2
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: 1.5.0
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
23
25
  requirements:
24
- - - "~>"
26
+ - - ">="
25
27
  - !ruby/object:Gem::Version
26
28
  version: 1.3.2
27
- description:
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: 1.5.0
28
32
  email:
29
33
  - ryancyq@gmail.com
30
34
  executables:
@@ -41,6 +45,7 @@ files:
41
45
  - lib/rodiff/configuration.rb
42
46
  - lib/rodiff/error.rb
43
47
  - lib/rodiff/executable.rb
48
+ - lib/rodiff/helpers/file_finder.rb
44
49
  - lib/rodiff/odiff.rb
45
50
  - lib/rodiff/version.rb
46
51
  homepage: https://github.com/ryancyq/rodiff
@@ -51,7 +56,6 @@ metadata:
51
56
  allowed_push_host: https://rubygems.org
52
57
  changelog_uri: https://github.com/ryancyq/rodiff/blob/main/CHANGELOG.md
53
58
  homepage_uri: https://github.com/ryancyq/rodiff
54
- post_install_message:
55
59
  rdoc_options: []
56
60
  require_paths:
57
61
  - lib
@@ -67,8 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
71
  version: 3.2.0
68
72
  requirements:
69
73
  - odiff, >= 3.0
70
- rubygems_version: 3.5.16
71
- signing_key:
74
+ rubygems_version: 4.0.3
72
75
  specification_version: 4
73
76
  summary: A ruby image comparison tool powered by ODiff in OCamel
74
77
  test_files: []