pyfig 0.5.0 → 0.6.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.
- package/README.md +6 -5
- package/SECURITY.md +1 -1
- package/dist/cjs/index.js +221 -73
- package/dist/cjs/index.js.map +7 -7
- package/dist/cjs/sync-resolver.js +220 -71
- package/dist/cjs/sync-resolver.js.map +8 -8
- package/dist/cli.js +2 -4
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +5 -9
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -29
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pep440.d.ts +12 -0
- package/dist/pep440.d.ts.map +1 -0
- package/dist/pep440.js +21 -0
- package/dist/pep440.js.map +1 -0
- package/dist/probes.d.ts.map +1 -1
- package/dist/probes.js +5 -6
- package/dist/probes.js.map +1 -1
- package/dist/provision.d.ts.map +1 -1
- package/dist/provision.js +203 -24
- package/dist/provision.js.map +1 -1
- package/package.json +3 -3
- package/dist/python-version.d.ts +0 -10
- package/dist/python-version.d.ts.map +0 -1
- package/dist/python-version.js +0 -17
- package/dist/python-version.js.map +0 -1
|
@@ -81,7 +81,21 @@ var import_undici = require("undici");
|
|
|
81
81
|
// src/config.ts
|
|
82
82
|
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
83
83
|
var envPaths = __toESM(require("env-paths"), 1);
|
|
84
|
-
|
|
84
|
+
|
|
85
|
+
// src/pep440.ts
|
|
86
|
+
var import_pep440 = require("@renovatebot/pep440");
|
|
87
|
+
function isValidPep440Specifier(specifier) {
|
|
88
|
+
return import_pep440.validRange(specifier);
|
|
89
|
+
}
|
|
90
|
+
function normalizePep440Version(version) {
|
|
91
|
+
return import_pep440.valid(version);
|
|
92
|
+
}
|
|
93
|
+
function pep440VersionSatisfies(version, specifier) {
|
|
94
|
+
return import_pep440.filter([version], specifier).length === 1;
|
|
95
|
+
}
|
|
96
|
+
function maxPep440Version(versions, specifier) {
|
|
97
|
+
return import_pep440.maxSatisfying([...versions], specifier);
|
|
98
|
+
}
|
|
85
99
|
|
|
86
100
|
// src/project-root.ts
|
|
87
101
|
var import_node_fs = __toESM(require("node:fs"), 1);
|
|
@@ -105,23 +119,10 @@ function* ancestors(startDirectory) {
|
|
|
105
119
|
}
|
|
106
120
|
}
|
|
107
121
|
|
|
108
|
-
// src/python-version.ts
|
|
109
|
-
var import_pep440 = require("@renovatebot/pep440");
|
|
110
|
-
function isValidPythonSpecifier(specifier) {
|
|
111
|
-
return import_pep440.validRange(specifier);
|
|
112
|
-
}
|
|
113
|
-
function isValidPythonVersion(version) {
|
|
114
|
-
return import_pep440.valid(version) !== null;
|
|
115
|
-
}
|
|
116
|
-
function pythonVersionSatisfies(version, specifier) {
|
|
117
|
-
return import_pep440.filter([version], specifier).length === 1;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
122
|
// src/config.ts
|
|
121
123
|
var DEFAULT_REQUIRES_PYTHON = ">=3.10,<4";
|
|
122
124
|
var DEFAULT_MANAGED_PYTHON = "3.12";
|
|
123
|
-
var
|
|
124
|
-
var DEFAULT_UV_RANGE = ">=0.10.0 <1.0.0";
|
|
125
|
+
var DEFAULT_REQUIRES_UV = ">=0.10,<1";
|
|
125
126
|
var DEFAULT_PROBE_TIMEOUT_MS = 1e4;
|
|
126
127
|
var DEFAULT_INSTALL_TIMEOUT_MS = 10 * 60000;
|
|
127
128
|
var DEFAULT_DOWNLOAD_TIMEOUT_MS = 5 * 60000;
|
|
@@ -135,13 +136,11 @@ var envPathsFunction = (() => {
|
|
|
135
136
|
function resolveOptions(options = {}) {
|
|
136
137
|
const env = { ...options.env ?? process.env };
|
|
137
138
|
const requiresPython = options.requiresPython ?? env["PYFIG_REQUIRES_PYTHON"] ?? DEFAULT_REQUIRES_PYTHON;
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
const requiresUv = options.requiresUv ?? env["PYFIG_REQUIRES_UV"] ?? DEFAULT_REQUIRES_UV;
|
|
140
|
+
assertPep440Specifier("requires-python", requiresPython);
|
|
141
|
+
assertPep440Specifier("requires-uv", requiresUv);
|
|
141
142
|
const managedPython = options.managedPython ?? env["PYFIG_MANAGED_PYTHON"] ?? DEFAULT_MANAGED_PYTHON;
|
|
142
|
-
const uvVersion = options.uvVersion ?? env["PYFIG_UV_VERSION"] ?? DEFAULT_UV_VERSION;
|
|
143
143
|
assertManagedPythonRequest(managedPython, requiresPython);
|
|
144
|
-
assertUvVersion(uvVersion, uvRange);
|
|
145
144
|
const probeTimeoutMs = resolveDuration("probeTimeoutMs", options.probeTimeoutMs, env["PYFIG_PROBE_TIMEOUT_MS"], DEFAULT_PROBE_TIMEOUT_MS);
|
|
146
145
|
const installTimeoutMs = resolveDuration("installTimeoutMs", options.installTimeoutMs, env["PYFIG_INSTALL_TIMEOUT_MS"], DEFAULT_INSTALL_TIMEOUT_MS);
|
|
147
146
|
const downloadTimeoutMs = resolveDuration("downloadTimeoutMs", options.downloadTimeoutMs, env["PYFIG_DOWNLOAD_TIMEOUT_MS"], DEFAULT_DOWNLOAD_TIMEOUT_MS);
|
|
@@ -155,8 +154,7 @@ function resolveOptions(options = {}) {
|
|
|
155
154
|
python: options.python ?? env["PYFIG_PYTHON"] ?? "",
|
|
156
155
|
requiresPython,
|
|
157
156
|
managedPython,
|
|
158
|
-
|
|
159
|
-
uvRange,
|
|
157
|
+
requiresUv,
|
|
160
158
|
requireEmbedding: options.requireEmbedding ?? parseBoolean(env["PYFIG_REQUIRE_EMBEDDING"], false),
|
|
161
159
|
requireGil: options.requireGil ?? parseBoolean(env["PYFIG_REQUIRE_GIL"], false),
|
|
162
160
|
autoInstall,
|
|
@@ -181,22 +179,9 @@ function uvEnvironment(options) {
|
|
|
181
179
|
UV_NO_CONFIG: "1"
|
|
182
180
|
};
|
|
183
181
|
}
|
|
184
|
-
function
|
|
185
|
-
if (!
|
|
186
|
-
throw new TypeError(`Invalid ${
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
function assertUvVersion(version, range) {
|
|
190
|
-
if (!import_semver.default.valid(version)) {
|
|
191
|
-
throw new TypeError(`Invalid exact uv version: ${version}`);
|
|
192
|
-
}
|
|
193
|
-
if (!import_semver.default.satisfies(version, range)) {
|
|
194
|
-
throw new TypeError(`Pinned uv ${version} does not satisfy supported range ${range}.`);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
function assertPythonSpecifier(specifier) {
|
|
198
|
-
if (!isValidPythonSpecifier(specifier)) {
|
|
199
|
-
throw new TypeError(`Invalid requires-python PEP 440 specifier: ${specifier}`);
|
|
182
|
+
function assertPep440Specifier(name, specifier) {
|
|
183
|
+
if (!isValidPep440Specifier(specifier)) {
|
|
184
|
+
throw new TypeError(`Invalid ${name} PEP 440 specifier: ${specifier}`);
|
|
200
185
|
}
|
|
201
186
|
}
|
|
202
187
|
function assertManagedPythonRequest(request, requiresPython) {
|
|
@@ -205,7 +190,7 @@ function assertManagedPythonRequest(request, requiresPython) {
|
|
|
205
190
|
}
|
|
206
191
|
if (/^\d+\.\d+(?:\.\d+)?$/u.test(request)) {
|
|
207
192
|
const normalized = request.split(".").length === 2 ? `${request}.0` : request;
|
|
208
|
-
if (!
|
|
193
|
+
if (!pep440VersionSatisfies(normalized, requiresPython)) {
|
|
209
194
|
throw new TypeError(`Managed Python ${request} cannot satisfy requires-python ${requiresPython}.`);
|
|
210
195
|
}
|
|
211
196
|
}
|
|
@@ -371,9 +356,6 @@ function assertNoTargetOverride(args) {
|
|
|
371
356
|
}
|
|
372
357
|
}
|
|
373
358
|
|
|
374
|
-
// src/probes.ts
|
|
375
|
-
var import_semver2 = __toESM(require("semver"), 1);
|
|
376
|
-
|
|
377
359
|
// src/process.ts
|
|
378
360
|
var import_node_child_process = require("node:child_process");
|
|
379
361
|
var import_node_path4 = __toESM(require("node:path"), 1);
|
|
@@ -543,7 +525,7 @@ print(json.dumps({
|
|
|
543
525
|
}))
|
|
544
526
|
`;
|
|
545
527
|
function pythonSatisfiesPolicy(python, options) {
|
|
546
|
-
return
|
|
528
|
+
return pep440VersionSatisfies(python.version, options.requiresPython) && (!options.requireEmbedding || python.implementation === "cpython" && python.embedding !== null && pythonArchitectureMatchesRuntime(python)) && (!options.requireGil || !python.gilDisabled);
|
|
547
529
|
}
|
|
548
530
|
async function probePython(candidate, options) {
|
|
549
531
|
const executable = await resolveExecutable(candidate.executable, options.env);
|
|
@@ -552,7 +534,7 @@ async function probePython(candidate, options) {
|
|
|
552
534
|
try {
|
|
553
535
|
const { stdout } = run(executable, [...candidate.args, "-c", PYTHON_PROBE], options.env, options.probeTimeoutMs);
|
|
554
536
|
const info = JSON.parse(stdout.trim());
|
|
555
|
-
return
|
|
537
|
+
return normalizePep440Version(info.version) ? info : null;
|
|
556
538
|
} catch {
|
|
557
539
|
return null;
|
|
558
540
|
}
|
|
@@ -561,7 +543,7 @@ async function findUv(options) {
|
|
|
561
543
|
const configured = options.env["PYFIG_UV"] ?? "uv";
|
|
562
544
|
const executable = await resolveExecutable(configured, options.env);
|
|
563
545
|
const uv = executable ? probeUv(executable, options) : null;
|
|
564
|
-
return uv &&
|
|
546
|
+
return uv && pep440VersionSatisfies(uv.version, options.requiresUv) ? uv : null;
|
|
565
547
|
}
|
|
566
548
|
function probeUv(executable, options) {
|
|
567
549
|
try {
|
|
@@ -575,7 +557,7 @@ function probeUv(executable, options) {
|
|
|
575
557
|
function normalizeVersion(value) {
|
|
576
558
|
if (!value)
|
|
577
559
|
return null;
|
|
578
|
-
return
|
|
560
|
+
return normalizePep440Version(value);
|
|
579
561
|
}
|
|
580
562
|
function pythonArchitectureMatchesRuntime(python) {
|
|
581
563
|
const architecture = python.architecture.toLowerCase();
|
|
@@ -814,21 +796,30 @@ async function ensureUvResolved(options) {
|
|
|
814
796
|
if (existing)
|
|
815
797
|
return existing;
|
|
816
798
|
if (!options.installUv) {
|
|
817
|
-
throw new Error(`Compatible uv is unavailable (
|
|
799
|
+
throw new Error(`Compatible uv is unavailable (requires-uv ${options.requiresUv}), and uv installation is disabled.`);
|
|
818
800
|
}
|
|
819
|
-
const
|
|
820
|
-
const executable = uvExecutable(options);
|
|
801
|
+
const policyKey = import_node_crypto.createHash("sha256").update(options.requiresUv).digest("hex");
|
|
821
802
|
return withProvisioningLock({
|
|
822
|
-
key: `uv:${canonicalPath(
|
|
803
|
+
key: `uv-policy:${canonicalPath(uvInstallRoot(options))}:${policyKey}`,
|
|
823
804
|
timeoutMs: options.coordinationTimeoutMs,
|
|
824
805
|
check: () => findAvailableUv(options),
|
|
825
806
|
mutate: async () => {
|
|
826
|
-
await
|
|
827
|
-
const
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
807
|
+
const release = await resolveUvRelease(options);
|
|
808
|
+
const installDir = uvInstallDirectory(options, release.version);
|
|
809
|
+
const executable = uvExecutable(options, release.version);
|
|
810
|
+
return withProvisioningLock({
|
|
811
|
+
key: `uv-release:${canonicalPath(installDir)}`,
|
|
812
|
+
timeoutMs: options.coordinationTimeoutMs,
|
|
813
|
+
check: () => findAvailableUv(options),
|
|
814
|
+
mutate: async () => {
|
|
815
|
+
await installUv(installDir, release, options);
|
|
816
|
+
const result = probeUv(executable, options);
|
|
817
|
+
if (!result || result.version !== release.version) {
|
|
818
|
+
throw new Error(`Expected managed uv ${release.version}, but the installed executable did not match.`);
|
|
819
|
+
}
|
|
820
|
+
return result;
|
|
821
|
+
}
|
|
822
|
+
});
|
|
832
823
|
}
|
|
833
824
|
});
|
|
834
825
|
}
|
|
@@ -836,8 +827,21 @@ async function findAvailableUv(options) {
|
|
|
836
827
|
const external = await findUv(options);
|
|
837
828
|
if (external)
|
|
838
829
|
return external;
|
|
839
|
-
|
|
840
|
-
|
|
830
|
+
return findManagedUv(options);
|
|
831
|
+
}
|
|
832
|
+
async function findManagedUv(options) {
|
|
833
|
+
const entries = await import_promises.readdir(uvInstallRoot(options), { withFileTypes: true }).catch(() => []);
|
|
834
|
+
let versions = entries.filter((entry) => entry.isDirectory() && normalizePep440Version(entry.name) === entry.name).map((entry) => entry.name);
|
|
835
|
+
while (versions.length > 0) {
|
|
836
|
+
const selected = maxPep440Version(versions, options.requiresUv);
|
|
837
|
+
if (!selected)
|
|
838
|
+
return null;
|
|
839
|
+
const candidate = probeUv(uvExecutable(options, selected), options);
|
|
840
|
+
if (candidate?.version === selected)
|
|
841
|
+
return candidate;
|
|
842
|
+
versions = versions.filter((version) => version !== selected);
|
|
843
|
+
}
|
|
844
|
+
return null;
|
|
841
845
|
}
|
|
842
846
|
function normalizeDependencies(dependencies) {
|
|
843
847
|
const normalized = dependencies.map((dependency) => dependency.trim());
|
|
@@ -898,15 +902,159 @@ async function virtualEnvironmentMatchesConfiguredPython(virtualEnvironment, opt
|
|
|
898
902
|
const configuredBase = configured.virtualEnvironment ? configured.baseExecutable : configured.executable;
|
|
899
903
|
return pathsEqual(configuredBase, virtualEnvironment.baseExecutable);
|
|
900
904
|
}
|
|
901
|
-
|
|
902
|
-
|
|
905
|
+
var UV_RELEASE_PAGE_SIZE = 100;
|
|
906
|
+
var UV_RELEASE_MAX_PAGES = 20;
|
|
907
|
+
var UV_RELEASE_METADATA_TTL_MS = 24 * 60 * 60000;
|
|
908
|
+
async function resolveUvRelease(options) {
|
|
909
|
+
const catalog = await ensureUvReleaseCatalog(options);
|
|
910
|
+
const asset = uvAsset();
|
|
911
|
+
const releases = catalog.releases.filter((release) => release.assets.includes(asset) && release.assets.includes(`${asset}.sha256`));
|
|
912
|
+
const version = maxPep440Version(releases.map((release) => release.version), options.requiresUv);
|
|
913
|
+
const release = releases.find((candidate) => candidate.version === version);
|
|
914
|
+
if (!release) {
|
|
915
|
+
throw new Error(`No published uv release satisfies requires-uv ${options.requiresUv}.`);
|
|
916
|
+
}
|
|
917
|
+
return release;
|
|
918
|
+
}
|
|
919
|
+
async function ensureUvReleaseCatalog(options) {
|
|
920
|
+
const file = uvReleaseMetadataFile(options);
|
|
921
|
+
const stale = await readUvReleaseCatalog(file);
|
|
922
|
+
try {
|
|
923
|
+
return await withProvisioningLock({
|
|
924
|
+
key: `uv-metadata:${canonicalPath(file)}`,
|
|
925
|
+
timeoutMs: options.coordinationTimeoutMs,
|
|
926
|
+
check: () => readFreshUvReleaseCatalog(file),
|
|
927
|
+
mutate: async () => {
|
|
928
|
+
const catalog = await fetchUvReleaseCatalog(options);
|
|
929
|
+
await writeUvReleaseCatalog(file, catalog);
|
|
930
|
+
return catalog;
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
} catch (error) {
|
|
934
|
+
const fallback = await readUvReleaseCatalog(file) ?? stale;
|
|
935
|
+
if (fallback)
|
|
936
|
+
return fallback;
|
|
937
|
+
throw error;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
async function fetchUvReleaseCatalog(options) {
|
|
941
|
+
const dispatcher = proxyDispatcher(options.env);
|
|
942
|
+
const releases = new Map;
|
|
943
|
+
let exhausted = false;
|
|
944
|
+
try {
|
|
945
|
+
for (let page = 1;page <= UV_RELEASE_MAX_PAGES; page += 1) {
|
|
946
|
+
const text = await downloadText(`https://api.github.com/repos/astral-sh/uv/releases?per_page=${UV_RELEASE_PAGE_SIZE}&page=${page}`, options.downloadTimeoutMs, dispatcher, {
|
|
947
|
+
Accept: "application/vnd.github+json",
|
|
948
|
+
"User-Agent": "pyfig",
|
|
949
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
950
|
+
});
|
|
951
|
+
const payload = JSON.parse(text);
|
|
952
|
+
if (!Array.isArray(payload)) {
|
|
953
|
+
throw new Error("GitHub returned invalid uv release metadata.");
|
|
954
|
+
}
|
|
955
|
+
for (const candidate of payload) {
|
|
956
|
+
if (!candidate || typeof candidate !== "object")
|
|
957
|
+
continue;
|
|
958
|
+
const release = candidate;
|
|
959
|
+
if (release.draft === true || typeof release.tag_name !== "string")
|
|
960
|
+
continue;
|
|
961
|
+
const assetNames = releaseAssetNames(release.assets);
|
|
962
|
+
const version = normalizePep440Version(release.tag_name);
|
|
963
|
+
if (version) {
|
|
964
|
+
releases.set(version, { assets: assetNames, tag: release.tag_name, version });
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
if (payload.length < UV_RELEASE_PAGE_SIZE) {
|
|
968
|
+
exhausted = true;
|
|
969
|
+
break;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
} finally {
|
|
973
|
+
await dispatcher?.close();
|
|
974
|
+
}
|
|
975
|
+
if (!exhausted) {
|
|
976
|
+
throw new Error(`uv release catalog exceeded ${UV_RELEASE_MAX_PAGES} pages.`);
|
|
977
|
+
}
|
|
978
|
+
if (releases.size === 0) {
|
|
979
|
+
throw new Error("GitHub returned no usable uv releases.");
|
|
980
|
+
}
|
|
981
|
+
return { fetchedAt: Date.now(), releases: [...releases.values()] };
|
|
982
|
+
}
|
|
983
|
+
async function readFreshUvReleaseCatalog(file) {
|
|
984
|
+
const catalog = await readUvReleaseCatalog(file);
|
|
985
|
+
if (!catalog)
|
|
986
|
+
return null;
|
|
987
|
+
const age = Date.now() - catalog.fetchedAt;
|
|
988
|
+
return age >= 0 && age < UV_RELEASE_METADATA_TTL_MS ? catalog : null;
|
|
989
|
+
}
|
|
990
|
+
async function readUvReleaseCatalog(file) {
|
|
991
|
+
try {
|
|
992
|
+
return parseUvReleaseCatalog(JSON.parse(await import_promises.readFile(file, "utf8")));
|
|
993
|
+
} catch {
|
|
994
|
+
return null;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
function parseUvReleaseCatalog(value) {
|
|
998
|
+
if (!value || typeof value !== "object")
|
|
999
|
+
return null;
|
|
1000
|
+
const catalog = value;
|
|
1001
|
+
if (!Number.isSafeInteger(catalog.fetchedAt) || catalog.fetchedAt < 0 || !Array.isArray(catalog.releases)) {
|
|
1002
|
+
return null;
|
|
1003
|
+
}
|
|
1004
|
+
const releases = [];
|
|
1005
|
+
for (const value of catalog.releases) {
|
|
1006
|
+
if (!value || typeof value !== "object")
|
|
1007
|
+
return null;
|
|
1008
|
+
const release = value;
|
|
1009
|
+
if (!Array.isArray(release.assets) || !release.assets.every((asset) => typeof asset === "string") || typeof release.tag !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._+-]*$/u.test(release.tag) || typeof release.version !== "string" || normalizePep440Version(release.version) !== release.version) {
|
|
1010
|
+
return null;
|
|
1011
|
+
}
|
|
1012
|
+
releases.push({
|
|
1013
|
+
assets: release.assets,
|
|
1014
|
+
tag: release.tag,
|
|
1015
|
+
version: release.version
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
return { fetchedAt: catalog.fetchedAt, releases };
|
|
1019
|
+
}
|
|
1020
|
+
async function writeUvReleaseCatalog(file, catalog) {
|
|
1021
|
+
await import_promises.mkdir(import_node_path5.default.dirname(file), { recursive: true });
|
|
1022
|
+
const staged = import_node_path5.default.join(import_node_path5.default.dirname(file), `.${import_node_path5.default.basename(file)}.${process.pid}.${import_node_crypto.randomUUID()}.tmp`);
|
|
1023
|
+
try {
|
|
1024
|
+
await import_promises.writeFile(staged, `${JSON.stringify(catalog)}
|
|
1025
|
+
`, { encoding: "utf8", flag: "wx" });
|
|
1026
|
+
if (process.platform === "win32")
|
|
1027
|
+
await import_promises.rm(file, { force: true });
|
|
1028
|
+
await import_promises.rename(staged, file);
|
|
1029
|
+
} finally {
|
|
1030
|
+
await import_promises.rm(staged, { force: true });
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
function uvReleaseMetadataFile(options) {
|
|
1034
|
+
return import_node_path5.default.join(options.cacheDir, "metadata", "uv-releases.json");
|
|
1035
|
+
}
|
|
1036
|
+
function releaseAssetNames(value) {
|
|
1037
|
+
if (!Array.isArray(value))
|
|
1038
|
+
return [];
|
|
1039
|
+
return value.flatMap((entry) => {
|
|
1040
|
+
if (!entry || typeof entry !== "object")
|
|
1041
|
+
return [];
|
|
1042
|
+
const name = entry.name;
|
|
1043
|
+
return typeof name === "string" ? [name] : [];
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
function uvInstallRoot(options) {
|
|
1047
|
+
return import_node_path5.default.join(options.cacheDir, "tools", "uv");
|
|
1048
|
+
}
|
|
1049
|
+
function uvInstallDirectory(options, version) {
|
|
1050
|
+
return import_node_path5.default.join(uvInstallRoot(options), version);
|
|
903
1051
|
}
|
|
904
|
-
function uvExecutable(options) {
|
|
905
|
-
return import_node_path5.default.join(uvInstallDirectory(options), process.platform === "win32" ? "uv.exe" : "uv");
|
|
1052
|
+
function uvExecutable(options, version) {
|
|
1053
|
+
return import_node_path5.default.join(uvInstallDirectory(options, version), process.platform === "win32" ? "uv.exe" : "uv");
|
|
906
1054
|
}
|
|
907
|
-
async function installUv(installDir, options) {
|
|
1055
|
+
async function installUv(installDir, release, options) {
|
|
908
1056
|
const asset = uvAsset();
|
|
909
|
-
const baseUrl = `https://github.com/astral-sh/uv/releases/download/${
|
|
1057
|
+
const baseUrl = `https://github.com/astral-sh/uv/releases/download/${release.tag}`;
|
|
910
1058
|
const temporary = await import_promises.mkdtemp(import_node_path5.default.join(import_node_os.default.tmpdir(), "pyfig-uv-"));
|
|
911
1059
|
const dispatcher = proxyDispatcher(options.env);
|
|
912
1060
|
try {
|
|
@@ -922,7 +1070,7 @@ async function installUv(installDir, options) {
|
|
|
922
1070
|
const source = await extractUvExecutable(archive, asset, extracted);
|
|
923
1071
|
if (!source)
|
|
924
1072
|
throw new Error(`uv archive did not contain the expected executable: ${asset}`);
|
|
925
|
-
await publishUvAtomically(source, installDir, options);
|
|
1073
|
+
await publishUvAtomically(source, installDir, release.version, options);
|
|
926
1074
|
} finally {
|
|
927
1075
|
await dispatcher?.close();
|
|
928
1076
|
await import_promises.rm(temporary, { recursive: true, force: true });
|
|
@@ -944,17 +1092,17 @@ async function extractUvExecutable(archive, asset, destination) {
|
|
|
944
1092
|
await import_promises.writeFile(source, matches[0][1], { flag: "wx" });
|
|
945
1093
|
return source;
|
|
946
1094
|
}
|
|
947
|
-
async function publishUvAtomically(source, installDir, options) {
|
|
1095
|
+
async function publishUvAtomically(source, installDir, version, options) {
|
|
948
1096
|
await import_promises.mkdir(installDir, { recursive: true });
|
|
949
|
-
const executable = uvExecutable(options);
|
|
1097
|
+
const executable = uvExecutable(options, version);
|
|
950
1098
|
const staged = import_node_path5.default.join(installDir, `.${import_node_path5.default.basename(executable)}.${process.pid}.${import_node_crypto.randomUUID()}.tmp`);
|
|
951
1099
|
try {
|
|
952
1100
|
await import_promises.copyFile(source, staged);
|
|
953
1101
|
if (process.platform !== "win32")
|
|
954
1102
|
await import_promises.chmod(staged, 493);
|
|
955
1103
|
const stagedUv = probeUv(staged, options);
|
|
956
|
-
if (!stagedUv || stagedUv.version !==
|
|
957
|
-
throw new Error(`Downloaded uv executable is not version ${
|
|
1104
|
+
if (!stagedUv || stagedUv.version !== version) {
|
|
1105
|
+
throw new Error(`Downloaded uv executable is not version ${version}.`);
|
|
958
1106
|
}
|
|
959
1107
|
if (process.platform === "win32")
|
|
960
1108
|
await import_promises.rm(executable, { force: true });
|
|
@@ -987,9 +1135,10 @@ async function download(url, destination, timeoutMs, dispatcher) {
|
|
|
987
1135
|
}
|
|
988
1136
|
await import_promises2.pipeline(import_node_stream.Readable.fromWeb(response.body), import_node_fs3.createWriteStream(destination, { flags: "wx" }));
|
|
989
1137
|
}
|
|
990
|
-
async function downloadText(url, timeoutMs, dispatcher) {
|
|
1138
|
+
async function downloadText(url, timeoutMs, dispatcher, headers) {
|
|
991
1139
|
const response = await import_undici.fetch(url, {
|
|
992
1140
|
dispatcher,
|
|
1141
|
+
headers,
|
|
993
1142
|
redirect: "follow",
|
|
994
1143
|
signal: AbortSignal.timeout(timeoutMs)
|
|
995
1144
|
});
|
|
@@ -1045,4 +1194,4 @@ main().catch((error) => {
|
|
|
1045
1194
|
process.exitCode = 1;
|
|
1046
1195
|
});
|
|
1047
1196
|
|
|
1048
|
-
//# debugId=
|
|
1197
|
+
//# debugId=D02BE720BF896D6864756E2164756E21
|