pray-cli 1.12.1 → 1.14.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 +4 -4
- data/CHANGELOG.md +10 -1
- data/lib/pray/cli/commands/workflow.rb +2 -0
- data/lib/pray/lockfile.rb +9 -5
- data/lib/pray/lockfile_serialize.rb +19 -0
- data/lib/pray/manifest_json.rb +2 -2
- data/lib/pray/package_spec.rb +14 -2
- data/lib/pray/publish.rb +53 -5
- data/lib/pray/registry.rb +17 -1
- data/lib/pray/render_content.rb +1 -1
- data/lib/pray/resolve.rb +9 -5
- data/lib/pray/serve_federation.rb +4 -4
- data/lib/pray/upstream.rb +104 -0
- data/lib/pray/version.rb +2 -2
- data/lib/pray.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cc753f65405f7052d882da07b3293b66c69e60cb26b8fe865919000323f2da1a
|
|
4
|
+
data.tar.gz: 91586f374cc5a677b0f5d2b722a4ba5da5912d8bd3664eac0ccd48b864889c65
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a84c2945dba3386f31dfdfc08d603ecee88d2be1e9898c20a993cd9dba9149ae4966b9cf9e02ba8c28905b7a1c81e2f5158bdf2eff8b36fe7f470e0bbd82ab6a
|
|
7
|
+
data.tar.gz: 48f107b5721d69c62b83db0f99247f9c4821eea42f85d3459cac09b7441badc3fa092965f877b1d3ae3fb0d38f391e8f65ae76cc21a6fd1595799dd2de0c6324
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 1.14.0 (2026-09-14)
|
|
4
|
+
|
|
5
|
+
- Keep an unchanged package version's artifact, first-publish time, and yank when `pray publish` runs again (RFC 0061).
|
|
6
|
+
- Write `published_at` as UTC Unix seconds in registry and federation JSON.
|
|
7
|
+
- Collapse trailing blank lines when composing so a composed file ends with a single newline, matching the other CLIs.
|
|
8
|
+
- Order `symbols` before `render` in the canonical manifest JSON so `manifest_hash` matches the other CLIs.
|
|
9
|
+
|
|
10
|
+
## 1.13.0 (2026-09-08)
|
|
11
|
+
|
|
12
|
+
- Record and verify package upstream pins in `.prayspec` and `Prayfile.lock`. Refuse path-fork updates until this CLI can refresh the path tree safely (RFC 0114).
|
|
4
13
|
|
|
5
14
|
## 1.12.1 (2026-09-08)
|
|
6
15
|
|
|
@@ -100,6 +100,8 @@ module Pray
|
|
|
100
100
|
raise Error.manifest("package #{package} not found")
|
|
101
101
|
end
|
|
102
102
|
end
|
|
103
|
+
current = resolve_current_project(ResolveOptions.new(offline: offline))
|
|
104
|
+
Upstream.ensure_update_supported!(current.packages, package)
|
|
103
105
|
install_command({locked: false, frozen: false, offline: offline, refresh: true})
|
|
104
106
|
end
|
|
105
107
|
|
data/lib/pray/lockfile.rb
CHANGED
|
@@ -8,14 +8,15 @@ module Pray
|
|
|
8
8
|
LockSource = Struct.new(:name, :kind, :url, :revision, :host_key_fingerprint)
|
|
9
9
|
LockedPackage = Struct.new(
|
|
10
10
|
:name, :version, :source, :path, :tree_hash, :artifact_hash, :artifact,
|
|
11
|
-
:exports, :dependencies, :signer_fingerprint
|
|
11
|
+
:exports, :dependencies, :signer_fingerprint, :upstream
|
|
12
12
|
) do
|
|
13
|
-
def initialize(exports: [], dependencies: [], signer_fingerprint: nil, source: nil, **kwargs)
|
|
14
|
-
super(**kwargs, exports: exports, dependencies: dependencies, signer_fingerprint: signer_fingerprint, source: source)
|
|
13
|
+
def initialize(exports: [], dependencies: [], signer_fingerprint: nil, source: nil, upstream: nil, **kwargs)
|
|
14
|
+
super(**kwargs, exports: exports, dependencies: dependencies, signer_fingerprint: signer_fingerprint, source: source, upstream: upstream)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
LockedTarget = Struct.new(:name, :outputs)
|
|
19
|
+
LockedUpstream = Struct.new(:name, :version, :source, :tree_hash, :artifact_hash, keyword_init: true)
|
|
19
20
|
ManagedSpanRecord = Struct.new(
|
|
20
21
|
:id, :target, :open_line, :close_line, :ideal_checksum, :package, :export,
|
|
21
22
|
:source_checksum, :silenced
|
|
@@ -98,6 +99,7 @@ module Pray
|
|
|
98
99
|
}
|
|
99
100
|
hash["source"] = entry.source unless entry.source.nil?
|
|
100
101
|
hash["signer_fingerprint"] = entry.signer_fingerprint if entry.signer_fingerprint
|
|
102
|
+
hash["upstream"] = Upstream.to_lock_hash(entry.upstream) if entry.upstream
|
|
101
103
|
hash
|
|
102
104
|
end
|
|
103
105
|
|
|
@@ -185,7 +187,8 @@ module Pray
|
|
|
185
187
|
artifact: normalize_lockfile_artifact(project_root, package.artifact, package.root),
|
|
186
188
|
exports: package.selected_exports,
|
|
187
189
|
dependencies: package.spec.dependencies.map(&:name),
|
|
188
|
-
signer_fingerprint: package.signer_fingerprint
|
|
190
|
+
signer_fingerprint: package.signer_fingerprint,
|
|
191
|
+
upstream: package.upstream
|
|
189
192
|
)
|
|
190
193
|
end,
|
|
191
194
|
target: manifest_targets.map { |target| LockedTarget.new(name: target.name, outputs: target.outputs) },
|
|
@@ -224,7 +227,8 @@ module Pray
|
|
|
224
227
|
artifact: entry["artifact"],
|
|
225
228
|
exports: entry["exports"] || [],
|
|
226
229
|
dependencies: entry["dependencies"] || [],
|
|
227
|
-
signer_fingerprint: entry["signer_fingerprint"]
|
|
230
|
+
signer_fingerprint: entry["signer_fingerprint"],
|
|
231
|
+
upstream: Upstream.from_lock_hash(entry["upstream"])
|
|
228
232
|
)
|
|
229
233
|
end,
|
|
230
234
|
target: Array(data["target"]).map { |entry| LockedTarget.new(name: entry["name"], outputs: entry["outputs"] || []) },
|
|
@@ -66,6 +66,25 @@ module Pray
|
|
|
66
66
|
lines << "exports = #{format_string_array(entry.exports)}"
|
|
67
67
|
lines << "dependencies = #{format_string_array(entry.dependencies)}"
|
|
68
68
|
lines << "signer_fingerprint = #{format_string(entry.signer_fingerprint)}" if entry.signer_fingerprint
|
|
69
|
+
if entry.upstream
|
|
70
|
+
lines << ""
|
|
71
|
+
lines << "[package.upstream]"
|
|
72
|
+
append_scalars(
|
|
73
|
+
lines,
|
|
74
|
+
[
|
|
75
|
+
["name", entry.upstream.name],
|
|
76
|
+
["version", entry.upstream.version]
|
|
77
|
+
].tap do |scalars|
|
|
78
|
+
scalars << ["source", entry.upstream.source] unless entry.upstream.source.nil?
|
|
79
|
+
scalars.concat(
|
|
80
|
+
[
|
|
81
|
+
["tree_hash", entry.upstream.tree_hash],
|
|
82
|
+
["artifact_hash", entry.upstream.artifact_hash]
|
|
83
|
+
]
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
)
|
|
87
|
+
end
|
|
69
88
|
lines
|
|
70
89
|
end
|
|
71
90
|
|
data/lib/pray/manifest_json.rb
CHANGED
|
@@ -14,10 +14,10 @@ module Pray
|
|
|
14
14
|
"sources" => manifest.sources.map { |source| source_fields(source) },
|
|
15
15
|
"targets" => manifest.targets.map { |target| target_fields(target) },
|
|
16
16
|
"packages" => manifest.packages.map { |package| package_fields(package) },
|
|
17
|
-
"local" => manifest.local.map { |entry| local_fields(entry) }
|
|
18
|
-
"render" => render_fields(manifest.render)
|
|
17
|
+
"local" => manifest.local.map { |entry| local_fields(entry) }
|
|
19
18
|
}
|
|
20
19
|
fields["symbols"] = manifest.symbols.sort.to_h unless manifest.symbols.empty?
|
|
20
|
+
fields["render"] = render_fields(manifest.render)
|
|
21
21
|
fields
|
|
22
22
|
end
|
|
23
23
|
|
data/lib/pray/package_spec.rb
CHANGED
|
@@ -9,17 +9,18 @@ module Pray
|
|
|
9
9
|
PackageSkill = Struct.new(:path, :summary)
|
|
10
10
|
PackageTemplate = Struct.new(:path, :summary)
|
|
11
11
|
PackageDependency = Struct.new(:name, :constraint, :optional)
|
|
12
|
+
PackageUpstream = Struct.new(:name, :constraint, keyword_init: true)
|
|
12
13
|
|
|
13
14
|
PackageSpec = Struct.new(
|
|
14
15
|
:name, :version, :summary, :description, :authors, :license, :homepage,
|
|
15
16
|
:source_code_uri, :changelog_uri, :prayfile_version, :files, :exports,
|
|
16
|
-
:skills, :templates, :adapters, :targets, :dependencies, :metadata
|
|
17
|
+
:skills, :templates, :adapters, :targets, :dependencies, :metadata, :upstream
|
|
17
18
|
) do
|
|
18
19
|
def initialize(
|
|
19
20
|
name: "", version: "", summary: nil, description: nil, authors: [], license: nil,
|
|
20
21
|
homepage: nil, source_code_uri: nil, changelog_uri: nil, prayfile_version: nil,
|
|
21
22
|
files: [], exports: {}, skills: {}, templates: {}, adapters: {}, targets: [],
|
|
22
|
-
dependencies: [], metadata: {}
|
|
23
|
+
dependencies: [], metadata: {}, upstream: nil
|
|
23
24
|
)
|
|
24
25
|
super
|
|
25
26
|
end
|
|
@@ -90,6 +91,13 @@ module Pray
|
|
|
90
91
|
)
|
|
91
92
|
end
|
|
92
93
|
|
|
94
|
+
def parse_upstream(rest)
|
|
95
|
+
values, _keywords = parse_call(rest)
|
|
96
|
+
name = string_from_value(values.first)
|
|
97
|
+
constraint = values[1] ? string_from_value(values[1]) : "*"
|
|
98
|
+
PackageUpstream.new(name: name, constraint: constraint)
|
|
99
|
+
end
|
|
100
|
+
|
|
93
101
|
def parse_exports(value)
|
|
94
102
|
map = Literal.parse_literal_map(value)
|
|
95
103
|
exports = {}
|
|
@@ -208,6 +216,10 @@ module Pray
|
|
|
208
216
|
spec.dependencies << parse_dependency(Regexp.last_match(1), false)
|
|
209
217
|
when /\Aspec\.add_optional_dependency (.+)\z/
|
|
210
218
|
spec.dependencies << parse_dependency(Regexp.last_match(1), true)
|
|
219
|
+
when /\Aspec\.upstream (.+)\z/
|
|
220
|
+
raise Error.parse("prayspec", "upstream may only be declared once") if spec.upstream
|
|
221
|
+
|
|
222
|
+
spec.upstream = parse_upstream(Regexp.last_match(1))
|
|
211
223
|
when /\Aspec\.(.+) = (.+)\z/
|
|
212
224
|
apply_assignment(spec, Regexp.last_match(1).strip, Regexp.last_match(2).strip)
|
|
213
225
|
else
|
data/lib/pray/publish.rb
CHANGED
|
@@ -20,13 +20,21 @@ module Pray
|
|
|
20
20
|
package_names = index.packages.to_set
|
|
21
21
|
|
|
22
22
|
project.packages.each do |package|
|
|
23
|
-
archive_bytes = Archive.build_package_archive_bytes(package)
|
|
24
23
|
artifact_path = registry_artifact_path(package.declaration.name, package.spec.version)
|
|
25
|
-
artifact_output_path = File.join(root, artifact_path)
|
|
26
|
-
write_output_bytes(artifact_output_path, archive_bytes)
|
|
27
|
-
|
|
28
24
|
metadata_path = registry_metadata_path(root, package.declaration.name)
|
|
29
25
|
metadata = load_registry_package_metadata(metadata_path, package.declaration.name)
|
|
26
|
+
existing = metadata.versions.find { |entry| entry.version == package.spec.version }
|
|
27
|
+
stored_artifact = stored_package_artifact(root, artifact_path, package, existing)
|
|
28
|
+
if stored_artifact && stored_publish_matches?(
|
|
29
|
+
stored_artifact, package, signer, signer_fingerprint, existing
|
|
30
|
+
)
|
|
31
|
+
package_names << package.declaration.name
|
|
32
|
+
write_registry_package_metadata(metadata_path, metadata)
|
|
33
|
+
next
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
archive_bytes = Archive.build_package_archive_bytes(package)
|
|
37
|
+
write_output_bytes(File.join(root, artifact_path), archive_bytes)
|
|
30
38
|
version_entry = published_registry_package_version(
|
|
31
39
|
package,
|
|
32
40
|
signer,
|
|
@@ -34,6 +42,7 @@ module Pray
|
|
|
34
42
|
archive_bytes,
|
|
35
43
|
artifact_path
|
|
36
44
|
)
|
|
45
|
+
preserve_existing_publish_metadata(metadata, version_entry, stored_artifact)
|
|
37
46
|
metadata.versions.reject! { |entry| entry.version == version_entry.version }
|
|
38
47
|
metadata.versions << version_entry
|
|
39
48
|
write_registry_package_metadata(metadata_path, metadata)
|
|
@@ -81,11 +90,50 @@ module Pray
|
|
|
81
90
|
exports: package.spec.exports.keys,
|
|
82
91
|
signer: signer,
|
|
83
92
|
signer_fingerprint: signer_fingerprint,
|
|
84
|
-
published_at: Time.now.
|
|
93
|
+
published_at: Time.now.to_i,
|
|
85
94
|
signature: Registry.registry_artifact_signature(archive_bytes, package.tree_hash, signer)
|
|
86
95
|
)
|
|
87
96
|
end
|
|
88
97
|
|
|
98
|
+
def stored_package_artifact(root, artifact_path, package, existing)
|
|
99
|
+
return unless existing&.artifact == artifact_path && existing.tree_hash == package.tree_hash
|
|
100
|
+
|
|
101
|
+
stored_path = File.join(root, artifact_path)
|
|
102
|
+
return unless File.file?(stored_path)
|
|
103
|
+
|
|
104
|
+
artifact_bytes = File.binread(stored_path)
|
|
105
|
+
return unless existing.artifact_hash == Hashing.sha256_prefixed(artifact_bytes)
|
|
106
|
+
return unless stored_prayspec_matches?(artifact_bytes, package.root)
|
|
107
|
+
|
|
108
|
+
artifact_bytes
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def stored_publish_matches?(artifact_bytes, package, signer, signer_fingerprint, existing)
|
|
112
|
+
existing.signer == signer &&
|
|
113
|
+
existing.signer_fingerprint == signer_fingerprint &&
|
|
114
|
+
existing.signature == Registry.registry_artifact_signature(artifact_bytes, package.tree_hash, signer)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def stored_prayspec_matches?(artifact_bytes, package_root)
|
|
118
|
+
Dir.mktmpdir("pray-publish-check-") do |directory|
|
|
119
|
+
Archive.unpack_praypkg(artifact_bytes, directory)
|
|
120
|
+
stored_path = Resolve.find_prayspec_file(directory)
|
|
121
|
+
current_path = Resolve.find_prayspec_file(package_root)
|
|
122
|
+
File.basename(stored_path) == File.basename(current_path) &&
|
|
123
|
+
File.binread(stored_path) == File.binread(current_path)
|
|
124
|
+
end
|
|
125
|
+
rescue Error, SystemCallError
|
|
126
|
+
false
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def preserve_existing_publish_metadata(metadata, version_entry, stored_artifact)
|
|
130
|
+
existing = metadata.versions.find { |entry| entry.version == version_entry.version }
|
|
131
|
+
return unless existing
|
|
132
|
+
|
|
133
|
+
version_entry.yanked = existing.yanked
|
|
134
|
+
version_entry.published_at = existing.published_at if stored_artifact
|
|
135
|
+
end
|
|
136
|
+
|
|
89
137
|
def load_registry_index(root)
|
|
90
138
|
path = File.join(root, "v1", "index.json")
|
|
91
139
|
return RegistryIndex.new unless File.exist?(path)
|
data/lib/pray/registry.rb
CHANGED
|
@@ -5,6 +5,7 @@ require "net/http"
|
|
|
5
5
|
require "uri"
|
|
6
6
|
require "fileutils"
|
|
7
7
|
require "pathname"
|
|
8
|
+
require "time"
|
|
8
9
|
require_relative "path_safety"
|
|
9
10
|
require_relative "http_body"
|
|
10
11
|
|
|
@@ -145,11 +146,26 @@ module Pray
|
|
|
145
146
|
exports: entry["exports"] || [],
|
|
146
147
|
signer: entry["signer"],
|
|
147
148
|
signer_fingerprint: entry["signer_fingerprint"],
|
|
148
|
-
published_at: entry["published_at"],
|
|
149
|
+
published_at: entry.key?("published_at") ? publish_timestamp_from_value(entry["published_at"]) : nil,
|
|
149
150
|
signature: entry["signature"]
|
|
150
151
|
)
|
|
151
152
|
end
|
|
152
153
|
|
|
154
|
+
def publish_timestamp_from_value(value)
|
|
155
|
+
timestamp = case value
|
|
156
|
+
when Integer then value
|
|
157
|
+
when String
|
|
158
|
+
value.match?(/\A\d+\z/) ? value.to_i : Time.iso8601(value).to_i
|
|
159
|
+
end
|
|
160
|
+
unless timestamp&.between?(0, 253_402_300_799)
|
|
161
|
+
raise Error.integrity("registry published_at must be whole UTC Unix seconds")
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
timestamp
|
|
165
|
+
rescue ArgumentError
|
|
166
|
+
raise Error.integrity("registry published_at must be whole UTC Unix seconds")
|
|
167
|
+
end
|
|
168
|
+
|
|
153
169
|
def select_package_version(metadata, constraint, preferred_version)
|
|
154
170
|
if preferred_version
|
|
155
171
|
version = metadata.versions.find { |entry| entry.version == preferred_version && !entry.yanked }
|
data/lib/pray/render_content.rb
CHANGED
data/lib/pray/resolve.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Pray
|
|
|
13
13
|
ResolvedPackage = Struct.new(
|
|
14
14
|
:declaration, :root, :spec, :tree_hash, :artifact_hash, :artifact,
|
|
15
15
|
:selected_exports, :source_checksum, :export_bodies, :skill_files,
|
|
16
|
-
:signer_fingerprint, :registry_latest_version
|
|
16
|
+
:signer_fingerprint, :registry_latest_version, :upstream
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
ResolvedLocalFile = Struct.new(
|
|
@@ -75,7 +75,7 @@ module Pray
|
|
|
75
75
|
user_config,
|
|
76
76
|
declaration,
|
|
77
77
|
lockfile_hints,
|
|
78
|
-
|
|
78
|
+
options: options
|
|
79
79
|
)
|
|
80
80
|
if seen[package.declaration.name]
|
|
81
81
|
raise Error.resolution("duplicate package declaration: #{package.declaration.name}")
|
|
@@ -149,9 +149,10 @@ module Pray
|
|
|
149
149
|
"Create the file or remove the entry from Prayfile, then run `pray install`."
|
|
150
150
|
end
|
|
151
151
|
|
|
152
|
-
def resolve_package(project_root, sources, git_sources, user_config, declaration, lockfile, offline: false)
|
|
152
|
+
def resolve_package(project_root, sources, git_sources, user_config, declaration, lockfile, offline: false, options: nil)
|
|
153
|
+
options ||= ResolveOptions.new(offline: offline)
|
|
153
154
|
root, registry_latest_version = resolve_package_root_with_metadata(
|
|
154
|
-
project_root, sources, git_sources, user_config, declaration, lockfile, offline: offline
|
|
155
|
+
project_root, sources, git_sources, user_config, declaration, lockfile, offline: options.offline
|
|
155
156
|
)
|
|
156
157
|
spec_path = find_prayspec_file(root)
|
|
157
158
|
spec_text = File.read(spec_path)
|
|
@@ -185,7 +186,10 @@ module Pray
|
|
|
185
186
|
export_bodies: export_bodies,
|
|
186
187
|
skill_files: skill_files,
|
|
187
188
|
signer_fingerprint: nil,
|
|
188
|
-
registry_latest_version: registry_latest_version
|
|
189
|
+
registry_latest_version: registry_latest_version,
|
|
190
|
+
upstream: Upstream.lock_path(
|
|
191
|
+
project_root, sources, git_sources, user_config, declaration, spec, lockfile, options
|
|
192
|
+
)
|
|
189
193
|
)
|
|
190
194
|
end
|
|
191
195
|
|
|
@@ -34,7 +34,7 @@ module Pray
|
|
|
34
34
|
)
|
|
35
35
|
next if metadata.versions.empty?
|
|
36
36
|
|
|
37
|
-
updated_at = metadata.versions.
|
|
37
|
+
updated_at = (metadata.versions.filter_map(&:published_at).max || 0).to_s
|
|
38
38
|
{
|
|
39
39
|
"name" => name,
|
|
40
40
|
"updated_at" => updated_at,
|
|
@@ -57,7 +57,7 @@ module Pray
|
|
|
57
57
|
metadata = Publish.load_registry_package_metadata(metadata_path, name)
|
|
58
58
|
body = {
|
|
59
59
|
"name" => metadata.name,
|
|
60
|
-
"updated_at" => metadata.versions.
|
|
60
|
+
"updated_at" => (metadata.versions.filter_map(&:published_at).max || 0).to_s,
|
|
61
61
|
"versions" => metadata.versions.map { |version| transport_version(version) }
|
|
62
62
|
}
|
|
63
63
|
Serve.ok_response("application/json", JSON.pretty_generate(body))
|
|
@@ -78,9 +78,9 @@ module Pray
|
|
|
78
78
|
"tree_hash" => version.tree_hash.to_s,
|
|
79
79
|
"yanked" => version.yanked,
|
|
80
80
|
"targets" => version.targets,
|
|
81
|
-
"exports" => version.exports
|
|
82
|
-
"published_at" => version.published_at.to_s
|
|
81
|
+
"exports" => version.exports
|
|
83
82
|
}
|
|
83
|
+
hash["published_at"] = version.published_at if version.published_at
|
|
84
84
|
if version.signer || version.signer_fingerprint
|
|
85
85
|
hash["publisher"] = {
|
|
86
86
|
"id" => version.signer.to_s,
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pray
|
|
4
|
+
module Upstream
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def ensure_update_supported!(packages, selected = nil)
|
|
8
|
+
unsupported = packages.find do |package|
|
|
9
|
+
package.declaration.path && package.spec.upstream &&
|
|
10
|
+
(selected.nil? || package.declaration.name == selected)
|
|
11
|
+
end
|
|
12
|
+
return unless unsupported
|
|
13
|
+
|
|
14
|
+
raise Error.unsupported(
|
|
15
|
+
"this installation cannot refresh upstream package #{unsupported.declaration.name}; " \
|
|
16
|
+
"install pray with Cargo and retry"
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_lock_hash(entry)
|
|
21
|
+
hash = {
|
|
22
|
+
"name" => entry.name,
|
|
23
|
+
"version" => entry.version,
|
|
24
|
+
"tree_hash" => entry.tree_hash,
|
|
25
|
+
"artifact_hash" => entry.artifact_hash
|
|
26
|
+
}
|
|
27
|
+
hash["source"] = entry.source unless entry.source.nil?
|
|
28
|
+
hash
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def from_lock_hash(entry)
|
|
32
|
+
return nil if entry.nil?
|
|
33
|
+
|
|
34
|
+
LockedUpstream.new(
|
|
35
|
+
name: entry["name"],
|
|
36
|
+
version: entry["version"],
|
|
37
|
+
source: entry["source"],
|
|
38
|
+
tree_hash: entry["tree_hash"],
|
|
39
|
+
artifact_hash: entry["artifact_hash"]
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def lock_path(project_root, sources, git_sources, user_config, declaration, spec, lockfile, options)
|
|
44
|
+
return nil unless spec.upstream
|
|
45
|
+
if spec.name == spec.upstream.name
|
|
46
|
+
raise Error.resolution("package #{spec.name} cannot use itself as upstream")
|
|
47
|
+
end
|
|
48
|
+
return nil unless declaration.path
|
|
49
|
+
|
|
50
|
+
refresh = options.ignore_locked_versions || options.unlocked_packages.include?(declaration.name)
|
|
51
|
+
locked = lockfile&.package&.find { |entry| entry.name == declaration.name }&.upstream
|
|
52
|
+
name, constraint, source = resolution_input(declaration, spec, sources, locked, refresh)
|
|
53
|
+
resolved = Resolve.resolve_package(
|
|
54
|
+
project_root,
|
|
55
|
+
sources,
|
|
56
|
+
git_sources,
|
|
57
|
+
user_config,
|
|
58
|
+
ManifestPackage.new(
|
|
59
|
+
name: name,
|
|
60
|
+
constraint: constraint,
|
|
61
|
+
source: source
|
|
62
|
+
),
|
|
63
|
+
lockfile,
|
|
64
|
+
options: options
|
|
65
|
+
)
|
|
66
|
+
resolved_upstream = LockedUpstream.new(
|
|
67
|
+
name: name,
|
|
68
|
+
version: resolved.spec.version,
|
|
69
|
+
source: source,
|
|
70
|
+
tree_hash: resolved.tree_hash,
|
|
71
|
+
artifact_hash: resolved.artifact_hash
|
|
72
|
+
)
|
|
73
|
+
ensure_locked_match!(locked, resolved_upstream) if !refresh && locked
|
|
74
|
+
resolved_upstream
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def resolution_input(declaration, spec, sources, locked, refresh)
|
|
78
|
+
if locked && !refresh
|
|
79
|
+
if locked.name != spec.upstream.name
|
|
80
|
+
raise Error.integrity(
|
|
81
|
+
"locked upstream name mismatch for #{declaration.name}: " \
|
|
82
|
+
"expected #{locked.name}, found #{spec.upstream.name}"
|
|
83
|
+
)
|
|
84
|
+
end
|
|
85
|
+
return [locked.name, "= #{locked.version}", locked.source]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
name = spec.upstream.name
|
|
89
|
+
source = ResolveSource.implied_source_name(ManifestPackage.new(name: name), sources)
|
|
90
|
+
[name, spec.upstream.constraint, source]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def ensure_locked_match!(locked, resolved)
|
|
94
|
+
if locked.name != resolved.name || locked.version != resolved.version
|
|
95
|
+
raise Error.integrity("locked upstream identity mismatch")
|
|
96
|
+
end
|
|
97
|
+
raise Error.integrity("locked upstream source mismatch") if locked.source != resolved.source
|
|
98
|
+
raise Error.integrity("locked upstream tree hash mismatch") if locked.tree_hash != resolved.tree_hash
|
|
99
|
+
if locked.artifact_hash != resolved.artifact_hash
|
|
100
|
+
raise Error.integrity("locked upstream artifact hash mismatch")
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
data/lib/pray/version.rb
CHANGED
data/lib/pray.rb
CHANGED
|
@@ -24,6 +24,7 @@ require_relative "pray/resolve_exports"
|
|
|
24
24
|
require_relative "pray/invocation"
|
|
25
25
|
require_relative "pray/git_refresh"
|
|
26
26
|
require_relative "pray/resolve"
|
|
27
|
+
require_relative "pray/upstream"
|
|
27
28
|
require_relative "pray/compose_dest"
|
|
28
29
|
require_relative "pray/render_patch"
|
|
29
30
|
require_relative "pray/render"
|
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.
|
|
4
|
+
version: 1.14.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrei Makarov
|
|
@@ -180,6 +180,7 @@ files:
|
|
|
180
180
|
- lib/pray/trust.rb
|
|
181
181
|
- lib/pray/trust_feed.rb
|
|
182
182
|
- lib/pray/trust_ops.rb
|
|
183
|
+
- lib/pray/upstream.rb
|
|
183
184
|
- lib/pray/verify.rb
|
|
184
185
|
- lib/pray/verify_position.rb
|
|
185
186
|
- lib/pray/verify_provisioned.rb
|