kettle-dev 3.1.3 → 3.1.4

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: 0af4e7c94cc4d2320e2ac4f19162509c98cc3bc322281fbe09968fe211af1d2f
4
- data.tar.gz: 1d4734bb8a3a6768340d2ddb35294d704d7c203f4052246554ff17460e65e5b3
3
+ metadata.gz: 3eaffce406ad243001b13e3e5fc92c3ffff48a7eac174506b7bcf6db2fb5031f
4
+ data.tar.gz: 67d34d5ab8630a31f4526c7c315b3647991b76c37b03617a153aaeb7f52320ab
5
5
  SHA512:
6
- metadata.gz: c3fd59b7f8de46b09620502a2c104599d31614f6f011cabe1adca6ee9e75c92bc70e32ebeaa46c897802ac1a629e4cfccbec093a2a572caed2720e2d52fa65aa
7
- data.tar.gz: 844135ea482141c8feaf2b48aeb837775492a70cf335fe6e4c97f9745bc6de92616787b6a6e5fb486b7b8b401a1147caa006af747cb06b8b75d8ed4987832454
6
+ metadata.gz: edb236854f14490bb18db34924f4ae92b94d471d3e7210fbf8ec696d68c43510720f80f5982dfab08f3fe8a5e7354e590c4d9c158ad102ecea341738fa917dc2
7
+ data.tar.gz: d09c6f5d8cfdbb4d1734b711c8889f8f5b9ec76fc54278a9709bcdb48aed27975e7913036d0d98a1fa88d17ec0962251991b711646c0645708dee69bd2477bea
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,17 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [3.1.4] - 2026-09-28
34
+
35
+ - TAG: [v3.1.4][3.1.4t]
36
+ - COVERAGE: 91.89% -- 6197/6744 lines in 49 files
37
+ - BRANCH COVERAGE: 76.24% -- 2359/3094 branches in 49 files
38
+ - 51.34% documented
39
+
40
+ ### Fixed
41
+
42
+ - Centralize canonical path and component-aware containment checks for Kettle tools.
43
+
33
44
  ## [3.1.3] - 2026-09-27
34
45
 
35
46
  - TAG: [v3.1.3][3.1.3t]
@@ -3916,7 +3927,9 @@ Please file a bug if you notice a violation of semantic versioning.
3916
3927
  - Selecting will run the selected workflow via `act`
3917
3928
  - This may move to its own gem in the future.
3918
3929
 
3919
- [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.1.3...HEAD
3930
+ [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.1.4...HEAD
3931
+ [3.1.4]: https://github.com/kettle-dev/kettle-dev/compare/v3.1.3...v3.1.4
3932
+ [3.1.4t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.1.4
3920
3933
  [3.1.3]: https://github.com/kettle-dev/kettle-dev/compare/v3.1.2...v3.1.3
3921
3934
  [3.1.3t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.1.3
3922
3935
  [3.1.2]: https://github.com/kettle-dev/kettle-dev/compare/v3.1.1...v3.1.2
data/README.md CHANGED
@@ -1066,7 +1066,7 @@ Thanks for RTFM. ☺️
1066
1066
  [📌gitmoji]: https://gitmoji.dev
1067
1067
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
1068
1068
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
1069
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-6.717-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1069
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-6.744-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1070
1070
  [🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
1071
1071
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
1072
1072
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kettle
4
+ module Dev
5
+ # Filesystem path operations shared by Kettle tools.
6
+ module Paths
7
+ module_function
8
+
9
+ # Expands a path and resolves its longest existing ancestor. This keeps
10
+ # comparisons useful for generated paths that do not exist yet.
11
+ def canonical(path, base: nil)
12
+ expanded = File.expand_path(path, base)
13
+ existing = expanded
14
+ suffix = []
15
+ until File.exist?(existing) || File.symlink?(existing)
16
+ parent = File.dirname(existing)
17
+ return expanded if parent == existing
18
+
19
+ suffix.unshift(File.basename(existing))
20
+ existing = parent
21
+ end
22
+
23
+ suffix.reduce(File.realpath(existing)) { |resolved, component| File.join(resolved, component) }
24
+ rescue Errno::EACCES, Errno::ENOENT
25
+ expanded
26
+ end
27
+
28
+ # Uses filesystem identity for existing paths, so symlink aliases and
29
+ # platform-specific aliases are compared by the operating system.
30
+ def same?(left, right, base: nil)
31
+ left_path = canonical(left, base: base)
32
+ right_path = canonical(right, base: base)
33
+ return true if left_path == right_path
34
+
35
+ return File.identical?(left_path, right_path) if File.exist?(left_path) && File.exist?(right_path)
36
+
37
+ comparable_parts(left_path) == comparable_parts(right_path)
38
+ rescue Errno::EACCES, Errno::ENOENT, Errno::ENOTDIR, NotImplementedError
39
+ comparable_parts(left_path || left) == comparable_parts(right_path || right)
40
+ end
41
+
42
+ # Tests containment by path components, not by a string prefix.
43
+ def within?(path, root, base: nil)
44
+ candidate = canonical(path, base: base)
45
+ boundary = canonical(root, base: base)
46
+ return true if same?(candidate, boundary)
47
+
48
+ candidate_parts = comparable_parts(candidate)
49
+ boundary_parts = comparable_parts(boundary)
50
+ candidate_parts[0, boundary_parts.length] == boundary_parts
51
+ rescue Errno::EACCES, Errno::ENOENT, Errno::ENOTDIR
52
+ false
53
+ end
54
+
55
+ def path_parts(path)
56
+ path.tr("\\", "/").split("/").reject(&:empty?)
57
+ end
58
+
59
+ def comparable_parts(path)
60
+ parts = path_parts(path)
61
+ Gem.win_platform? ? parts.map(&:downcase) : parts
62
+ end
63
+ end
64
+ end
65
+ end
@@ -30,7 +30,7 @@ module Kettle
30
30
 
31
31
  def initialize(name:, root:, ci_root:, local_path_roots: [], selector_env: {})
32
32
  @name = String(name)
33
- @root = File.realpath(root)
33
+ @root = Paths.canonical(root)
34
34
  @ci_root = canonical_path(ci_root)
35
35
  @local_path_roots = Array(local_path_roots).map { |path| canonical_path(path) }.uniq.freeze
36
36
  @selector_env = selector_env.to_h.map { |key, value| [String(key), String(value)] }.to_h.freeze
@@ -86,25 +86,11 @@ module Kettle
86
86
  end
87
87
 
88
88
  def canonical_path(path)
89
- expanded = File.expand_path(path, @root)
90
- candidate = expanded
91
- suffix = []
92
-
93
- until File.exist?(candidate) || File.symlink?(candidate)
94
- parent = File.dirname(candidate)
95
- return expanded if parent == candidate
96
-
97
- suffix.unshift(File.basename(candidate))
98
- candidate = parent
99
- end
100
-
101
- suffix.reduce(File.realpath(candidate)) { |base, component| File.join(base, component) }
102
- rescue Errno::ENOENT
103
- expanded
89
+ Paths.canonical(path, base: @root)
104
90
  end
105
91
 
106
92
  def path_within_root?(path, root)
107
- path == root || (path[0, root.length] == root && path[root.length] == "/")
93
+ Paths.within?(path, root)
108
94
  end
109
95
  end
110
96
  end
@@ -5,7 +5,7 @@ module Kettle
5
5
  # Version namespace for this gem.
6
6
  module Version
7
7
  # Current gem version.
8
- VERSION = "3.1.3"
8
+ VERSION = "3.1.4"
9
9
  end
10
10
  # Current gem version exposed at the traditional constant location.
11
11
  VERSION = Version::VERSION # Traditional Constant Location
data/lib/kettle/dev.rb CHANGED
@@ -47,6 +47,7 @@ module Kettle
47
47
  autoload :MarkdownReferenceValidator, "kettle/dev/markdown_reference_validator"
48
48
  autoload :ReadmeBackers, "kettle/dev/readme_backers"
49
49
  autoload :OpenCollectiveConfig, "kettle/dev/open_collective_config"
50
+ autoload :Paths, "kettle/dev/paths"
50
51
  autoload :ReleaseNotifier, "kettle/dev/release_notifier"
51
52
  autoload :ReleaseCLI, "kettle/dev/release_cli"
52
53
  autoload :ReleaseGraphContract, "kettle/dev/release_graph_contract"
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kettle-dev
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.3
4
+ version: 3.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -390,6 +390,7 @@ files:
390
390
  - lib/kettle/dev/lockfile_reset.rb
391
391
  - lib/kettle/dev/markdown_reference_validator.rb
392
392
  - lib/kettle/dev/open_collective_config.rb
393
+ - lib/kettle/dev/paths.rb
393
394
  - lib/kettle/dev/pre_release_cli.rb
394
395
  - lib/kettle/dev/rakelib/appraisal.rake
395
396
  - lib/kettle/dev/rakelib/bench.rake
@@ -421,10 +422,10 @@ licenses:
421
422
  - AGPL-3.0-only
422
423
  metadata:
423
424
  homepage_uri: https://kettle-dev.galtzo.com
424
- source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v3.1.3
425
- changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.1.3/CHANGELOG.md
425
+ source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v3.1.4
426
+ changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.1.4/CHANGELOG.md
426
427
  bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
427
- documentation_uri: https://www.rubydoc.info/gems/kettle-dev/3.1.3
428
+ documentation_uri: https://www.rubydoc.info/gems/kettle-dev/3.1.4
428
429
  funding_uri: https://github.com/sponsors/pboling
429
430
  wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
430
431
  news_uri: https://www.railsbling.com/tags/kettle-dev
metadata.gz.sig CHANGED
Binary file