fhir_packages_manager 0.2.0 → 0.3.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 +12 -1
- data/README.md +10 -0
- data/lib/fhir_packages_manager/cli.rb +13 -2
- data/lib/fhir_packages_manager/fetch_result.rb +8 -3
- data/lib/fhir_packages_manager/manager.rb +37 -4
- data/lib/fhir_packages_manager/version.rb +1 -1
- data/sig/fhir_packages_manager/cli.rbs +2 -0
- data/sig/fhir_packages_manager/fetch_result.rbs +2 -0
- data/sig/fhir_packages_manager/manager.rbs +12 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7d65db7b1f5b29ac8f0064d0cfd224529dc336b2b88c7a4de952206fe81477f7
|
|
4
|
+
data.tar.gz: c16f3255dce19c1058b3781b5695e0c059e6d76b45dc63ff1c35a94891eacaa3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 016d41a5b7f0aed1ce89fa445e149ea85b4e991c9c61d9ba111fab699b113e88b8e62c650f8b08314e5246ca875927dbe0abb9bbdd92b9d68dbf8306c502f68c
|
|
7
|
+
data.tar.gz: bed4d3fb7c4f7abb708837a2ebbd7ecac247c18284b16e51967b216240f98878090df35765dcfdfdf3c8700c41ab785176d05d58747dff6a076ee636ef1ff29a
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-07-10
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `sync` CLI command and `Manager#sync`: downloads every non-ignored version of a package not
|
|
15
|
+
already present in the destination folder (checked as `name-version.tgz`, the same naming
|
|
16
|
+
`fetch` uses), reusing `#fetch` for the actual download of each missing version. Output reuses
|
|
17
|
+
`fetch`'s `OK`/`SKIP`/`MISS`/`ERR` lines, with `SKIP` covering both an ignored version and one
|
|
18
|
+
already on disk. (#3)
|
|
19
|
+
|
|
10
20
|
## [0.2.0] - 2026-07-10
|
|
11
21
|
|
|
12
22
|
### Added
|
|
@@ -50,6 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
50
60
|
- **Documentation**: YARD doc comments across the public API, and a Codecov/docs badge pair
|
|
51
61
|
in the README.
|
|
52
62
|
|
|
53
|
-
[Unreleased]: https://github.com/projkov/fhir_packages_manager/compare/v0.
|
|
63
|
+
[Unreleased]: https://github.com/projkov/fhir_packages_manager/compare/v0.3.0...HEAD
|
|
64
|
+
[0.3.0]: https://github.com/projkov/fhir_packages_manager/compare/v0.2.0...v0.3.0
|
|
54
65
|
[0.2.0]: https://github.com/projkov/fhir_packages_manager/compare/v0.1.0...v0.2.0
|
|
55
66
|
[0.1.0]: https://github.com/projkov/fhir_packages_manager/releases/tag/v0.1.0
|
data/README.md
CHANGED
|
@@ -46,6 +46,8 @@ result.path # => "./fhir_packages/hl7.fhir.us.core-6.1.0.tgz" when downloaded
|
|
|
46
46
|
manager.fetch_all(["hl7.fhir.us.core@6.1.0", "hl7.fhir.r4.core"]) # bare name = latest
|
|
47
47
|
|
|
48
48
|
manager.list_versions("hl7.fhir.us.core") # => {"https://packages.fhir.org" => ["1.0.0", "1.0.1", ...], ...}
|
|
49
|
+
|
|
50
|
+
manager.sync("hl7.fhir.us.core") # fetches every non-ignored version not already in destination
|
|
49
51
|
```
|
|
50
52
|
|
|
51
53
|
The ignore list file (YAML or JSON) is a flat array where a bare string
|
|
@@ -66,8 +68,16 @@ exe/fhir_packages_manager fetch hl7.fhir.us.core@6.1.0 hl7.fhir.r4.core \
|
|
|
66
68
|
-d ./fhir_packages -i fhir_packages_ignore.yml
|
|
67
69
|
exe/fhir_packages_manager list hl7.fhir.us.core \
|
|
68
70
|
-r https://packages.fhir.org -r https://packages.simplifier.net
|
|
71
|
+
exe/fhir_packages_manager sync hl7.fhir.us.core \
|
|
72
|
+
-r https://packages.fhir.org -d ./fhir_packages -i fhir_packages_ignore.yml
|
|
69
73
|
```
|
|
70
74
|
|
|
75
|
+
`sync` downloads every non-ignored version of a package that isn't already in the destination
|
|
76
|
+
folder (checked as `name-version.tgz`, the same naming `fetch` uses — keep that naming if you
|
|
77
|
+
move the files afterward, since a bare `version.tgz` can collide between two IGs that happen to
|
|
78
|
+
publish the same version number). Its output reuses `fetch`'s `OK`/`SKIP`/`MISS`/`ERR` lines,
|
|
79
|
+
with `SKIP` covering both an ignored version and one already on disk.
|
|
80
|
+
|
|
71
81
|
### Docker
|
|
72
82
|
|
|
73
83
|
The CLI is also published as a container image, so it can be used without installing Ruby
|
|
@@ -7,7 +7,7 @@ module FhirPackagesManager
|
|
|
7
7
|
# See the "CLI" section of the README for usage examples.
|
|
8
8
|
class CLI
|
|
9
9
|
# @return [Array<String>] the supported subcommands
|
|
10
|
-
COMMANDS = %w[fetch check list].freeze
|
|
10
|
+
COMMANDS = %w[fetch check list sync].freeze
|
|
11
11
|
|
|
12
12
|
# @return [String] usage text shown on --help and on invalid invocations
|
|
13
13
|
BANNER = <<~USAGE
|
|
@@ -17,6 +17,7 @@ module FhirPackagesManager
|
|
|
17
17
|
fetch Download packages into the destination folder
|
|
18
18
|
check Report which registry (if any) has each package/version
|
|
19
19
|
list List every version of a package available across registries
|
|
20
|
+
sync Download every non-ignored version not already in the destination folder
|
|
20
21
|
|
|
21
22
|
USAGE
|
|
22
23
|
|
|
@@ -56,6 +57,8 @@ module FhirPackagesManager
|
|
|
56
57
|
check(package_specs)
|
|
57
58
|
when 'list'
|
|
58
59
|
list(package_specs)
|
|
60
|
+
when 'sync'
|
|
61
|
+
sync(package_specs)
|
|
59
62
|
end
|
|
60
63
|
end
|
|
61
64
|
|
|
@@ -113,9 +116,11 @@ module FhirPackagesManager
|
|
|
113
116
|
|
|
114
117
|
def fetch_line(result)
|
|
115
118
|
package = result.package
|
|
119
|
+
path = result.path
|
|
116
120
|
case result.status
|
|
117
|
-
when :downloaded then "OK #{package} -> #{
|
|
121
|
+
when :downloaded then "OK #{package} -> #{path} (#{result.registry})"
|
|
118
122
|
when :ignored then "SKIP #{package} (ignored)"
|
|
123
|
+
when :skipped then "SKIP #{package} (already exists at #{path})"
|
|
119
124
|
when :not_found then "MISS #{package} (not found in any registry)"
|
|
120
125
|
when :error then "ERR #{package}: #{result.error}"
|
|
121
126
|
end
|
|
@@ -150,5 +155,11 @@ module FhirPackagesManager
|
|
|
150
155
|
"FOUND #{name} @ #{base_url}: #{versions.sort.join(', ')}"
|
|
151
156
|
end
|
|
152
157
|
end
|
|
158
|
+
|
|
159
|
+
def sync(package_specs)
|
|
160
|
+
results = package_specs.flat_map { |spec| manager.sync(Package.parse(spec).name) }
|
|
161
|
+
results.each { |result| puts fetch_line(result) }
|
|
162
|
+
exit 1 if results.any? { |result| result.not_found? || result.error? }
|
|
163
|
+
end
|
|
153
164
|
end
|
|
154
165
|
end
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module FhirPackagesManager
|
|
4
|
-
# Outcome of {Manager#fetch} for a single package.
|
|
4
|
+
# Outcome of {Manager#fetch} (or {Manager#sync}) for a single package/version.
|
|
5
5
|
#
|
|
6
6
|
# @!attribute package
|
|
7
7
|
# @return [Package] the package that was requested (version resolved, when downloaded)
|
|
8
8
|
# @!attribute status
|
|
9
|
-
# @return [Symbol] one of :downloaded, :ignored, :not_found, :error
|
|
9
|
+
# @return [Symbol] one of :downloaded, :ignored, :skipped, :not_found, :error
|
|
10
10
|
# @!attribute registry
|
|
11
11
|
# @return [String, nil] the base URL of the registry that served the package, if downloaded
|
|
12
12
|
# @!attribute path
|
|
13
|
-
# @return [String, nil] where the tarball was
|
|
13
|
+
# @return [String, nil] where the tarball was (or already is) on disk, if downloaded/skipped
|
|
14
14
|
# @!attribute error
|
|
15
15
|
# @return [String, nil] the error message, when status is :error
|
|
16
16
|
class FetchResult < Struct.new(:package, :status, :registry, :path, :error, keyword_init: true)
|
|
@@ -24,6 +24,11 @@ module FhirPackagesManager
|
|
|
24
24
|
status == :ignored
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
# @return [Boolean] true if {Manager#sync} skipped it because it was already downloaded
|
|
28
|
+
def skipped?
|
|
29
|
+
status == :skipped
|
|
30
|
+
end
|
|
31
|
+
|
|
27
32
|
# @return [Boolean] true if no registry had the package/version
|
|
28
33
|
def not_found?
|
|
29
34
|
status == :not_found
|
|
@@ -80,6 +80,20 @@ module FhirPackagesManager
|
|
|
80
80
|
end
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
+
# Downloads every non-ignored version of a package that isn't already present in
|
|
84
|
+
# {#destination} (as `name-version.tgz`, the same convention {#fetch} downloads use).
|
|
85
|
+
# A whole-package ignore skips it entirely, without querying any registry; an individual
|
|
86
|
+
# ignored version instead surfaces as a normal `:ignored` {FetchResult}, same as {#fetch}.
|
|
87
|
+
#
|
|
88
|
+
# @param name [String] the package name
|
|
89
|
+
# @return [Array<FetchResult>] one result per version considered, across all registries
|
|
90
|
+
def sync(name)
|
|
91
|
+
whole_package = Package.new(name, nil)
|
|
92
|
+
return [FetchResult.new(package: whole_package, status: :ignored)] if ignored?(whole_package)
|
|
93
|
+
|
|
94
|
+
candidate_versions(name).map { |version| sync_version(Package.new(name, version)) }
|
|
95
|
+
end
|
|
96
|
+
|
|
83
97
|
private
|
|
84
98
|
|
|
85
99
|
def fetch_package(package)
|
|
@@ -98,18 +112,37 @@ module FhirPackagesManager
|
|
|
98
112
|
end
|
|
99
113
|
|
|
100
114
|
def available_versions(registry, name)
|
|
101
|
-
registry
|
|
115
|
+
raw_versions(registry, name).reject { |version| ignored?(Package.new(name, version)) }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def raw_versions(registry, name)
|
|
119
|
+
registry.versions(name)
|
|
102
120
|
rescue PackageNotFoundError
|
|
103
121
|
[]
|
|
104
122
|
end
|
|
105
123
|
|
|
124
|
+
def candidate_versions(name)
|
|
125
|
+
registries.flat_map { |registry| raw_versions(registry, name) }.uniq
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def sync_version(package)
|
|
129
|
+
existing_path = download_path(package)
|
|
130
|
+
return FetchResult.new(package: package, status: :skipped, path: existing_path) if File.exist?(existing_path)
|
|
131
|
+
|
|
132
|
+
fetch(package)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def download_path(package)
|
|
136
|
+
File.join(destination, "#{package.name}-#{package.version}.tgz")
|
|
137
|
+
end
|
|
138
|
+
|
|
106
139
|
def download_result(package, found)
|
|
107
140
|
registry, resolved_version = found
|
|
108
141
|
name = package.name
|
|
109
|
-
|
|
142
|
+
resolved_package = Package.new(name, resolved_version)
|
|
143
|
+
target = download_path(resolved_package)
|
|
110
144
|
registry.download(name, resolved_version, target)
|
|
111
|
-
FetchResult.new(package:
|
|
112
|
-
registry: registry.base_url, path: target)
|
|
145
|
+
FetchResult.new(package: resolved_package, status: :downloaded, registry: registry.base_url, path: target)
|
|
113
146
|
end
|
|
114
147
|
end
|
|
115
148
|
end
|
|
@@ -16,14 +16,24 @@ module FhirPackagesManager
|
|
|
16
16
|
|
|
17
17
|
def list_versions: (String name) -> Hash[String, Array[String]]
|
|
18
18
|
|
|
19
|
+
def sync: (String name) -> Array[FetchResult]
|
|
20
|
+
|
|
19
21
|
private
|
|
20
22
|
|
|
21
23
|
def fetch_package: (Package package) -> FetchResult
|
|
22
24
|
|
|
23
25
|
def ignored?: (Package package) -> bool
|
|
24
26
|
|
|
25
|
-
def download_result: (Package package, [Registry, String] found) -> FetchResult
|
|
26
|
-
|
|
27
27
|
def available_versions: (Registry registry, String name) -> Array[String]
|
|
28
|
+
|
|
29
|
+
def raw_versions: (Registry registry, String name) -> Array[String]
|
|
30
|
+
|
|
31
|
+
def candidate_versions: (String name) -> Array[String]
|
|
32
|
+
|
|
33
|
+
def sync_version: (Package package) -> FetchResult
|
|
34
|
+
|
|
35
|
+
def download_path: (Package package) -> String
|
|
36
|
+
|
|
37
|
+
def download_result: (Package package, [Registry, String] found) -> FetchResult
|
|
28
38
|
end
|
|
29
39
|
end
|