pray-cli 1.26.1 → 1.26.3

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: 7a2524f61bfecb06bcdcf1656ed618e104d854a2d0386c791c3bf3989b9894d1
4
- data.tar.gz: d20780c7dd5cb5a9f14448fcb793e2bb42007ec8c29db9a390fbe3d4c9dd27b5
3
+ metadata.gz: 2c518cdb4d98021a08d150ad7c0c20463d885b09c9f69b022f2fa596d9597269
4
+ data.tar.gz: 8e46339135b9a8cb554eb4b8d9f60510baa5eab1b1b730bbda70efdd227289f3
5
5
  SHA512:
6
- metadata.gz: 3f721c1a473ce6e07b726c6be47f6b98da4dcd83a6f6da6e3afcf6f80d18d50a7f47ed1b42f3bdde9b4922e16c05784ef5c32f69e1255cb7ae521f7f6ade8dbe
7
- data.tar.gz: aeeaaade1743bf0b15511ec45704692fed58ed65b2f2f4ccca6d848481b23bd958bee3e433bb944632828ed029391f638c1ffaf31699bb73251763e8654f0c9b
6
+ metadata.gz: 1b619b7f79ee252328c885ac0664270d29f00f81a720102a26f8a1af8d78c57e7f9245f6eb09e724a3ba1f19d482001c59a8153d0f2da534d64fe64cdc5cc314
7
+ data.tar.gz: bd6f8f108e1e8cab3e48060c09dff86b8dfc55cc5edaaed320fcb6d347f2b9ea90e208ceb5c2757136084b7da815f34b491ef7fffec3f78d7b70abfb530819d3
data/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 1.26.3 (2026-11-12)
6
+
7
+ - Allow `pray install` to refresh the lock when a managed span already matches the fresh render but the lock ideal is stale. Keep failing when the on-disk body matches neither, and name move-aside recovery instead of a force flag.
8
+
9
+ ## 1.26.2 (2026-11-06)
10
+
11
+ - Reduce wall and CPU time for package resolve, tree hashing, and related install work without changing install results.
12
+
5
13
  ## 1.26.1 (2026-11-02)
6
14
 
7
15
  - Show optional package referrals separately in `pray explain`, exclude them from dependency cycles and trees, and validate their constraints when another declaration selects the target.
data/lib/pray/hashing.rb CHANGED
@@ -24,6 +24,8 @@ module Pray
24
24
  end
25
25
 
26
26
  def normalize_line_endings(text)
27
+ return text unless text.include?("\r")
28
+
27
29
  text.gsub("\r\n", "\n").tr("\r", "\n")
28
30
  end
29
31
 
@@ -54,27 +54,6 @@ module Pray
54
54
  copy.dependencies = dependencies.sort_by { |dependency| [dependency.name, dependency.constraint, dependency.optional] }
55
55
  end
56
56
  end
57
-
58
- def tree_hash_for_root(root)
59
- validate_relative_paths!
60
- file_bytes = {}
61
- files.each do |file|
62
- path = File.join(root, file)
63
- raise Error.integrity("package file missing: #{file}") unless File.exist?(path)
64
- raise Error.integrity("package file is a directory: #{file}") if File.directory?(path)
65
-
66
- file_bytes[file] = File.binread(path)
67
- end
68
- self.class.tree_hash_from_file_bytes(file_bytes)
69
- end
70
-
71
- def self.tree_hash_from_file_bytes(file_bytes)
72
- entries = file_bytes.map { |path, bytes| [path, Hashing.sha256_prefixed(bytes)] }.sort_by(&:first)
73
- serialized = entries.map do |path, hash|
74
- "file\0regular\0#{path}\0#{hash}\n"
75
- end.join
76
- Hashing.sha256_prefixed(serialized)
77
- end
78
57
  end
79
58
 
80
59
  module PackageSpecParser
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest"
4
+
5
+ module Pray
6
+ class PackageSpec
7
+ def tree_hash_for_root(root)
8
+ validate_relative_paths!
9
+ file_bytes = {}
10
+ files.each do |file|
11
+ path = File.join(root, file)
12
+ raise Error.integrity("package file missing: #{file}") unless File.exist?(path)
13
+ raise Error.integrity("package file is a directory: #{file}") if File.directory?(path)
14
+
15
+ file_bytes[file] = File.binread(path)
16
+ end
17
+ self.class.tree_hash_from_file_bytes(file_bytes)
18
+ end
19
+
20
+ def self.tree_hash_from_file_bytes(file_bytes)
21
+ # Stream the same bytes the prior string builder emitted so the digest stays identical.
22
+ digest = Digest::SHA256.new
23
+ file_bytes.keys.sort.each do |path|
24
+ bytes = file_bytes.fetch(path)
25
+ digest << "file\0regular\0"
26
+ digest << path
27
+ digest << "\0"
28
+ digest << "sha256:"
29
+ digest << Digest::SHA256.hexdigest(bytes)
30
+ digest << "\n"
31
+ end
32
+ Hashing.prefixed_hex_digest(digest.digest)
33
+ end
34
+ end
35
+ end
@@ -31,6 +31,9 @@ module Pray
31
31
  end
32
32
 
33
33
  def reject_managed_span_conflicts!(project, rendered, previous_lockfile)
34
+ fresh_ideals = rendered.each_with_object({}) do |target, ideals|
35
+ target.managed_spans.each { |span| ideals[span.id] = span.ideal_checksum }
36
+ end
34
37
  active_by_target = rendered.to_h do |target|
35
38
  [target.path, target.managed_spans.to_h { |span| [span.id, true] }]
36
39
  end
@@ -47,11 +50,16 @@ module Pray
47
50
  bodies = RenderPatch.managed_bodies(RenderPatch.split_segments(content))
48
51
  spans.each do |span|
49
52
  next unless active[span.id] && bodies.key?(span.id)
50
- next if Hashing.checksum_managed_span_content(bodies[span.id]) == span.ideal_checksum
53
+
54
+ checksum = Hashing.checksum_managed_span_content(bodies[span.id])
55
+ next if checksum == span.ideal_checksum
56
+ next if checksum == fresh_ideals[span.id]
51
57
 
52
58
  raise Error.render(
53
- "conflict: managed span `#{span.id}` in `#{target_path}` was edited " \
54
- "(`#{span.package}::#{span.export}`)"
59
+ "conflict: managed span `#{span.id}` in `#{target_path}` differs from lock and from " \
60
+ "fresh render (`#{span.package}::#{span.export}`).\n" \
61
+ "Move the destination aside and rerun `pray install`, or restore the managed block " \
62
+ "to the locked bytes."
55
63
  )
56
64
  end
57
65
  end
data/lib/pray/resolve.rb CHANGED
@@ -277,18 +277,17 @@ module Pray
277
277
  end
278
278
 
279
279
  def find_prayspec_file(root)
280
- files = []
280
+ found = nil
281
281
  Dir.each_child(root) do |entry|
282
282
  next unless File.extname(entry) == ".prayspec"
283
283
 
284
284
  path = File.join(root, entry)
285
- files << path if File.file?(path)
286
- end
287
- case files.length
288
- when 1 then files.first
289
- when 0 then raise Error.resolution("no prayspec file found in #{root.inspect}")
290
- else raise Error.resolution("multiple prayspec files found in #{root.inspect}")
285
+ next unless File.file?(path)
286
+ raise Error.resolution("multiple prayspec files found in #{root.inspect}") if found
287
+
288
+ found = path
291
289
  end
290
+ found || raise(Error.resolution("no prayspec file found in #{root.inspect}"))
292
291
  end
293
292
 
294
293
  def source_map(sources)
@@ -5,6 +5,8 @@ module Pray
5
5
  module_function
6
6
 
7
7
  def reject_dependency_cycles(packages)
8
+ return if packages.all? { |package| package.spec.dependencies.all?(&:optional) }
9
+
8
10
  edges = {}
9
11
  packages.each do |package|
10
12
  edges[package.declaration.name] = package.spec.dependencies.reject(&:optional).map(&:name)
@@ -16,6 +18,8 @@ module Pray
16
18
  end
17
19
 
18
20
  def validate_optional_referrals(packages)
21
+ return if packages.all? { |package| package.spec.dependencies.none?(&:optional) }
22
+
19
23
  packages_by_name = packages.to_h { |package| [package.declaration.name, package] }
20
24
  packages.each do |package|
21
25
  package.spec.dependencies.select(&:optional).each do |dependency|
data/lib/pray/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pray
4
- VERSION = "1.26.1"
5
- GENERATED_BY = "pray 1.26.1"
4
+ VERSION = "1.26.3"
5
+ GENERATED_BY = "pray 1.26.3"
6
6
  end
data/lib/pray.rb CHANGED
@@ -18,6 +18,7 @@ require_relative "pray/format_manifest"
18
18
  require_relative "pray/package_relation"
19
19
  require_relative "pray/package_spec"
20
20
  require_relative "pray/package_spec_paths"
21
+ require_relative "pray/package_spec_tree_hash"
21
22
  require_relative "pray/package_spec_version"
22
23
  require_relative "pray/local_prayer"
23
24
  require_relative "pray/lockfile"
data/pray-cli.gemspec CHANGED
@@ -44,5 +44,5 @@ Gem::Specification.new do |spec|
44
44
 
45
45
  spec.add_development_dependency "rspec", "~> 3.13"
46
46
  spec.add_development_dependency "polyrun", "~> 2.2"
47
- spec.add_development_dependency "rbs", "~> 3.9"
47
+ spec.add_development_dependency "rbs", "~> 4.0"
48
48
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pray-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.26.1
4
+ version: 1.26.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Makarov
@@ -77,14 +77,14 @@ dependencies:
77
77
  requirements:
78
78
  - - "~>"
79
79
  - !ruby/object:Gem::Version
80
- version: '3.9'
80
+ version: '4.0'
81
81
  type: :development
82
82
  prerelease: false
83
83
  version_requirements: !ruby/object:Gem::Requirement
84
84
  requirements:
85
85
  - - "~>"
86
86
  - !ruby/object:Gem::Version
87
- version: '3.9'
87
+ version: '4.0'
88
88
  description: 'Ruby Prayfile CLI and library: resolve, lock, render, verify, and publish
89
89
  inference input packages. Consumes path, git, and registry distribution points.'
90
90
  email:
@@ -166,6 +166,7 @@ files:
166
166
  - lib/pray/package_spec.rb
167
167
  - lib/pray/package_spec_paths.rb
168
168
  - lib/pray/package_spec_render.rb
169
+ - lib/pray/package_spec_tree_hash.rb
169
170
  - lib/pray/package_spec_version.rb
170
171
  - lib/pray/path_safety.rb
171
172
  - lib/pray/plan.rb