mirror of
https://github.com/astral-sh/setup-uv.git
synced 2026-04-17 02:06:29 +00:00
159 lines
4.2 KiB
TypeScript
159 lines
4.2 KiB
TypeScript
import * as path from "node:path";
|
|
import * as core from "@actions/core";
|
|
import { getParsedVersionFile } from "./file-parser";
|
|
import { normalizeVersionSpecifier } from "./specifier";
|
|
import type {
|
|
ParsedVersionFile,
|
|
ResolveUvVersionOptions,
|
|
VersionRequest,
|
|
} from "./types";
|
|
|
|
export interface VersionRequestResolver {
|
|
resolve(context: VersionRequestContext): VersionRequest | undefined;
|
|
}
|
|
|
|
export class VersionRequestContext {
|
|
readonly version: string | undefined;
|
|
readonly versionFile: string | undefined;
|
|
readonly workingDirectory: string;
|
|
|
|
private readonly parsedFiles = new Map<
|
|
string,
|
|
ParsedVersionFile | undefined
|
|
>();
|
|
|
|
constructor(
|
|
version: string | undefined,
|
|
versionFile: string | undefined,
|
|
workingDirectory: string,
|
|
) {
|
|
this.version = version;
|
|
this.versionFile = versionFile;
|
|
this.workingDirectory = workingDirectory;
|
|
}
|
|
|
|
getVersionFile(filePath: string): ParsedVersionFile | undefined {
|
|
const cachedResult = this.parsedFiles.get(filePath);
|
|
if (cachedResult !== undefined || this.parsedFiles.has(filePath)) {
|
|
return cachedResult;
|
|
}
|
|
|
|
const result = getParsedVersionFile(filePath);
|
|
this.parsedFiles.set(filePath, result);
|
|
return result;
|
|
}
|
|
|
|
getWorkspaceCandidates(): Array<{
|
|
source: "pyproject.toml" | "uv.toml";
|
|
sourcePath: string;
|
|
}> {
|
|
return [
|
|
{
|
|
source: "uv.toml",
|
|
sourcePath: path.join(this.workingDirectory, "uv.toml"),
|
|
},
|
|
{
|
|
source: "pyproject.toml",
|
|
sourcePath: path.join(this.workingDirectory, "pyproject.toml"),
|
|
},
|
|
];
|
|
}
|
|
}
|
|
|
|
export class ExplicitInputVersionResolver implements VersionRequestResolver {
|
|
resolve(context: VersionRequestContext): VersionRequest | undefined {
|
|
if (context.version === undefined) {
|
|
return undefined;
|
|
}
|
|
|
|
return {
|
|
source: "input",
|
|
specifier: normalizeVersionSpecifier(context.version),
|
|
};
|
|
}
|
|
}
|
|
|
|
export class VersionFileVersionResolver implements VersionRequestResolver {
|
|
resolve(context: VersionRequestContext): VersionRequest | undefined {
|
|
if (context.versionFile === undefined) {
|
|
return undefined;
|
|
}
|
|
|
|
const versionFile = context.getVersionFile(context.versionFile);
|
|
if (versionFile === undefined) {
|
|
throw new Error(
|
|
`Could not determine uv version from file: ${context.versionFile}`,
|
|
);
|
|
}
|
|
|
|
return {
|
|
format: versionFile.format,
|
|
source: "version-file",
|
|
sourcePath: context.versionFile,
|
|
specifier: versionFile.specifier,
|
|
};
|
|
}
|
|
}
|
|
|
|
export class WorkspaceVersionResolver implements VersionRequestResolver {
|
|
resolve(context: VersionRequestContext): VersionRequest | undefined {
|
|
for (const candidate of context.getWorkspaceCandidates()) {
|
|
const versionFile = context.getVersionFile(candidate.sourcePath);
|
|
if (versionFile === undefined) {
|
|
continue;
|
|
}
|
|
|
|
return {
|
|
format: versionFile.format,
|
|
source: candidate.source,
|
|
sourcePath: candidate.sourcePath,
|
|
specifier: versionFile.specifier,
|
|
};
|
|
}
|
|
|
|
core.info(
|
|
"Could not determine uv version from uv.toml or pyproject.toml. Falling back to latest.",
|
|
);
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
export class LatestVersionResolver implements VersionRequestResolver {
|
|
resolve(): VersionRequest {
|
|
return {
|
|
source: "default",
|
|
specifier: "latest",
|
|
};
|
|
}
|
|
}
|
|
|
|
const VERSION_REQUEST_RESOLVERS: VersionRequestResolver[] = [
|
|
new ExplicitInputVersionResolver(),
|
|
new VersionFileVersionResolver(),
|
|
new WorkspaceVersionResolver(),
|
|
new LatestVersionResolver(),
|
|
];
|
|
|
|
export function resolveVersionRequest(
|
|
options: ResolveUvVersionOptions,
|
|
): VersionRequest {
|
|
const context = new VersionRequestContext(
|
|
emptyToUndefined(options.version),
|
|
emptyToUndefined(options.versionFile),
|
|
options.workingDirectory,
|
|
);
|
|
|
|
for (const resolver of VERSION_REQUEST_RESOLVERS) {
|
|
const request = resolver.resolve(context);
|
|
if (request !== undefined) {
|
|
return request;
|
|
}
|
|
}
|
|
|
|
throw new Error("Could not resolve a requested uv version.");
|
|
}
|
|
|
|
function emptyToUndefined(value: string | undefined): string | undefined {
|
|
return value === undefined || value === "" ? undefined : value;
|
|
}
|