pray-cli 1.26.0 → 1.26.1

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: '087854aaa5f5bfead826eaa843615d2a52ba5f52236cc953b55d715c66c6f84b'
4
- data.tar.gz: 2600fce7bf405cdcc5f9ef78da7e7026dd408f0babd026ecbf869dc09da2de6f
3
+ metadata.gz: 7a2524f61bfecb06bcdcf1656ed618e104d854a2d0386c791c3bf3989b9894d1
4
+ data.tar.gz: d20780c7dd5cb5a9f14448fcb793e2bb42007ec8c29db9a390fbe3d4c9dd27b5
5
5
  SHA512:
6
- metadata.gz: 1242427bff2198aafc4c74e2c6977128150dde7ba0d7fadecf9d92df8bcaf68662028f45e11419faf8e3a25b9b3c9c959034190dff054cb264c93b303ee1fe3a
7
- data.tar.gz: 8d4b9ebc38d9fef0360ec9173b7e53ff92baff22f146e349f6ab049b48b1d0668883bfa0acb6bd3c8a8fd42993e91d06bc96b310b58df09d83dcfa0c377899f8
6
+ metadata.gz: 3f721c1a473ce6e07b726c6be47f6b98da4dcd83a6f6da6e3afcf6f80d18d50a7f47ed1b42f3bdde9b4922e16c05784ef5c32f69e1255cb7ae521f7f6ade8dbe
7
+ data.tar.gz: aeeaaade1743bf0b15511ec45704692fed58ed65b2f2f4ccca6d848481b23bd958bee3e433bb944632828ed029391f638c1ffaf31699bb73251763e8654f0c9b
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 1.26.1 (2026-11-02)
6
+
7
+ - 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.
8
+ - Keep drift, render checks, planning, and writes consistent for managed files that contain local content.
9
+
5
10
  ## 1.26.0 (2026-10-30)
6
11
 
7
12
  - Add validated `related` references to prayspec parsing, rendering, and `pray explain`.
@@ -84,7 +84,12 @@ module Pray
84
84
  end
85
85
  lines << "source: #{package_source_summary(package)}"
86
86
  lines << "exports: #{format_list(package.selected_exports)}"
87
- lines << "dependencies: #{format_list(package.spec.dependencies.map(&:name))}"
87
+ required_dependencies = package.spec.dependencies.reject(&:optional).map(&:name)
88
+ optional_referrals = package.spec.dependencies.select(&:optional).map do |dependency|
89
+ "#{dependency.name} (#{dependency.constraint})"
90
+ end
91
+ lines << "dependencies: #{format_list(required_dependencies)}"
92
+ lines << "optional referrals: #{format_list(optional_referrals)}"
88
93
  lines << "related prayers: #{format_list(package.spec.related)}"
89
94
  lines << "tree hash: #{package.tree_hash}"
90
95
  lines << "artifact hash: #{package.artifact_hash}"
@@ -152,7 +152,7 @@ module Pray
152
152
  lines << "#{indent}#{package.declaration.name} #{package.spec.recorded_version}"
153
153
  return unless ancestry.add?(package.declaration.name)
154
154
 
155
- package.spec.dependencies.each do |dependency|
155
+ package.spec.dependencies.reject(&:optional).each do |dependency|
156
156
  resolved = package_map[dependency.name]
157
157
  if resolved
158
158
  if ancestry.include?(resolved.declaration.name)
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "fileutils"
4
- require "pathname"
5
4
 
6
5
  module Pray
7
6
  module RenderDest
@@ -157,7 +156,7 @@ module Pray
157
156
  unless kind == :regular
158
157
  raise Error.render("refusing to write `#{display}`; destination is not a regular file")
159
158
  end
160
- RenderPatch.patch_rendered_content(decode_utf8(read_regular_bytes(path, display), display), fresh, retired)
159
+ RenderReconcile.reconcile_content(decode_utf8(read_regular_bytes(path, display), display), fresh, retired)
161
160
  end
162
161
 
163
162
  def write_rendered_content(path, display, fresh, retired = {})
@@ -165,7 +164,7 @@ module Pray
165
164
 
166
165
  open_regular(path, display, File::RDWR) do |file|
167
166
  existing = decode_utf8(read_destination_bytes(file, display), display)
168
- content = RenderPatch.patch_rendered_content(existing, fresh, retired)
167
+ content = RenderReconcile.reconcile_content(existing, fresh, retired)
169
168
  return if Transaction.replace(path, existing.b, content.b)
170
169
 
171
170
  file.rewind
@@ -4,6 +4,10 @@ module Pray
4
4
  module RenderReconcile
5
5
  module_function
6
6
 
7
+ def reconcile_content(existing, fresh, retired = {})
8
+ RenderPatch.patch_rendered_content(existing, fresh, retired)
9
+ end
10
+
7
11
  def current?(path, display, fresh, retired = {})
8
12
  kind = RenderDest.destination_kind(path)
9
13
  return false if kind == :missing
@@ -13,7 +17,7 @@ module Pray
13
17
  raise Error.render("refusing to read `#{display}`; destination is not a regular file")
14
18
  end
15
19
  existing = RenderDest.decode_utf8(RenderDest.read_regular_bytes(path, display), display)
16
- existing == RenderPatch.patch_rendered_content(existing, fresh, retired)
20
+ existing == reconcile_content(existing, fresh, retired)
17
21
  end
18
22
 
19
23
  def retired_span_checksums(previous_lockfile, target)
data/lib/pray/resolve.rb CHANGED
@@ -100,6 +100,7 @@ module Pray
100
100
  raise Error.resolution(local_errors.join("\n")) unless local_errors.empty?
101
101
 
102
102
  ResolveDeps.reject_dependency_cycles(packages)
103
+ ResolveDeps.validate_optional_referrals(packages)
103
104
  source_revisions = git_sources.revisions
104
105
 
105
106
  ResolvedProject.new(
@@ -7,12 +7,29 @@ module Pray
7
7
  def reject_dependency_cycles(packages)
8
8
  edges = {}
9
9
  packages.each do |package|
10
- edges[package.declaration.name] = package.spec.dependencies.map(&:name)
10
+ edges[package.declaration.name] = package.spec.dependencies.reject(&:optional).map(&:name)
11
11
  end
12
12
  cycle = DependencyGraph.find_dependency_cycle(edges)
13
13
  return unless cycle
14
14
 
15
15
  raise Error.resolution("dependency cycle detected: #{cycle.join(" -> ")}")
16
16
  end
17
+
18
+ def validate_optional_referrals(packages)
19
+ packages_by_name = packages.to_h { |package| [package.declaration.name, package] }
20
+ packages.each do |package|
21
+ package.spec.dependencies.select(&:optional).each do |dependency|
22
+ target = packages_by_name[dependency.name]
23
+ next unless target
24
+
25
+ target.spec.satisfy_constraint!(dependency.constraint)
26
+ rescue Error
27
+ raise Error.resolution(
28
+ "optional referral #{package.declaration.name} -> #{dependency.name} requires " \
29
+ "#{dependency.constraint}, but selected version is #{target.spec.recorded_version}"
30
+ )
31
+ end
32
+ end
33
+ end
17
34
  end
18
35
  end
data/lib/pray/verify.rb CHANGED
@@ -36,11 +36,16 @@ module Pray
36
36
 
37
37
  def drift_project(project, lockfile)
38
38
  report, rendered_targets, fresh_targets = collect_verification_report(project, lockfile)
39
- fresh_targets.each do |path, fresh_content|
40
- normalized_fresh = Hashing.normalize_line_endings(fresh_content)
39
+ fresh_targets.each do |path, fresh_target|
41
40
  on_disk = rendered_targets[path]
42
- on_disk = Hashing.normalize_line_endings(on_disk) if on_disk
43
- unless on_disk == normalized_fresh
41
+ retired = RenderReconcile.retired_span_checksums(lockfile, fresh_target)
42
+ expected = if on_disk
43
+ RenderReconcile.reconcile_content(on_disk, fresh_target.content, retired)
44
+ else
45
+ fresh_target.content
46
+ end
47
+ normalized_on_disk = Hashing.normalize_line_endings(on_disk) if on_disk
48
+ unless normalized_on_disk == Hashing.normalize_line_endings(expected)
44
49
  report.findings << VerificationFinding.new(
45
50
  kind: "renderer_drift",
46
51
  message: "#{path} differs from fresh render"
@@ -64,7 +69,7 @@ module Pray
64
69
  def collect_verification_report(project, lockfile)
65
70
  report = VerificationReport.new
66
71
  rendered_targets = {}
67
- fresh_targets = Render.render_project(project).to_h { |target| [target.path, target.content] }
72
+ fresh_targets = Render.render_project(project).to_h { |target| [target.path, target] }
68
73
 
69
74
  if project.manifest_hash != lockfile.manifest_hash
70
75
  report.findings << VerificationFinding.new(
@@ -104,6 +109,7 @@ module Pray
104
109
  end
105
110
 
106
111
  target_spans = lockfile.managed_span.group_by(&:target)
112
+ fresh_targets.each_key { |target_path| target_spans[target_path] ||= [] }
107
113
  target_spans.each do |target_path, spans|
108
114
  absolute_path = File.join(project.project_root, target_path)
109
115
  unless File.exist?(absolute_path)
@@ -135,7 +141,7 @@ module Pray
135
141
  end
136
142
  end
137
143
  end
138
- fresh_lines = fresh_targets[target_path]&.lines(chomp: true)
144
+ fresh_lines = fresh_targets[target_path]&.content&.lines(chomp: true)
139
145
  summary = VerifyPosition.summarize_position_drift(
140
146
  target_path,
141
147
  spans,
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.0"
5
- GENERATED_BY = "pray 1.26.0"
4
+ VERSION = "1.26.1"
5
+ GENERATED_BY = "pray 1.26.1"
6
6
  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.0
4
+ version: 1.26.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Makarov
@@ -251,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
251
251
  - !ruby/object:Gem::Version
252
252
  version: '0'
253
253
  requirements: []
254
- rubygems_version: 3.6.9
254
+ rubygems_version: 4.0.20
255
255
  specification_version: 4
256
256
  summary: Package manager for the language placed before inference (Prayfile)
257
257
  test_files: []