renovate 44.93.4 → 44.93.6
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/dist/config/options/index.js +1 -1
- package/dist/config/options/index.js.map +1 -1
- package/dist/global-config-option-defaults.generated.js +1 -1
- package/dist/global-config-option-defaults.generated.js.map +1 -1
- package/dist/modules/manager/bazel/rules/http.js.map +1 -1
- package/dist/modules/manager/cargo/extract.js.map +1 -1
- package/dist/modules/manager/composer/schema.js.map +1 -1
- package/dist/modules/manager/deps-edn/extract.js.map +1 -1
- package/dist/modules/manager/docker-compose/extract.js +1 -1
- package/dist/modules/manager/docker-compose/extract.js.map +1 -1
- package/dist/modules/manager/fingerprint.generated.js +21 -21
- package/dist/modules/manager/fingerprint.generated.js.map +1 -1
- package/dist/modules/manager/git-submodules/extract.js +1 -1
- package/dist/modules/manager/git-submodules/extract.js.map +1 -1
- package/dist/modules/manager/github-actions/known-actions.js +11 -1
- package/dist/modules/manager/github-actions/known-actions.js.map +1 -1
- package/dist/modules/manager/glasskube/extract.js +2 -2
- package/dist/modules/manager/glasskube/extract.js.map +1 -1
- package/dist/modules/manager/gomod/artifacts-extra.js.map +1 -1
- package/dist/modules/manager/gradle/extract/catalog.js +2 -0
- package/dist/modules/manager/gradle/extract/catalog.js.map +1 -1
- package/dist/modules/manager/gradle/extract/consistent-versions-plugin.js +3 -1
- package/dist/modules/manager/gradle/extract/consistent-versions-plugin.js.map +1 -1
- package/dist/modules/manager/gradle/extract.js +5 -2
- package/dist/modules/manager/gradle/extract.js.map +1 -1
- package/dist/modules/manager/gradle/parser/common.js +2 -0
- package/dist/modules/manager/gradle/parser/common.js.map +1 -1
- package/dist/modules/manager/gradle/parser/handlers.js +9 -0
- package/dist/modules/manager/gradle/parser/handlers.js.map +1 -1
- package/dist/modules/manager/gradle/parser/registry-urls.js +1 -0
- package/dist/modules/manager/gradle/parser/registry-urls.js.map +1 -1
- package/dist/modules/manager/gradle/parser.js +1 -0
- package/dist/modules/manager/gradle/parser.js.map +1 -1
- package/dist/modules/manager/helmfile/artifacts.js +1 -0
- package/dist/modules/manager/helmfile/artifacts.js.map +1 -1
- package/dist/modules/manager/hermit/artifacts.js +1 -0
- package/dist/modules/manager/hermit/artifacts.js.map +1 -1
- package/dist/modules/manager/maven/extract.js +14 -4
- package/dist/modules/manager/maven/extract.js.map +1 -1
- package/dist/modules/manager/maven/update.js +3 -0
- package/dist/modules/manager/maven/update.js.map +1 -1
- package/dist/modules/manager/mix/artifacts.js +6 -1
- package/dist/modules/manager/mix/artifacts.js.map +1 -1
- package/dist/modules/manager/nuget/config-formatter.js +2 -0
- package/dist/modules/manager/nuget/config-formatter.js.map +1 -1
- package/dist/modules/manager/nuget/extract.js +2 -0
- package/dist/modules/manager/nuget/extract.js.map +1 -1
- package/dist/modules/manager/nuget/util.js +1 -0
- package/dist/modules/manager/nuget/util.js.map +1 -1
- package/dist/modules/manager/ocb/extract.js +1 -0
- package/dist/modules/manager/ocb/extract.js.map +1 -1
- package/dist/modules/manager/pep621/processors/uv.js +4 -0
- package/dist/modules/manager/pep621/processors/uv.js.map +1 -1
- package/dist/modules/manager/pep621/schema.js +4 -1
- package/dist/modules/manager/pep621/schema.js.map +1 -1
- package/dist/modules/manager/pip-compile/common.js +2 -0
- package/dist/modules/manager/pip-compile/common.js.map +1 -1
- package/dist/modules/manager/pip-compile/utils.js +3 -1
- package/dist/modules/manager/pip-compile/utils.js.map +1 -1
- package/dist/modules/manager/pipenv/artifacts.js +3 -0
- package/dist/modules/manager/pipenv/artifacts.js.map +1 -1
- package/dist/modules/manager/pipenv/extract.js +1 -0
- package/dist/modules/manager/pipenv/extract.js.map +1 -1
- package/dist/modules/manager/pixi/extract.js +1 -0
- package/dist/modules/manager/pixi/extract.js.map +1 -1
- package/dist/modules/manager/poetry/artifacts.js +1 -0
- package/dist/modules/manager/poetry/artifacts.js.map +1 -1
- package/dist/modules/manager/poetry/extract.js +1 -0
- package/dist/modules/manager/poetry/extract.js.map +1 -1
- package/dist/modules/manager/pre-commit/index.js.map +1 -1
- package/dist/modules/manager/swift/extract.js.map +1 -1
- package/dist/modules/manager/terraform/extractors/others/modules.js.map +1 -1
- package/dist/modules/manager/tflint-plugin/plugins.js.map +1 -1
- package/dist/modules/manager/vendir/artifacts.js +1 -0
- package/dist/modules/manager/vendir/artifacts.js.map +1 -1
- package/dist/util/http/legacy.js +6 -3
- package/dist/util/http/legacy.js.map +1 -1
- package/dist/workers/repository/extract/manager-files.js +4 -2
- package/dist/workers/repository/extract/manager-files.js.map +1 -1
- package/package.json +1 -1
- package/renovate-schema.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.js","names":[],"sources":["../../../../lib/modules/manager/ocb/extract.ts"],"sourcesContent":["import { isNullOrUndefined } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parseSingleYaml } from '../../../util/yaml.ts';\nimport { GoDatasource } from '../../datasource/go/index.ts';\nimport type {\n ExtractConfig,\n PackageDependency,\n PackageFileContent,\n} from '../types.ts';\nimport { type Module, OCBConfig } from './schema.ts';\n\nexport function extractPackageFile(\n content: string,\n packageFile: string,\n _config?: ExtractConfig,\n): PackageFileContent | null {\n let definition: OCBConfig | null = null;\n try {\n const yaml = parseSingleYaml(content);\n const parsed = OCBConfig.safeParse(yaml);\n if (!parsed.success) {\n logger.trace(\n { packageFile, err: parsed.error },\n 'Failed to parse OCB schema',\n );\n return null;\n }\n\n definition = parsed.data;\n } catch (error) {\n logger.debug(\n { packageFile, err: error },\n 'OCB manager failed to parse file as YAML',\n );\n return null;\n }\n\n const deps: PackageDependency[] = [];\n if (definition.dist.otelcol_version) {\n deps.push({\n datasource: GoDatasource.id,\n depType: 'collector',\n depName: 'go.opentelemetry.io/collector',\n currentValue: definition.dist.otelcol_version,\n extractVersion: '^v(?<version>\\\\S+)',\n });\n }\n\n deps.push(...processModule(definition.connectors, 'connectors'));\n deps.push(...processModule(definition.exporters, 'exports'));\n deps.push(...processModule(definition.extensions, 'extensions'));\n deps.push(...processModule(definition.processors, 'processors'));\n deps.push(...processModule(definition.providers, 'providers'));\n deps.push(...processModule(definition.receivers, 'receivers'));\n\n return {\n packageFileVersion: definition.dist.version,\n deps,\n };\n}\n\nexport function processModule(\n module: Module,\n depType: string,\n): PackageDependency[] {\n const deps: PackageDependency[] = [];\n if (isNullOrUndefined(module)) {\n return deps;\n }\n\n for (const element of module) {\n const [depName, currentValue] = element.gomod.trim().split(regEx(/\\s+/));\n deps.push({\n datasource: GoDatasource.id,\n depType,\n depName,\n currentValue,\n });\n }\n\n return deps;\n}\n"],"mappings":";;;;;;;AAYA,SAAgB,mBACd,SACA,aACA,SAC2B;CAC3B,IAAI,aAA+B;CACnC,IAAI;EACF,MAAM,OAAO,gBAAgB,OAAO;EACpC,MAAM,SAAS,UAAU,UAAU,IAAI;EACvC,IAAI,CAAC,OAAO,SAAS;GACnB,OAAO,MACL;IAAE;IAAa,KAAK,OAAO;GAAM,GACjC,4BACF;GACA,OAAO;EACT;EAEA,aAAa,OAAO;CACtB,SAAS,OAAO;EACd,OAAO,MACL;GAAE;GAAa,KAAK;EAAM,GAC1B,0CACF;EACA,OAAO;CACT;CAEA,MAAM,OAA4B,CAAC
|
|
1
|
+
{"version":3,"file":"extract.js","names":[],"sources":["../../../../lib/modules/manager/ocb/extract.ts"],"sourcesContent":["import { isNullOrUndefined } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parseSingleYaml } from '../../../util/yaml.ts';\nimport { GoDatasource } from '../../datasource/go/index.ts';\nimport type {\n ExtractConfig,\n PackageDependency,\n PackageFileContent,\n} from '../types.ts';\nimport { type Module, OCBConfig } from './schema.ts';\n\nexport function extractPackageFile(\n content: string,\n packageFile: string,\n _config?: ExtractConfig,\n): PackageFileContent | null {\n let definition: OCBConfig | null = null;\n try {\n const yaml = parseSingleYaml(content);\n const parsed = OCBConfig.safeParse(yaml);\n if (!parsed.success) {\n logger.trace(\n { packageFile, err: parsed.error },\n 'Failed to parse OCB schema',\n );\n return null;\n }\n\n definition = parsed.data;\n } catch (error) {\n logger.debug(\n { packageFile, err: error },\n 'OCB manager failed to parse file as YAML',\n );\n return null;\n }\n\n const deps: PackageDependency[] = [];\n // v8 ignore else -- needs a builder definition whose dist omits the version\n if (definition.dist.otelcol_version) {\n deps.push({\n datasource: GoDatasource.id,\n depType: 'collector',\n depName: 'go.opentelemetry.io/collector',\n currentValue: definition.dist.otelcol_version,\n extractVersion: '^v(?<version>\\\\S+)',\n });\n }\n\n deps.push(...processModule(definition.connectors, 'connectors'));\n deps.push(...processModule(definition.exporters, 'exports'));\n deps.push(...processModule(definition.extensions, 'extensions'));\n deps.push(...processModule(definition.processors, 'processors'));\n deps.push(...processModule(definition.providers, 'providers'));\n deps.push(...processModule(definition.receivers, 'receivers'));\n\n return {\n packageFileVersion: definition.dist.version,\n deps,\n };\n}\n\nexport function processModule(\n module: Module,\n depType: string,\n): PackageDependency[] {\n const deps: PackageDependency[] = [];\n if (isNullOrUndefined(module)) {\n return deps;\n }\n\n for (const element of module) {\n const [depName, currentValue] = element.gomod.trim().split(regEx(/\\s+/));\n deps.push({\n datasource: GoDatasource.id,\n depType,\n depName,\n currentValue,\n });\n }\n\n return deps;\n}\n"],"mappings":";;;;;;;AAYA,SAAgB,mBACd,SACA,aACA,SAC2B;CAC3B,IAAI,aAA+B;CACnC,IAAI;EACF,MAAM,OAAO,gBAAgB,OAAO;EACpC,MAAM,SAAS,UAAU,UAAU,IAAI;EACvC,IAAI,CAAC,OAAO,SAAS;GACnB,OAAO,MACL;IAAE;IAAa,KAAK,OAAO;GAAM,GACjC,4BACF;GACA,OAAO;EACT;EAEA,aAAa,OAAO;CACtB,SAAS,OAAO;EACd,OAAO,MACL;GAAE;GAAa,KAAK;EAAM,GAC1B,0CACF;EACA,OAAO;CACT;CAEA,MAAM,OAA4B,CAAC;;CAEnC,IAAI,WAAW,KAAK,iBAClB,KAAK,KAAK;EACR,YAAY,aAAa;EACzB,SAAS;EACT,SAAS;EACT,cAAc,WAAW,KAAK;EAC9B,gBAAgB;CAClB,CAAC;CAGH,KAAK,KAAK,GAAG,cAAc,WAAW,YAAY,YAAY,CAAC;CAC/D,KAAK,KAAK,GAAG,cAAc,WAAW,WAAW,SAAS,CAAC;CAC3D,KAAK,KAAK,GAAG,cAAc,WAAW,YAAY,YAAY,CAAC;CAC/D,KAAK,KAAK,GAAG,cAAc,WAAW,YAAY,YAAY,CAAC;CAC/D,KAAK,KAAK,GAAG,cAAc,WAAW,WAAW,WAAW,CAAC;CAC7D,KAAK,KAAK,GAAG,cAAc,WAAW,WAAW,WAAW,CAAC;CAE7D,OAAO;EACL,oBAAoB,WAAW,KAAK;EACpC;CACF;AACF;AAEA,SAAgB,cACd,QACA,SACqB;CACrB,MAAM,OAA4B,CAAC;CACnC,IAAI,kBAAkB,MAAM,GAC1B,OAAO;CAGT,KAAK,MAAM,WAAW,QAAQ;EAC5B,MAAM,CAAC,SAAS,gBAAgB,QAAQ,MAAM,KAAK,CAAC,CAAC,MAAM,MAAM,KAAK,CAAC;EACvE,KAAK,KAAK;GACR,YAAY,aAAa;GACzB;GACA;GACA;EACF,CAAC;CACH;CAEA,OAAO;AACT"}
|
|
@@ -181,7 +181,9 @@ async function getUvExtraIndexUrl(project, deps) {
|
|
|
181
181
|
if (!parsedUrl) continue;
|
|
182
182
|
const { username, password } = await getUsernamePassword(parsedUrl);
|
|
183
183
|
if (username || password) {
|
|
184
|
+
// v8 ignore else -- needs a host rule carrying only one of the two
|
|
184
185
|
if (username) parsedUrl.username = username;
|
|
186
|
+
// v8 ignore else -- needs a host rule carrying only one of the two
|
|
185
187
|
if (password) parsedUrl.password = password;
|
|
186
188
|
}
|
|
187
189
|
extraIndexUrls.push(parsedUrl.toString());
|
|
@@ -199,7 +201,9 @@ async function getUvIndexCredentials(project) {
|
|
|
199
201
|
if (!name) continue;
|
|
200
202
|
const { username, password } = await getUsernamePassword(parsedUrl);
|
|
201
203
|
const NAME = name.toUpperCase().replace(regEx(/[^A-Z0-9]/g), "_");
|
|
204
|
+
// v8 ignore else -- needs a host rule carrying only one of the two
|
|
202
205
|
if (username) entries.push([`UV_INDEX_${NAME}_USERNAME`, username]);
|
|
206
|
+
// v8 ignore else -- needs a host rule carrying only one of the two
|
|
203
207
|
if (password) entries.push([`UV_INDEX_${NAME}_PASSWORD`, password]);
|
|
204
208
|
}
|
|
205
209
|
return Object.fromEntries(entries);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uv.js","names":[],"sources":["../../../../../lib/modules/manager/pep621/processors/uv.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport { quote } from 'shlex';\nimport { TEMPORARY_ERROR } from '../../../../constants/error-messages.ts';\nimport { logger } from '../../../../logger/index.ts';\nimport type { HostRule } from '../../../../types/index.ts';\nimport { coerceArray } from '../../../../util/array.ts';\nimport type {\n ExecOptions,\n ToolConstraint,\n} from '../../../../util/exec/types.ts';\nimport {\n findLocalSiblingOrParent,\n readLocalFile,\n} from '../../../../util/fs/index.ts';\nimport { withGitEnvironment } from '../../../../util/git/exec.ts';\nimport { find } from '../../../../util/host-rules.ts';\nimport { regEx } from '../../../../util/regex.ts';\nimport { Result } from '../../../../util/result.ts';\nimport { parseUrl } from '../../../../util/url.ts';\nimport { PypiDatasource } from '../../../datasource/pypi/index.ts';\nimport { getGoogleAuthHostRule } from '../../../datasource/util.ts';\nimport type {\n PackageDependency,\n UpdateArtifact,\n UpdateArtifactsResult,\n Upgrade,\n} from '../../types.ts';\nimport { applyGitSource, resolveToolConstraint } from '../../util.ts';\nimport { type PyProject, UvLockfile, type UvSource } from '../schema.ts';\nimport { depTypes } from '../utils.ts';\nimport { BasePyProjectProcessor } from './abstract.ts';\n\nconst uvUpdateCMD = 'uv lock';\nconst gitExec = withGitEnvironment(['pep621']);\n\nfunction isUvIndexSource(\n source: UvSource,\n): source is Extract<UvSource, { index: string }> {\n return 'index' in source;\n}\n\nexport class UvProcessor extends BasePyProjectProcessor {\n override lockfileName = 'uv.lock';\n\n process(project: PyProject, deps: PackageDependency[]): PackageDependency[] {\n const uv = project.tool?.uv;\n if (!uv) {\n return deps;\n }\n\n const hasExplicitDefault = uv.index?.some(\n (index) => index.default && index.explicit,\n );\n const defaultIndex = uv.index?.find(\n (index) => index.default && !index.explicit,\n );\n const implicitIndexUrls = uv.index\n ?.filter((index) => !index.explicit && index.name !== defaultIndex?.name)\n ?.map(({ url }) => url);\n\n const devDependencies = uv['dev-dependencies'];\n if (devDependencies) {\n deps.push(...devDependencies);\n }\n\n // https://docs.astral.sh/uv/concepts/dependencies/#dependency-sources\n // Skip sources that do not make sense to handle (e.g. path).\n if (uv.sources || defaultIndex || implicitIndexUrls) {\n for (const dep of deps) {\n /* v8 ignore next -- needs test */\n if (!dep.packageName) {\n continue;\n }\n\n if (dep.depType === 'requires-python') {\n continue;\n }\n\n // Using `packageName` as it applies PEP 508 normalization, which is\n // also applied by uv when matching a source to a dependency.\n const depSources = uv.sources?.[dep.packageName];\n if (depSources) {\n // Dependency is pinned to one or more specific sources.\n dep.depType = depTypes.uvSources;\n if (depSources.every(isUvIndexSource)) {\n // Sources referencing an index, possibly disambiguated by\n // environment markers. Any of the indexes can serve the package,\n // so use all of them as registries.\n const registryUrls: string[] = [];\n for (const depSource of depSources) {\n const index = uv.index?.find(\n ({ name }) => name === depSource.index,\n );\n if (index) {\n registryUrls.push(index.url);\n }\n }\n if (registryUrls.length) {\n dep.registryUrls = [...new Set(registryUrls)];\n }\n } else if (depSources.length === 1) {\n const depSource = depSources[0];\n if ('git' in depSource) {\n applyGitSource(\n dep,\n depSource.git,\n depSource.rev,\n depSource.tag,\n depSource.branch,\n );\n } else if ('url' in depSource) {\n dep.skipReason = 'unsupported-url';\n } else if ('path' in depSource) {\n dep.skipReason = 'path-dependency';\n } else if ('workspace' in depSource) {\n dep.skipReason = 'inherited-dependency';\n } else {\n dep.skipReason = 'unknown-registry';\n }\n } else {\n // Multiple sources that are not all indexes (e.g. a git source\n // per platform) cannot be represented as a single update.\n dep.skipReason = 'unsupported';\n }\n } else {\n // Dependency is not pinned to a specific source, so we need to\n // determine the source based on the index configuration.\n if (hasExplicitDefault) {\n // don't fall back to pypi if there is an explicit default index\n dep.registryUrls = [];\n } else if (defaultIndex) {\n // There is a default index configured, so use it.\n dep.registryUrls = [defaultIndex.url];\n }\n\n if (implicitIndexUrls?.length) {\n // If there are implicit indexes, check them first and fall back\n // to the default.\n dep.registryUrls = implicitIndexUrls.concat(\n dep.registryUrls ?? PypiDatasource.defaultURL,\n );\n }\n }\n }\n }\n\n return deps;\n }\n\n async extractLockedVersions(\n project: PyProject,\n deps: PackageDependency[],\n packageFile: string,\n ): Promise<PackageDependency[]> {\n const lockFileName = await findLocalSiblingOrParent(\n packageFile,\n this.lockfileName,\n );\n if (lockFileName === null) {\n logger.debug({ packageFile }, `No uv lock file found`);\n } else {\n const lockFileContent = await readLocalFile(lockFileName, 'utf8');\n if (lockFileContent) {\n const { val: lockFileMapping, err } = Result.parse(\n lockFileContent,\n UvLockfile,\n ).unwrap();\n\n if (err) {\n logger.debug({ packageFile, err }, `Error parsing uv lock file`);\n } else {\n for (const dep of deps) {\n const packageName = dep.packageName;\n if (packageName && packageName in lockFileMapping) {\n dep.lockedVersion = lockFileMapping[packageName];\n }\n }\n }\n }\n }\n\n return Promise.resolve(deps);\n }\n\n async updateArtifacts(\n updateArtifact: UpdateArtifact,\n project: PyProject,\n ): Promise<UpdateArtifactsResult[] | null> {\n const { config, updatedDeps, packageFileName } = updateArtifact;\n\n const { isLockFileMaintenance } = config;\n\n // abort if no lockfile is defined\n const lockFileName = await findLocalSiblingOrParent(\n packageFileName,\n 'uv.lock',\n );\n if (lockFileName === null) {\n logger.debug({ packageFileName }, `No uv lock file found`);\n return null;\n }\n try {\n const existingLockFileContent = await readLocalFile(lockFileName, 'utf8');\n if (!existingLockFileContent) {\n logger.debug('No uv.lock found');\n return null;\n }\n\n const pythonConstraint: ToolConstraint = {\n toolName: 'python',\n constraint: await resolveToolConstraint(\n config,\n 'python',\n () => project.project?.['requires-python'],\n ),\n };\n const uvConstraint: ToolConstraint = {\n toolName: 'uv',\n constraint: await resolveToolConstraint(\n config,\n 'uv',\n () => project.tool?.uv?.['required-version'],\n ),\n };\n\n const extraEnv = {\n ...(await getUvExtraIndexUrl(project, updateArtifact.updatedDeps)),\n ...(await getUvIndexCredentials(project)),\n };\n const execOptions: ExecOptions = {\n cwdFile: packageFileName,\n extraEnv,\n docker: {},\n toolConstraints: [pythonConstraint, uvConstraint],\n };\n\n // on lockFileMaintenance do not specify any packages and update the complete lock file\n // else only update specific packages\n let cmd: string;\n if (isLockFileMaintenance) {\n cmd = `${uvUpdateCMD} --upgrade`;\n } else {\n cmd = generateCMD(updatedDeps);\n }\n await gitExec(cmd, execOptions);\n\n // check for changes\n const fileChanges: UpdateArtifactsResult[] = [];\n const newLockContent = await readLocalFile(lockFileName, 'utf8');\n const isLockFileChanged = existingLockFileContent !== newLockContent;\n if (isLockFileChanged) {\n fileChanges.push({\n file: {\n type: 'addition',\n path: lockFileName,\n contents: newLockContent,\n },\n });\n } else {\n logger.debug('uv.lock is unchanged');\n }\n\n return fileChanges.length ? fileChanges : null;\n } catch (err) {\n if (err.message === TEMPORARY_ERROR) {\n throw err;\n }\n logger.debug({ err }, 'Failed to update uv lock file');\n return [\n {\n artifactError: {\n fileName: lockFileName,\n stderr: err.message,\n },\n },\n ];\n }\n }\n}\n\nfunction generateCMD(updatedDeps: Upgrade[]): string {\n const deps: string[] = [];\n\n for (const dep of updatedDeps) {\n switch (dep.depType) {\n case depTypes.optionalDependencies: {\n deps.push(dep.depName!);\n break;\n }\n case depTypes.uvDevDependencies:\n case depTypes.uvSources: {\n deps.push(dep.depName!);\n break;\n }\n case depTypes.buildSystemRequires:\n // build requirements are not locked in the lock files, no need to update.\n break;\n default: {\n deps.push(dep.packageName!);\n }\n }\n }\n\n return `${uvUpdateCMD} ${deps.map((dep) => `--upgrade-package ${quote(dep)}`).join(' ')}`;\n}\n\nfunction getMatchingHostRule(url: string | undefined): HostRule {\n return find({ hostType: PypiDatasource.id, url });\n}\n\nasync function getUsernamePassword(\n url: URL,\n): Promise<{ username?: string; password?: string }> {\n const rule = getMatchingHostRule(url.toString());\n if (rule.username || rule.password) {\n return rule;\n }\n\n if (url.hostname.endsWith('.pkg.dev')) {\n const hostRule = await getGoogleAuthHostRule();\n if (hostRule) {\n return hostRule;\n }\n logger.once.debug({ url }, 'Could not get Google access token');\n }\n\n return {};\n}\n\nasync function getUvExtraIndexUrl(\n project: PyProject,\n deps: Upgrade[],\n): Promise<NodeJS.ProcessEnv> {\n const pyPiRegistryUrls = deps\n .filter((dep) => dep.datasource === PypiDatasource.id)\n .filter((dep) => {\n // Remove dependencies that are pinned to a specific index\n const sources = project.tool?.uv?.sources;\n const packageName = dep.packageName!;\n return !sources || !(packageName in sources);\n })\n .flatMap((dep) => dep.registryUrls)\n .filter(isString)\n .filter((registryUrl) => {\n // Check if the registry URL is not the default one and not already configured\n const configuredIndexUrls = coerceArray(\n project.tool?.uv?.index?.map(({ url }) => url),\n );\n return (\n registryUrl !== PypiDatasource.defaultURL &&\n !configuredIndexUrls.includes(registryUrl)\n );\n });\n\n const registryUrls = new Set(pyPiRegistryUrls);\n const extraIndexUrls: string[] = [];\n\n for (const registryUrl of registryUrls) {\n const parsedUrl = parseUrl(registryUrl);\n if (!parsedUrl) {\n continue;\n }\n\n const { username, password } = await getUsernamePassword(parsedUrl);\n if (username || password) {\n if (username) {\n parsedUrl.username = username;\n }\n if (password) {\n parsedUrl.password = password;\n }\n }\n\n extraIndexUrls.push(parsedUrl.toString());\n }\n\n return {\n UV_EXTRA_INDEX_URL: extraIndexUrls.join(' '),\n };\n}\n\nasync function getUvIndexCredentials(\n project: PyProject,\n): Promise<NodeJS.ProcessEnv> {\n const uv_indexes = project.tool?.uv?.index;\n\n if (!uv_indexes) {\n return {};\n }\n\n const entries = [];\n\n for (const { name, url } of uv_indexes) {\n const parsedUrl = parseUrl(url);\n /* v8 ignore next -- needs test */\n if (!parsedUrl) {\n continue;\n }\n\n // If no name is provided for the index, authentication information must be passed through alternative methods\n if (!name) {\n continue;\n }\n\n const { username, password } = await getUsernamePassword(parsedUrl);\n\n const NAME = name.toUpperCase().replace(regEx(/[^A-Z0-9]/g), '_');\n\n if (username) {\n entries.push([`UV_INDEX_${NAME}_USERNAME`, username]);\n }\n\n if (password) {\n entries.push([`UV_INDEX_${NAME}_PASSWORD`, password]);\n }\n }\n\n return Object.fromEntries(entries);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"uv.js","names":[],"sources":["../../../../../lib/modules/manager/pep621/processors/uv.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport { quote } from 'shlex';\nimport { TEMPORARY_ERROR } from '../../../../constants/error-messages.ts';\nimport { logger } from '../../../../logger/index.ts';\nimport type { HostRule } from '../../../../types/index.ts';\nimport { coerceArray } from '../../../../util/array.ts';\nimport type {\n ExecOptions,\n ToolConstraint,\n} from '../../../../util/exec/types.ts';\nimport {\n findLocalSiblingOrParent,\n readLocalFile,\n} from '../../../../util/fs/index.ts';\nimport { withGitEnvironment } from '../../../../util/git/exec.ts';\nimport { find } from '../../../../util/host-rules.ts';\nimport { regEx } from '../../../../util/regex.ts';\nimport { Result } from '../../../../util/result.ts';\nimport { parseUrl } from '../../../../util/url.ts';\nimport { PypiDatasource } from '../../../datasource/pypi/index.ts';\nimport { getGoogleAuthHostRule } from '../../../datasource/util.ts';\nimport type {\n PackageDependency,\n UpdateArtifact,\n UpdateArtifactsResult,\n Upgrade,\n} from '../../types.ts';\nimport { applyGitSource, resolveToolConstraint } from '../../util.ts';\nimport { type PyProject, UvLockfile, type UvSource } from '../schema.ts';\nimport { depTypes } from '../utils.ts';\nimport { BasePyProjectProcessor } from './abstract.ts';\n\nconst uvUpdateCMD = 'uv lock';\nconst gitExec = withGitEnvironment(['pep621']);\n\nfunction isUvIndexSource(\n source: UvSource,\n): source is Extract<UvSource, { index: string }> {\n return 'index' in source;\n}\n\nexport class UvProcessor extends BasePyProjectProcessor {\n override lockfileName = 'uv.lock';\n\n process(project: PyProject, deps: PackageDependency[]): PackageDependency[] {\n const uv = project.tool?.uv;\n if (!uv) {\n return deps;\n }\n\n const hasExplicitDefault = uv.index?.some(\n (index) => index.default && index.explicit,\n );\n const defaultIndex = uv.index?.find(\n (index) => index.default && !index.explicit,\n );\n const implicitIndexUrls = uv.index\n ?.filter((index) => !index.explicit && index.name !== defaultIndex?.name)\n ?.map(({ url }) => url);\n\n const devDependencies = uv['dev-dependencies'];\n if (devDependencies) {\n deps.push(...devDependencies);\n }\n\n // https://docs.astral.sh/uv/concepts/dependencies/#dependency-sources\n // Skip sources that do not make sense to handle (e.g. path).\n if (uv.sources || defaultIndex || implicitIndexUrls) {\n for (const dep of deps) {\n /* v8 ignore next -- needs test */\n if (!dep.packageName) {\n continue;\n }\n\n if (dep.depType === 'requires-python') {\n continue;\n }\n\n // Using `packageName` as it applies PEP 508 normalization, which is\n // also applied by uv when matching a source to a dependency.\n const depSources = uv.sources?.[dep.packageName];\n if (depSources) {\n // Dependency is pinned to one or more specific sources.\n dep.depType = depTypes.uvSources;\n if (depSources.every(isUvIndexSource)) {\n // Sources referencing an index, possibly disambiguated by\n // environment markers. Any of the indexes can serve the package,\n // so use all of them as registries.\n const registryUrls: string[] = [];\n for (const depSource of depSources) {\n const index = uv.index?.find(\n ({ name }) => name === depSource.index,\n );\n if (index) {\n registryUrls.push(index.url);\n }\n }\n if (registryUrls.length) {\n dep.registryUrls = [...new Set(registryUrls)];\n }\n } else if (depSources.length === 1) {\n const depSource = depSources[0];\n if ('git' in depSource) {\n applyGitSource(\n dep,\n depSource.git,\n depSource.rev,\n depSource.tag,\n depSource.branch,\n );\n } else if ('url' in depSource) {\n dep.skipReason = 'unsupported-url';\n } else if ('path' in depSource) {\n dep.skipReason = 'path-dependency';\n } else if ('workspace' in depSource) {\n dep.skipReason = 'inherited-dependency';\n } else {\n dep.skipReason = 'unknown-registry';\n }\n } else {\n // Multiple sources that are not all indexes (e.g. a git source\n // per platform) cannot be represented as a single update.\n dep.skipReason = 'unsupported';\n }\n } else {\n // Dependency is not pinned to a specific source, so we need to\n // determine the source based on the index configuration.\n if (hasExplicitDefault) {\n // don't fall back to pypi if there is an explicit default index\n dep.registryUrls = [];\n } else if (defaultIndex) {\n // There is a default index configured, so use it.\n dep.registryUrls = [defaultIndex.url];\n }\n\n if (implicitIndexUrls?.length) {\n // If there are implicit indexes, check them first and fall back\n // to the default.\n dep.registryUrls = implicitIndexUrls.concat(\n dep.registryUrls ?? PypiDatasource.defaultURL,\n );\n }\n }\n }\n }\n\n return deps;\n }\n\n async extractLockedVersions(\n project: PyProject,\n deps: PackageDependency[],\n packageFile: string,\n ): Promise<PackageDependency[]> {\n const lockFileName = await findLocalSiblingOrParent(\n packageFile,\n this.lockfileName,\n );\n if (lockFileName === null) {\n logger.debug({ packageFile }, `No uv lock file found`);\n } else {\n const lockFileContent = await readLocalFile(lockFileName, 'utf8');\n if (lockFileContent) {\n const { val: lockFileMapping, err } = Result.parse(\n lockFileContent,\n UvLockfile,\n ).unwrap();\n\n if (err) {\n logger.debug({ packageFile, err }, `Error parsing uv lock file`);\n } else {\n for (const dep of deps) {\n const packageName = dep.packageName;\n if (packageName && packageName in lockFileMapping) {\n dep.lockedVersion = lockFileMapping[packageName];\n }\n }\n }\n }\n }\n\n return Promise.resolve(deps);\n }\n\n async updateArtifacts(\n updateArtifact: UpdateArtifact,\n project: PyProject,\n ): Promise<UpdateArtifactsResult[] | null> {\n const { config, updatedDeps, packageFileName } = updateArtifact;\n\n const { isLockFileMaintenance } = config;\n\n // abort if no lockfile is defined\n const lockFileName = await findLocalSiblingOrParent(\n packageFileName,\n 'uv.lock',\n );\n if (lockFileName === null) {\n logger.debug({ packageFileName }, `No uv lock file found`);\n return null;\n }\n try {\n const existingLockFileContent = await readLocalFile(lockFileName, 'utf8');\n if (!existingLockFileContent) {\n logger.debug('No uv.lock found');\n return null;\n }\n\n const pythonConstraint: ToolConstraint = {\n toolName: 'python',\n constraint: await resolveToolConstraint(\n config,\n 'python',\n () => project.project?.['requires-python'],\n ),\n };\n const uvConstraint: ToolConstraint = {\n toolName: 'uv',\n constraint: await resolveToolConstraint(\n config,\n 'uv',\n () => project.tool?.uv?.['required-version'],\n ),\n };\n\n const extraEnv = {\n ...(await getUvExtraIndexUrl(project, updateArtifact.updatedDeps)),\n ...(await getUvIndexCredentials(project)),\n };\n const execOptions: ExecOptions = {\n cwdFile: packageFileName,\n extraEnv,\n docker: {},\n toolConstraints: [pythonConstraint, uvConstraint],\n };\n\n // on lockFileMaintenance do not specify any packages and update the complete lock file\n // else only update specific packages\n let cmd: string;\n if (isLockFileMaintenance) {\n cmd = `${uvUpdateCMD} --upgrade`;\n } else {\n cmd = generateCMD(updatedDeps);\n }\n await gitExec(cmd, execOptions);\n\n // check for changes\n const fileChanges: UpdateArtifactsResult[] = [];\n const newLockContent = await readLocalFile(lockFileName, 'utf8');\n const isLockFileChanged = existingLockFileContent !== newLockContent;\n if (isLockFileChanged) {\n fileChanges.push({\n file: {\n type: 'addition',\n path: lockFileName,\n contents: newLockContent,\n },\n });\n } else {\n logger.debug('uv.lock is unchanged');\n }\n\n return fileChanges.length ? fileChanges : null;\n } catch (err) {\n if (err.message === TEMPORARY_ERROR) {\n throw err;\n }\n logger.debug({ err }, 'Failed to update uv lock file');\n return [\n {\n artifactError: {\n fileName: lockFileName,\n stderr: err.message,\n },\n },\n ];\n }\n }\n}\n\nfunction generateCMD(updatedDeps: Upgrade[]): string {\n const deps: string[] = [];\n\n for (const dep of updatedDeps) {\n switch (dep.depType) {\n case depTypes.optionalDependencies: {\n deps.push(dep.depName!);\n break;\n }\n case depTypes.uvDevDependencies:\n case depTypes.uvSources: {\n deps.push(dep.depName!);\n break;\n }\n case depTypes.buildSystemRequires:\n // build requirements are not locked in the lock files, no need to update.\n break;\n default: {\n deps.push(dep.packageName!);\n }\n }\n }\n\n return `${uvUpdateCMD} ${deps.map((dep) => `--upgrade-package ${quote(dep)}`).join(' ')}`;\n}\n\nfunction getMatchingHostRule(url: string | undefined): HostRule {\n return find({ hostType: PypiDatasource.id, url });\n}\n\nasync function getUsernamePassword(\n url: URL,\n): Promise<{ username?: string; password?: string }> {\n const rule = getMatchingHostRule(url.toString());\n if (rule.username || rule.password) {\n return rule;\n }\n\n if (url.hostname.endsWith('.pkg.dev')) {\n const hostRule = await getGoogleAuthHostRule();\n if (hostRule) {\n return hostRule;\n }\n logger.once.debug({ url }, 'Could not get Google access token');\n }\n\n return {};\n}\n\nasync function getUvExtraIndexUrl(\n project: PyProject,\n deps: Upgrade[],\n): Promise<NodeJS.ProcessEnv> {\n const pyPiRegistryUrls = deps\n .filter((dep) => dep.datasource === PypiDatasource.id)\n .filter((dep) => {\n // Remove dependencies that are pinned to a specific index\n const sources = project.tool?.uv?.sources;\n const packageName = dep.packageName!;\n return !sources || !(packageName in sources);\n })\n .flatMap((dep) => dep.registryUrls)\n .filter(isString)\n .filter((registryUrl) => {\n // Check if the registry URL is not the default one and not already configured\n const configuredIndexUrls = coerceArray(\n project.tool?.uv?.index?.map(({ url }) => url),\n );\n return (\n registryUrl !== PypiDatasource.defaultURL &&\n !configuredIndexUrls.includes(registryUrl)\n );\n });\n\n const registryUrls = new Set(pyPiRegistryUrls);\n const extraIndexUrls: string[] = [];\n\n for (const registryUrl of registryUrls) {\n const parsedUrl = parseUrl(registryUrl);\n if (!parsedUrl) {\n continue;\n }\n\n const { username, password } = await getUsernamePassword(parsedUrl);\n if (username || password) {\n // v8 ignore else -- needs a host rule carrying only one of the two\n if (username) {\n parsedUrl.username = username;\n }\n // v8 ignore else -- needs a host rule carrying only one of the two\n if (password) {\n parsedUrl.password = password;\n }\n }\n\n extraIndexUrls.push(parsedUrl.toString());\n }\n\n return {\n UV_EXTRA_INDEX_URL: extraIndexUrls.join(' '),\n };\n}\n\nasync function getUvIndexCredentials(\n project: PyProject,\n): Promise<NodeJS.ProcessEnv> {\n const uv_indexes = project.tool?.uv?.index;\n\n if (!uv_indexes) {\n return {};\n }\n\n const entries = [];\n\n for (const { name, url } of uv_indexes) {\n const parsedUrl = parseUrl(url);\n /* v8 ignore next -- needs test */\n if (!parsedUrl) {\n continue;\n }\n\n // If no name is provided for the index, authentication information must be passed through alternative methods\n if (!name) {\n continue;\n }\n\n const { username, password } = await getUsernamePassword(parsedUrl);\n\n const NAME = name.toUpperCase().replace(regEx(/[^A-Z0-9]/g), '_');\n\n // v8 ignore else -- needs a host rule carrying only one of the two\n if (username) {\n entries.push([`UV_INDEX_${NAME}_USERNAME`, username]);\n }\n\n // v8 ignore else -- needs a host rule carrying only one of the two\n if (password) {\n entries.push([`UV_INDEX_${NAME}_PASSWORD`, password]);\n }\n }\n\n return Object.fromEntries(entries);\n}\n"],"mappings":"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"}
|
|
@@ -23,6 +23,7 @@ function DependencyGroup(depType) {
|
|
|
23
23
|
return LooseRecord(LooseArray(Pep508Dependency(depType))).transform((depGroups) => {
|
|
24
24
|
const deps = [];
|
|
25
25
|
for (const [depGroup, groupDeps] of Object.entries(depGroups)) for (const dep of groupDeps) {
|
|
26
|
+
// v8 ignore else -- the parser always sets a package name on a group dep
|
|
26
27
|
if (dep.packageName) dep.depName = dep.packageName;
|
|
27
28
|
dep.managerData = { depGroup };
|
|
28
29
|
deps.push(dep);
|
|
@@ -99,7 +100,9 @@ const ProjectSection = z.object({
|
|
|
99
100
|
const PixiMinimalConfig = z.object({
|
|
100
101
|
project: z.object({ "requires-pixi": z.string().optional() }).optional().catch(void 0),
|
|
101
102
|
workspace: z.object({ "requires-pixi": z.string().optional() }).optional().catch(void 0)
|
|
102
|
-
}).transform((val) => ({
|
|
103
|
+
}).transform((val) => ({
|
|
104
|
+
/* v8 ignore start: needs a pixi manifest declaring the requirement only under workspace */
|
|
105
|
+
"requires-pixi": val.project?.["requires-pixi"] ?? val.workspace?.["requires-pixi"] })).optional().catch(void 0);
|
|
103
106
|
const PyProject = z.object({
|
|
104
107
|
project: ProjectSection.optional().catch(void 0),
|
|
105
108
|
"build-system": z.object({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","names":["pep440"],"sources":["../../../../lib/modules/manager/pep621/schema.ts"],"sourcesContent":["import { z } from 'zod/v4';\nimport {\n LooseArray,\n LooseRecord,\n Toml,\n} from '../../../util/schema-utils/index.ts';\nimport { normalizePythonDepName } from '../../datasource/pypi/common.ts';\nimport { PypiDatasource } from '../../datasource/pypi/index.ts';\nimport { api as pep440 } from '../../versioning/pep440/index.ts';\nimport type { PackageDependency } from '../types.ts';\nimport { depTypes, pep508ToPackageDependency } from './utils.ts';\n\ntype Pep508Dependency = z.ZodType<PackageDependency>;\n\nfunction Pep508Dependency(depType: string): Pep508Dependency {\n return z.string().transform((x, ctx) => {\n const res = pep508ToPackageDependency(depType, x);\n\n if (!res) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'should be a valid PEP508 dependency',\n fatal: true,\n });\n\n return z.NEVER;\n }\n\n return res;\n }) as Pep508Dependency;\n}\n\ntype DependencyGroup = z.ZodType<PackageDependency[]>;\n\nexport function DependencyGroup(depType: string): DependencyGroup {\n return LooseRecord(LooseArray(Pep508Dependency(depType))).transform(\n (depGroups) => {\n const deps: PackageDependency[] = [];\n for (const [depGroup, groupDeps] of Object.entries(depGroups)) {\n for (const dep of groupDeps) {\n if (dep.packageName) {\n dep.depName = dep.packageName;\n }\n dep.managerData = { depGroup };\n deps.push(dep);\n }\n }\n return deps;\n },\n );\n}\n\nconst PdmConfig = z\n .object({\n 'dev-dependencies': DependencyGroup(depTypes.pdmDevDependencies).catch([]),\n source: LooseArray(\n z.object({\n url: z.string(),\n name: z.string(),\n }),\n )\n .transform((pdmSource) => {\n const registryUrls: string[] = [];\n\n let containsPyPiUrl = false;\n for (const source of pdmSource) {\n if (source.name === 'pypi') {\n containsPyPiUrl = true;\n }\n\n registryUrls.push(source.url);\n }\n\n // Add pypi default url, if there is no source declared with the name `pypi`\n // @see https://daobook.github.io/pdm/pyproject/tool-pdm/#specify-other-sources-for-finding-packages\n if (!containsPyPiUrl) {\n registryUrls.unshift(PypiDatasource.defaultURL);\n }\n\n return registryUrls;\n })\n .optional()\n .catch(undefined),\n })\n .transform(\n ({ 'dev-dependencies': devDependencies, source: registryUrls }) => ({\n devDependencies,\n registryUrls,\n }),\n );\n\nconst HatchConfig = z\n .object({\n envs: LooseRecord(\n z.string(),\n z.object({\n dependencies: z.unknown().optional(),\n 'extra-dependencies': z.unknown().optional(),\n }),\n ),\n })\n .catch({ envs: {} })\n .transform(({ envs }) => {\n const deps: PackageDependency[] = [];\n for (const [\n envName,\n { dependencies, 'extra-dependencies': extraDependencies },\n ] of Object.entries(envs)) {\n const depType = `tool.hatch.envs.${envName}`;\n const HatchDependency = LooseArray(Pep508Dependency(depType)).catch([]);\n deps.push(\n ...HatchDependency.parse(dependencies),\n ...HatchDependency.parse(extraDependencies),\n );\n }\n return { deps };\n });\n\nconst UvIndexSource = z.object({\n index: z.string(),\n});\n\nconst UvGitSource = z.object({\n git: z.string(),\n rev: z.string().optional(),\n tag: z.string().optional(),\n branch: z.string().optional(),\n});\nexport type UvGitSource = z.infer<typeof UvGitSource>;\n\nconst UvUrlSource = z.object({\n url: z.string(),\n});\n\nconst UvPathSource = z.object({\n path: z.string(),\n});\n\nconst UvWorkspaceSource = z.object({\n workspace: z.literal(true),\n});\n\n// https://docs.astral.sh/uv/concepts/dependencies/#dependency-sources\nconst UvSource = z.union([\n UvIndexSource,\n UvGitSource,\n UvUrlSource,\n UvPathSource,\n UvWorkspaceSource,\n]);\nexport type UvSource = z.infer<typeof UvSource>;\n\n// A dependency can declare a single source or, when disambiguated by\n// environment markers, an array of sources. Normalize both to an array.\n// https://docs.astral.sh/uv/concepts/projects/dependencies/#multiple-sources\nconst UvSources = z\n .union([UvSource, z.array(UvSource).min(1)])\n .transform((source) => (Array.isArray(source) ? source : [source]));\n\nconst UvConfig = z.object({\n 'dev-dependencies': LooseArray(\n Pep508Dependency(depTypes.uvDevDependencies),\n ).catch([]),\n 'required-version': z.string().optional(),\n sources: LooseRecord(\n // uv applies the same normalization as for Python dependencies on sources\n z.string().transform((source) => normalizePythonDepName(source)),\n UvSources,\n ).optional(),\n index: z\n .array(\n z.object({\n name: z.string().optional(),\n url: z.string(),\n default: z.boolean().default(false),\n explicit: z.boolean().default(false),\n }),\n )\n .optional(),\n});\n\nexport const ProjectSection = z.object({\n version: z.string().optional().catch(undefined),\n 'requires-python': z.string().optional().catch(undefined),\n dependencies: LooseArray(Pep508Dependency(depTypes.dependencies)).catch([]),\n 'optional-dependencies': DependencyGroup(depTypes.optionalDependencies).catch(\n [],\n ),\n});\n\nconst PixiMinimalConfig = z\n .object({\n project: z\n .object({ 'requires-pixi': z.string().optional() })\n .optional()\n .catch(undefined),\n workspace: z\n .object({ 'requires-pixi': z.string().optional() })\n .optional()\n .catch(undefined),\n })\n .transform((val) => ({\n 'requires-pixi':\n val.project?.['requires-pixi'] ?? val.workspace?.['requires-pixi'],\n }))\n .optional()\n .catch(undefined);\n\nexport const PyProject = z.object({\n project: ProjectSection.optional().catch(undefined),\n 'build-system': z\n .object({\n requires: LooseArray(\n Pep508Dependency(depTypes.buildSystemRequires),\n ).catch([]),\n 'build-backend': z.string().optional().catch(undefined),\n })\n .optional()\n .catch(undefined),\n 'dependency-groups': DependencyGroup(depTypes.dependencyGroups).catch([]),\n tool: z\n .object({\n pdm: PdmConfig.optional().catch(undefined),\n hatch: HatchConfig.optional().catch(undefined),\n uv: UvConfig.optional().catch(undefined),\n pixi: PixiMinimalConfig,\n })\n .optional()\n .catch(undefined),\n});\nexport type PyProject = z.infer<typeof PyProject>;\n\nexport const PdmLockfile = Toml.pipe(\n z.object({\n package: LooseArray(\n z.object({\n name: z.string(),\n version: z.string(),\n }),\n ),\n }),\n)\n .transform(({ package: pkg }) =>\n Object.fromEntries(\n pkg.map(({ name, version }): [string, string] => [name, version]),\n ),\n )\n .transform((lock) => ({ lock }));\n\nexport const UvLockfile = Toml.pipe(\n z.object({\n package: LooseArray(\n z.object({\n name: z.string(),\n version: z.string(),\n }),\n ),\n }),\n).transform(({ package: pkgs }) => {\n const pkgMap: Record<string, string> = {};\n\n for (const { name, version } of pkgs) {\n if (!(name in pkgMap) || pep440.isGreaterThan(pkgMap[name], version)) {\n pkgMap[name] = version;\n }\n }\n\n return pkgMap;\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema.js","names":["pep440"],"sources":["../../../../lib/modules/manager/pep621/schema.ts"],"sourcesContent":["import { z } from 'zod/v4';\nimport {\n LooseArray,\n LooseRecord,\n Toml,\n} from '../../../util/schema-utils/index.ts';\nimport { normalizePythonDepName } from '../../datasource/pypi/common.ts';\nimport { PypiDatasource } from '../../datasource/pypi/index.ts';\nimport { api as pep440 } from '../../versioning/pep440/index.ts';\nimport type { PackageDependency } from '../types.ts';\nimport { depTypes, pep508ToPackageDependency } from './utils.ts';\n\ntype Pep508Dependency = z.ZodType<PackageDependency>;\n\nfunction Pep508Dependency(depType: string): Pep508Dependency {\n return z.string().transform((x, ctx) => {\n const res = pep508ToPackageDependency(depType, x);\n\n if (!res) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'should be a valid PEP508 dependency',\n fatal: true,\n });\n\n return z.NEVER;\n }\n\n return res;\n }) as Pep508Dependency;\n}\n\ntype DependencyGroup = z.ZodType<PackageDependency[]>;\n\nexport function DependencyGroup(depType: string): DependencyGroup {\n return LooseRecord(LooseArray(Pep508Dependency(depType))).transform(\n (depGroups) => {\n const deps: PackageDependency[] = [];\n for (const [depGroup, groupDeps] of Object.entries(depGroups)) {\n for (const dep of groupDeps) {\n // v8 ignore else -- the parser always sets a package name on a group dep\n if (dep.packageName) {\n dep.depName = dep.packageName;\n }\n dep.managerData = { depGroup };\n deps.push(dep);\n }\n }\n return deps;\n },\n );\n}\n\nconst PdmConfig = z\n .object({\n 'dev-dependencies': DependencyGroup(depTypes.pdmDevDependencies).catch([]),\n source: LooseArray(\n z.object({\n url: z.string(),\n name: z.string(),\n }),\n )\n .transform((pdmSource) => {\n const registryUrls: string[] = [];\n\n let containsPyPiUrl = false;\n for (const source of pdmSource) {\n if (source.name === 'pypi') {\n containsPyPiUrl = true;\n }\n\n registryUrls.push(source.url);\n }\n\n // Add pypi default url, if there is no source declared with the name `pypi`\n // @see https://daobook.github.io/pdm/pyproject/tool-pdm/#specify-other-sources-for-finding-packages\n if (!containsPyPiUrl) {\n registryUrls.unshift(PypiDatasource.defaultURL);\n }\n\n return registryUrls;\n })\n .optional()\n .catch(undefined),\n })\n .transform(\n ({ 'dev-dependencies': devDependencies, source: registryUrls }) => ({\n devDependencies,\n registryUrls,\n }),\n );\n\nconst HatchConfig = z\n .object({\n envs: LooseRecord(\n z.string(),\n z.object({\n dependencies: z.unknown().optional(),\n 'extra-dependencies': z.unknown().optional(),\n }),\n ),\n })\n .catch({ envs: {} })\n .transform(({ envs }) => {\n const deps: PackageDependency[] = [];\n for (const [\n envName,\n { dependencies, 'extra-dependencies': extraDependencies },\n ] of Object.entries(envs)) {\n const depType = `tool.hatch.envs.${envName}`;\n const HatchDependency = LooseArray(Pep508Dependency(depType)).catch([]);\n deps.push(\n ...HatchDependency.parse(dependencies),\n ...HatchDependency.parse(extraDependencies),\n );\n }\n return { deps };\n });\n\nconst UvIndexSource = z.object({\n index: z.string(),\n});\n\nconst UvGitSource = z.object({\n git: z.string(),\n rev: z.string().optional(),\n tag: z.string().optional(),\n branch: z.string().optional(),\n});\nexport type UvGitSource = z.infer<typeof UvGitSource>;\n\nconst UvUrlSource = z.object({\n url: z.string(),\n});\n\nconst UvPathSource = z.object({\n path: z.string(),\n});\n\nconst UvWorkspaceSource = z.object({\n workspace: z.literal(true),\n});\n\n// https://docs.astral.sh/uv/concepts/dependencies/#dependency-sources\nconst UvSource = z.union([\n UvIndexSource,\n UvGitSource,\n UvUrlSource,\n UvPathSource,\n UvWorkspaceSource,\n]);\nexport type UvSource = z.infer<typeof UvSource>;\n\n// A dependency can declare a single source or, when disambiguated by\n// environment markers, an array of sources. Normalize both to an array.\n// https://docs.astral.sh/uv/concepts/projects/dependencies/#multiple-sources\nconst UvSources = z\n .union([UvSource, z.array(UvSource).min(1)])\n .transform((source) => (Array.isArray(source) ? source : [source]));\n\nconst UvConfig = z.object({\n 'dev-dependencies': LooseArray(\n Pep508Dependency(depTypes.uvDevDependencies),\n ).catch([]),\n 'required-version': z.string().optional(),\n sources: LooseRecord(\n // uv applies the same normalization as for Python dependencies on sources\n z.string().transform((source) => normalizePythonDepName(source)),\n UvSources,\n ).optional(),\n index: z\n .array(\n z.object({\n name: z.string().optional(),\n url: z.string(),\n default: z.boolean().default(false),\n explicit: z.boolean().default(false),\n }),\n )\n .optional(),\n});\n\nexport const ProjectSection = z.object({\n version: z.string().optional().catch(undefined),\n 'requires-python': z.string().optional().catch(undefined),\n dependencies: LooseArray(Pep508Dependency(depTypes.dependencies)).catch([]),\n 'optional-dependencies': DependencyGroup(depTypes.optionalDependencies).catch(\n [],\n ),\n});\n\nconst PixiMinimalConfig = z\n .object({\n project: z\n .object({ 'requires-pixi': z.string().optional() })\n .optional()\n .catch(undefined),\n workspace: z\n .object({ 'requires-pixi': z.string().optional() })\n .optional()\n .catch(undefined),\n })\n .transform((val) => ({\n /* v8 ignore start: needs a pixi manifest declaring the requirement only under workspace */\n 'requires-pixi':\n val.project?.['requires-pixi'] ?? val.workspace?.['requires-pixi'],\n /* v8 ignore stop */\n }))\n .optional()\n .catch(undefined);\n\nexport const PyProject = z.object({\n project: ProjectSection.optional().catch(undefined),\n 'build-system': z\n .object({\n requires: LooseArray(\n Pep508Dependency(depTypes.buildSystemRequires),\n ).catch([]),\n 'build-backend': z.string().optional().catch(undefined),\n })\n .optional()\n .catch(undefined),\n 'dependency-groups': DependencyGroup(depTypes.dependencyGroups).catch([]),\n tool: z\n .object({\n pdm: PdmConfig.optional().catch(undefined),\n hatch: HatchConfig.optional().catch(undefined),\n uv: UvConfig.optional().catch(undefined),\n pixi: PixiMinimalConfig,\n })\n .optional()\n .catch(undefined),\n});\nexport type PyProject = z.infer<typeof PyProject>;\n\nexport const PdmLockfile = Toml.pipe(\n z.object({\n package: LooseArray(\n z.object({\n name: z.string(),\n version: z.string(),\n }),\n ),\n }),\n)\n .transform(({ package: pkg }) =>\n Object.fromEntries(\n pkg.map(({ name, version }): [string, string] => [name, version]),\n ),\n )\n .transform((lock) => ({ lock }));\n\nexport const UvLockfile = Toml.pipe(\n z.object({\n package: LooseArray(\n z.object({\n name: z.string(),\n version: z.string(),\n }),\n ),\n }),\n).transform(({ package: pkgs }) => {\n const pkgMap: Record<string, string> = {};\n\n for (const { name, version } of pkgs) {\n if (!(name in pkgMap) || pep440.isGreaterThan(pkgMap[name], version)) {\n pkgMap[name] = version;\n }\n }\n\n return pkgMap;\n});\n"],"mappings":"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"}
|
|
@@ -108,6 +108,7 @@ function extractHeaderCommand(content, fileName) {
|
|
|
108
108
|
if (command === "pip-compile") commandType = "pip-compile";
|
|
109
109
|
else if (command === "uv") commandType = "uv";
|
|
110
110
|
else commandType = "custom";
|
|
111
|
+
// v8 ignore else -- a compile command always records its arguments
|
|
111
112
|
if (compileCommand.groups.arguments) argv.push(...split(compileCommand.groups.arguments));
|
|
112
113
|
logger.debug({
|
|
113
114
|
fileName,
|
|
@@ -209,6 +210,7 @@ function getRegistryCredEnvVars(url, index) {
|
|
|
209
210
|
const hostRule = find({ url: url.href });
|
|
210
211
|
logger.debug(hostRule, `Found host rule for url ${url.href}`);
|
|
211
212
|
const ret = {};
|
|
213
|
+
// v8 ignore else -- needs an index url whose host rule carries no credentials
|
|
212
214
|
if (!!hostRule.username || !!hostRule.password) {
|
|
213
215
|
ret[`KEYRING_SERVICE_NAME_${index}`] = url.hostname;
|
|
214
216
|
ret[`KEYRING_SERVICE_USERNAME_${index}`] = hostRule.username ?? "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","names":["hostRules.find"],"sources":["../../../../lib/modules/manager/pip-compile/common.ts"],"sourcesContent":["import { split } from 'shlex';\nimport upath from 'upath';\nimport { logger } from '../../../logger/index.ts';\nimport { coerceArray, isNotNullOrUndefined } from '../../../util/array.ts';\nimport type {\n ExecOptions,\n ExtraEnv,\n ToolConstraint,\n} from '../../../util/exec/types.ts';\nimport { ensureCacheDir } from '../../../util/fs/index.ts';\nimport { ensureLocalPath } from '../../../util/fs/util.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport type { PackageFileContent, UpdateArtifactsConfig } from '../types.ts';\nimport { resolveToolConstraint } from '../util.ts';\nimport type {\n CommandType,\n PipCompileArgs,\n SupportedManagers,\n} from './types.ts';\n\nexport async function getPythonVersionConstraint(\n config: UpdateArtifactsConfig,\n extractedPythonVersion: string | undefined,\n): Promise<string | undefined> {\n return await resolveToolConstraint(config, 'python', () => {\n if (extractedPythonVersion) {\n logger.debug('Using python constraint extracted from the lock file');\n return `==${extractedPythonVersion}`;\n }\n\n return undefined;\n });\n}\n\nexport async function getToolVersionConstraint(\n config: UpdateArtifactsConfig,\n commandType: CommandType,\n): Promise<ToolConstraint> {\n if (commandType === 'uv') {\n return {\n toolName: 'uv',\n constraint: await resolveToolConstraint(config, 'uv'),\n };\n }\n\n return {\n toolName: 'pip-tools',\n constraint: await resolveToolConstraint(config, 'pipTools'),\n };\n}\n\nexport async function getExecOptions(\n config: UpdateArtifactsConfig,\n commandType: CommandType,\n cwd: string,\n extraEnv: ExtraEnv<string>,\n extractedPythonVersion: string | undefined,\n): Promise<ExecOptions> {\n const constraint = await getPythonVersionConstraint(\n config,\n extractedPythonVersion,\n );\n const execOptions: ExecOptions = {\n cwd: ensureLocalPath(cwd),\n docker: {},\n toolConstraints: [\n {\n toolName: 'python',\n constraint,\n },\n await getToolVersionConstraint(config, commandType),\n ],\n extraEnv: {\n PIP_CACHE_DIR: await ensureCacheDir('pip'),\n PIP_NO_INPUT: 'true', // ensure pip doesn't block forever waiting for credentials on stdin\n PIP_KEYRING_PROVIDER: 'import',\n PYTHON_KEYRING_BACKEND: 'keyrings.envvars.keyring.EnvvarsKeyring',\n ...extraEnv,\n },\n };\n return execOptions;\n}\n\nexport const constraintLineRegex = regEx(\n /^(?:#.*?\\r?\\n)+# {4}(?<command>\\S*)(?<arguments> .*?)?\\r?\\n/,\n);\n\nexport const disallowedPipOptions = [\n '--no-header', // header is required by this manager\n];\nconst commonOptionsWithArguments = [\n '--output-file',\n '--extra',\n '--extra-index-url',\n];\nconst pipOptionsWithArguments = [\n '--resolver',\n '--constraint',\n ...commonOptionsWithArguments,\n];\nconst uvOptionsWithArguments = [\n '--constraints',\n '--constraint', // singular alias accepted by uv\n '--python-version',\n '--no-emit-package',\n '--prerelease',\n '--format',\n '--resolution',\n '--fork-strategy',\n '--exclude-newer',\n '--exclude-newer-package',\n '--group',\n '--override',\n '--overrides',\n ...commonOptionsWithArguments,\n];\nexport const optionsWithArguments = [\n ...pipOptionsWithArguments,\n ...uvOptionsWithArguments,\n];\nconst allowedCommonOptions = [\n '-v',\n '--generate-hashes',\n '--emit-index-url',\n '--index-url',\n '--all-extras',\n];\nexport const allowedOptions: Record<CommandType, string[]> = {\n 'pip-compile': [\n '--allow-unsafe',\n '--generate-hashes',\n '--no-emit-index-url',\n '--strip-extras',\n ...allowedCommonOptions,\n ...pipOptionsWithArguments,\n ],\n uv: [\n '--no-strip-extras',\n '--universal',\n ...allowedCommonOptions,\n ...uvOptionsWithArguments,\n ],\n custom: [],\n};\n\n// TODO(not7cd): test on all correct headers, even with CUSTOM_COMPILE_COMMAND\nexport function extractHeaderCommand(\n content: string,\n fileName: string,\n): PipCompileArgs {\n const compileCommand = constraintLineRegex.exec(content);\n if (compileCommand?.groups === undefined) {\n throw new Error(\n `Failed to extract command from header in ${fileName} ${content}`,\n );\n }\n logger.trace(\n `pip-compile: found header in ${fileName}: \\n${compileCommand[0]}`,\n );\n const command = compileCommand.groups.command;\n const argv = [command];\n let commandType: CommandType;\n if (command === 'pip-compile') {\n commandType = 'pip-compile';\n } else if (command === 'uv') {\n commandType = 'uv';\n } else {\n commandType = 'custom';\n }\n if (compileCommand.groups.arguments) {\n argv.push(...split(compileCommand.groups.arguments));\n }\n logger.debug(\n { fileName, argv, commandType },\n `pip-compile: extracted command from header`,\n );\n\n const result: PipCompileArgs = {\n argv,\n command,\n commandType,\n outputFile: '',\n sourceFiles: [],\n };\n for (const arg of argv.slice(1)) {\n if (commandType === 'uv' && ['pip', 'compile'].includes(arg)) {\n continue;\n }\n // TODO(not7cd): check for \"--option -- argument\" case\n if (!arg.startsWith('-')) {\n result.sourceFiles.push(arg);\n continue;\n }\n throwForDisallowedOption(arg);\n throwForNoEqualSignInOptionWithArgument(arg);\n throwForUnknownOption(commandType, arg);\n\n if (arg.includes('=')) {\n const [option, value] = arg.split('=');\n if (option === '--extra') {\n result.extra = coerceArray(result.extra);\n result.extra.push(value);\n } else if (option === '--extra-index-url') {\n result.extraIndexUrl = coerceArray(result.extraIndexUrl);\n result.extraIndexUrl.push(value);\n // TODO: add to secrets? next PR\n } else if (['--constraint', '--constraints'].includes(option)) {\n result.constraintsFiles = coerceArray(result.constraintsFiles);\n result.constraintsFiles.push(value);\n } else if (['--override', '--overrides'].includes(option)) {\n result.overridesFiles = coerceArray(result.overridesFiles);\n result.overridesFiles.push(value);\n } else if (option === '--output-file') {\n if (result.outputFile) {\n throw new Error('Cannot use multiple --output-file options');\n }\n result.outputFile = upath.normalize(value);\n } else if (option === '--python-version') {\n result.pythonVersion = value;\n } else if (option === '--index-url') {\n if (result.indexUrl) {\n throw new Error('Cannot use multiple --index-url options');\n }\n result.indexUrl = value;\n // TODO: add to secrets? next PR\n } else {\n logger.debug({ option }, `pip-compile: option not handled`);\n }\n continue;\n }\n if (arg === '--no-emit-index-url') {\n result.noEmitIndexUrl = true;\n continue;\n }\n if (arg === '--emit-index-url') {\n result.emitIndexUrl = true;\n continue;\n }\n if (arg === '--all-extras') {\n result.allExtras = true;\n continue;\n }\n\n logger.debug({ option: arg }, `pip-compile: option not handled`);\n }\n logger.trace(\n {\n ...result,\n },\n 'Parsed pip-compile command from header',\n );\n if (result.noEmitIndexUrl && result.emitIndexUrl) {\n throw new Error('Cannot use both --no-emit-index-url and --emit-index-url');\n }\n if (result.sourceFiles.length === 0) {\n throw new Error(\n 'No source files detected in command, pass at least one package file explicitly',\n );\n }\n return result;\n}\n\nconst pythonVersionRegex = regEx(\n /^(?:#.*?\\r?\\n)*# This file is autogenerated by pip-compile with Python (?<pythonVersion>\\d+(?:\\.\\d+)*)\\s/,\n 'i',\n);\n\nexport function extractPythonVersion(\n content: string,\n fileName: string,\n): string | undefined {\n const match = pythonVersionRegex.exec(content);\n if (match?.groups === undefined) {\n logger.warn(\n { fileName, content },\n 'pip-compile: failed to extract Python version from header in file',\n );\n return undefined;\n }\n logger.trace(\n `pip-compile: found Python version header in ${fileName}: \\n${match[0]}`,\n );\n const { pythonVersion } = match.groups;\n logger.debug(\n { fileName, pythonVersion },\n `pip-compile: extracted Python version from header`,\n );\n return pythonVersion;\n}\n\nfunction throwForDisallowedOption(arg: string): void {\n if (disallowedPipOptions.includes(arg)) {\n throw new Error(`Option ${arg} not allowed for this manager`);\n }\n}\nfunction throwForNoEqualSignInOptionWithArgument(arg: string): void {\n if (optionsWithArguments.includes(arg)) {\n throw new Error(\n `Option ${arg} must have equal sign '=' separating it's argument`,\n );\n }\n}\nfunction throwForUnknownOption(commandType: CommandType, arg: string): void {\n if (arg.includes('=')) {\n const [option] = arg.split('=');\n if (allowedOptions[commandType].includes(option)) {\n return;\n }\n }\n if (allowedOptions[commandType].includes(arg)) {\n return;\n }\n throw new Error(`Option ${arg} not supported (yet)`);\n}\n\nfunction getRegistryCredEnvVars(\n url: URL,\n index: number,\n): Record<string, string> {\n const hostRule = hostRules.find({ url: url.href });\n logger.debug(hostRule, `Found host rule for url ${url.href}`);\n const ret: Record<string, string> = {};\n if (!!hostRule.username || !!hostRule.password) {\n ret[`KEYRING_SERVICE_NAME_${index}`] = url.hostname;\n ret[`KEYRING_SERVICE_USERNAME_${index}`] = hostRule.username ?? '';\n ret[`KEYRING_SERVICE_PASSWORD_${index}`] = hostRule.password ?? '';\n }\n return ret;\n}\n\nfunction cleanUrl(url: string): URL | null {\n // Strip everything but protocol, host, and port\n const urlObj = parseUrl(url);\n if (!urlObj) {\n return null;\n }\n // origin of a valid URL is always parseable\n return parseUrl(urlObj.origin);\n}\n\nexport function getRegistryCredVarsFromPackageFiles(\n packageFiles: PackageFileContent[],\n): ExtraEnv<string> {\n const urls: string[] = [];\n for (const packageFile of packageFiles) {\n urls.push(\n ...coerceArray(packageFile.registryUrls),\n ...coerceArray(packageFile.additionalRegistryUrls),\n );\n }\n logger.debug(urls, 'Extracted registry URLs from package files');\n\n const uniqueHosts = new Set<URL>(\n urls.map(cleanUrl).filter(isNotNullOrUndefined),\n );\n\n let allCreds: ExtraEnv<string> = {};\n for (const [index, host] of [...uniqueHosts].entries()) {\n const hostCreds = getRegistryCredEnvVars(host, index);\n allCreds = {\n ...allCreds,\n ...hostCreds,\n };\n }\n\n return allCreds;\n}\n\nexport function matchManager(filename: string): SupportedManagers | 'unknown' {\n if (filename.endsWith('setup.py')) {\n return 'pip_setup';\n }\n if (filename.endsWith('setup.cfg')) {\n return 'setup-cfg';\n }\n if (filename.endsWith('pyproject.toml')) {\n return 'pep621';\n }\n // naive, could be improved, maybe use pip_requirements.managerFilePatterns\n if (filename.endsWith('.in') || filename.endsWith('.txt')) {\n return 'pip_requirements';\n }\n return 'unknown';\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"common.js","names":["hostRules.find"],"sources":["../../../../lib/modules/manager/pip-compile/common.ts"],"sourcesContent":["import { split } from 'shlex';\nimport upath from 'upath';\nimport { logger } from '../../../logger/index.ts';\nimport { coerceArray, isNotNullOrUndefined } from '../../../util/array.ts';\nimport type {\n ExecOptions,\n ExtraEnv,\n ToolConstraint,\n} from '../../../util/exec/types.ts';\nimport { ensureCacheDir } from '../../../util/fs/index.ts';\nimport { ensureLocalPath } from '../../../util/fs/util.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport type { PackageFileContent, UpdateArtifactsConfig } from '../types.ts';\nimport { resolveToolConstraint } from '../util.ts';\nimport type {\n CommandType,\n PipCompileArgs,\n SupportedManagers,\n} from './types.ts';\n\nexport async function getPythonVersionConstraint(\n config: UpdateArtifactsConfig,\n extractedPythonVersion: string | undefined,\n): Promise<string | undefined> {\n return await resolveToolConstraint(config, 'python', () => {\n if (extractedPythonVersion) {\n logger.debug('Using python constraint extracted from the lock file');\n return `==${extractedPythonVersion}`;\n }\n\n return undefined;\n });\n}\n\nexport async function getToolVersionConstraint(\n config: UpdateArtifactsConfig,\n commandType: CommandType,\n): Promise<ToolConstraint> {\n if (commandType === 'uv') {\n return {\n toolName: 'uv',\n constraint: await resolveToolConstraint(config, 'uv'),\n };\n }\n\n return {\n toolName: 'pip-tools',\n constraint: await resolveToolConstraint(config, 'pipTools'),\n };\n}\n\nexport async function getExecOptions(\n config: UpdateArtifactsConfig,\n commandType: CommandType,\n cwd: string,\n extraEnv: ExtraEnv<string>,\n extractedPythonVersion: string | undefined,\n): Promise<ExecOptions> {\n const constraint = await getPythonVersionConstraint(\n config,\n extractedPythonVersion,\n );\n const execOptions: ExecOptions = {\n cwd: ensureLocalPath(cwd),\n docker: {},\n toolConstraints: [\n {\n toolName: 'python',\n constraint,\n },\n await getToolVersionConstraint(config, commandType),\n ],\n extraEnv: {\n PIP_CACHE_DIR: await ensureCacheDir('pip'),\n PIP_NO_INPUT: 'true', // ensure pip doesn't block forever waiting for credentials on stdin\n PIP_KEYRING_PROVIDER: 'import',\n PYTHON_KEYRING_BACKEND: 'keyrings.envvars.keyring.EnvvarsKeyring',\n ...extraEnv,\n },\n };\n return execOptions;\n}\n\nexport const constraintLineRegex = regEx(\n /^(?:#.*?\\r?\\n)+# {4}(?<command>\\S*)(?<arguments> .*?)?\\r?\\n/,\n);\n\nexport const disallowedPipOptions = [\n '--no-header', // header is required by this manager\n];\nconst commonOptionsWithArguments = [\n '--output-file',\n '--extra',\n '--extra-index-url',\n];\nconst pipOptionsWithArguments = [\n '--resolver',\n '--constraint',\n ...commonOptionsWithArguments,\n];\nconst uvOptionsWithArguments = [\n '--constraints',\n '--constraint', // singular alias accepted by uv\n '--python-version',\n '--no-emit-package',\n '--prerelease',\n '--format',\n '--resolution',\n '--fork-strategy',\n '--exclude-newer',\n '--exclude-newer-package',\n '--group',\n '--override',\n '--overrides',\n ...commonOptionsWithArguments,\n];\nexport const optionsWithArguments = [\n ...pipOptionsWithArguments,\n ...uvOptionsWithArguments,\n];\nconst allowedCommonOptions = [\n '-v',\n '--generate-hashes',\n '--emit-index-url',\n '--index-url',\n '--all-extras',\n];\nexport const allowedOptions: Record<CommandType, string[]> = {\n 'pip-compile': [\n '--allow-unsafe',\n '--generate-hashes',\n '--no-emit-index-url',\n '--strip-extras',\n ...allowedCommonOptions,\n ...pipOptionsWithArguments,\n ],\n uv: [\n '--no-strip-extras',\n '--universal',\n ...allowedCommonOptions,\n ...uvOptionsWithArguments,\n ],\n custom: [],\n};\n\n// TODO(not7cd): test on all correct headers, even with CUSTOM_COMPILE_COMMAND\nexport function extractHeaderCommand(\n content: string,\n fileName: string,\n): PipCompileArgs {\n const compileCommand = constraintLineRegex.exec(content);\n if (compileCommand?.groups === undefined) {\n throw new Error(\n `Failed to extract command from header in ${fileName} ${content}`,\n );\n }\n logger.trace(\n `pip-compile: found header in ${fileName}: \\n${compileCommand[0]}`,\n );\n const command = compileCommand.groups.command;\n const argv = [command];\n let commandType: CommandType;\n if (command === 'pip-compile') {\n commandType = 'pip-compile';\n } else if (command === 'uv') {\n commandType = 'uv';\n } else {\n commandType = 'custom';\n }\n // v8 ignore else -- a compile command always records its arguments\n if (compileCommand.groups.arguments) {\n argv.push(...split(compileCommand.groups.arguments));\n }\n logger.debug(\n { fileName, argv, commandType },\n `pip-compile: extracted command from header`,\n );\n\n const result: PipCompileArgs = {\n argv,\n command,\n commandType,\n outputFile: '',\n sourceFiles: [],\n };\n for (const arg of argv.slice(1)) {\n if (commandType === 'uv' && ['pip', 'compile'].includes(arg)) {\n continue;\n }\n // TODO(not7cd): check for \"--option -- argument\" case\n if (!arg.startsWith('-')) {\n result.sourceFiles.push(arg);\n continue;\n }\n throwForDisallowedOption(arg);\n throwForNoEqualSignInOptionWithArgument(arg);\n throwForUnknownOption(commandType, arg);\n\n if (arg.includes('=')) {\n const [option, value] = arg.split('=');\n if (option === '--extra') {\n result.extra = coerceArray(result.extra);\n result.extra.push(value);\n } else if (option === '--extra-index-url') {\n result.extraIndexUrl = coerceArray(result.extraIndexUrl);\n result.extraIndexUrl.push(value);\n // TODO: add to secrets? next PR\n } else if (['--constraint', '--constraints'].includes(option)) {\n result.constraintsFiles = coerceArray(result.constraintsFiles);\n result.constraintsFiles.push(value);\n } else if (['--override', '--overrides'].includes(option)) {\n result.overridesFiles = coerceArray(result.overridesFiles);\n result.overridesFiles.push(value);\n } else if (option === '--output-file') {\n if (result.outputFile) {\n throw new Error('Cannot use multiple --output-file options');\n }\n result.outputFile = upath.normalize(value);\n } else if (option === '--python-version') {\n result.pythonVersion = value;\n } else if (option === '--index-url') {\n if (result.indexUrl) {\n throw new Error('Cannot use multiple --index-url options');\n }\n result.indexUrl = value;\n // TODO: add to secrets? next PR\n } else {\n logger.debug({ option }, `pip-compile: option not handled`);\n }\n continue;\n }\n if (arg === '--no-emit-index-url') {\n result.noEmitIndexUrl = true;\n continue;\n }\n if (arg === '--emit-index-url') {\n result.emitIndexUrl = true;\n continue;\n }\n if (arg === '--all-extras') {\n result.allExtras = true;\n continue;\n }\n\n logger.debug({ option: arg }, `pip-compile: option not handled`);\n }\n logger.trace(\n {\n ...result,\n },\n 'Parsed pip-compile command from header',\n );\n if (result.noEmitIndexUrl && result.emitIndexUrl) {\n throw new Error('Cannot use both --no-emit-index-url and --emit-index-url');\n }\n if (result.sourceFiles.length === 0) {\n throw new Error(\n 'No source files detected in command, pass at least one package file explicitly',\n );\n }\n return result;\n}\n\nconst pythonVersionRegex = regEx(\n /^(?:#.*?\\r?\\n)*# This file is autogenerated by pip-compile with Python (?<pythonVersion>\\d+(?:\\.\\d+)*)\\s/,\n 'i',\n);\n\nexport function extractPythonVersion(\n content: string,\n fileName: string,\n): string | undefined {\n const match = pythonVersionRegex.exec(content);\n if (match?.groups === undefined) {\n logger.warn(\n { fileName, content },\n 'pip-compile: failed to extract Python version from header in file',\n );\n return undefined;\n }\n logger.trace(\n `pip-compile: found Python version header in ${fileName}: \\n${match[0]}`,\n );\n const { pythonVersion } = match.groups;\n logger.debug(\n { fileName, pythonVersion },\n `pip-compile: extracted Python version from header`,\n );\n return pythonVersion;\n}\n\nfunction throwForDisallowedOption(arg: string): void {\n if (disallowedPipOptions.includes(arg)) {\n throw new Error(`Option ${arg} not allowed for this manager`);\n }\n}\nfunction throwForNoEqualSignInOptionWithArgument(arg: string): void {\n if (optionsWithArguments.includes(arg)) {\n throw new Error(\n `Option ${arg} must have equal sign '=' separating it's argument`,\n );\n }\n}\nfunction throwForUnknownOption(commandType: CommandType, arg: string): void {\n if (arg.includes('=')) {\n const [option] = arg.split('=');\n if (allowedOptions[commandType].includes(option)) {\n return;\n }\n }\n if (allowedOptions[commandType].includes(arg)) {\n return;\n }\n throw new Error(`Option ${arg} not supported (yet)`);\n}\n\nfunction getRegistryCredEnvVars(\n url: URL,\n index: number,\n): Record<string, string> {\n const hostRule = hostRules.find({ url: url.href });\n logger.debug(hostRule, `Found host rule for url ${url.href}`);\n const ret: Record<string, string> = {};\n // v8 ignore else -- needs an index url whose host rule carries no credentials\n if (!!hostRule.username || !!hostRule.password) {\n ret[`KEYRING_SERVICE_NAME_${index}`] = url.hostname;\n ret[`KEYRING_SERVICE_USERNAME_${index}`] = hostRule.username ?? '';\n ret[`KEYRING_SERVICE_PASSWORD_${index}`] = hostRule.password ?? '';\n }\n return ret;\n}\n\nfunction cleanUrl(url: string): URL | null {\n // Strip everything but protocol, host, and port\n const urlObj = parseUrl(url);\n if (!urlObj) {\n return null;\n }\n // origin of a valid URL is always parseable\n return parseUrl(urlObj.origin);\n}\n\nexport function getRegistryCredVarsFromPackageFiles(\n packageFiles: PackageFileContent[],\n): ExtraEnv<string> {\n const urls: string[] = [];\n for (const packageFile of packageFiles) {\n urls.push(\n ...coerceArray(packageFile.registryUrls),\n ...coerceArray(packageFile.additionalRegistryUrls),\n );\n }\n logger.debug(urls, 'Extracted registry URLs from package files');\n\n const uniqueHosts = new Set<URL>(\n urls.map(cleanUrl).filter(isNotNullOrUndefined),\n );\n\n let allCreds: ExtraEnv<string> = {};\n for (const [index, host] of [...uniqueHosts].entries()) {\n const hostCreds = getRegistryCredEnvVars(host, index);\n allCreds = {\n ...allCreds,\n ...hostCreds,\n };\n }\n\n return allCreds;\n}\n\nexport function matchManager(filename: string): SupportedManagers | 'unknown' {\n if (filename.endsWith('setup.py')) {\n return 'pip_setup';\n }\n if (filename.endsWith('setup.cfg')) {\n return 'setup-cfg';\n }\n if (filename.endsWith('pyproject.toml')) {\n return 'pep621';\n }\n // naive, could be improved, maybe use pip_requirements.managerFilePatterns\n if (filename.endsWith('.in') || filename.endsWith('.txt')) {\n return 'pip_requirements';\n }\n return 'unknown';\n}\n"],"mappings":"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"}
|
|
@@ -12,7 +12,9 @@ function sortPackageFiles(depsBetweenFiles, packageFiles) {
|
|
|
12
12
|
for (const file of sorted) if (packageFiles.has(file)) {
|
|
13
13
|
const packageFile = packageFiles.get(file);
|
|
14
14
|
const sortedLockFiles = [];
|
|
15
|
-
for (const lockFile of packageFile.lockFiles)
|
|
15
|
+
for (const lockFile of packageFile.lockFiles)
|
|
16
|
+
// v8 ignore else -- every lock file of a package file is in the sorted list
|
|
17
|
+
if (sorted.includes(lockFile)) sortedLockFiles.push(lockFile);
|
|
16
18
|
packageFile.lockFiles = sortedLockFiles;
|
|
17
19
|
result.push(packageFile);
|
|
18
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../../../../lib/modules/manager/pip-compile/utils.ts"],"sourcesContent":["import { Graph, topologicalSort } from 'graph-data-structure';\nimport upath from 'upath';\nimport { logger } from '../../../logger/index.ts';\nimport type { PackageFile } from '../types.ts';\nimport type { DependencyBetweenFiles, PipCompileArgs } from './types.ts';\n\nexport function sortPackageFiles(\n depsBetweenFiles: DependencyBetweenFiles[],\n packageFiles: Map<string, PackageFile>,\n): PackageFile[] {\n const result: PackageFile[] = [];\n const graph = new Graph();\n depsBetweenFiles.forEach(({ sourceFile, outputFile }) => {\n graph.addEdge(sourceFile, outputFile);\n });\n const sorted = topologicalSort(graph);\n for (const file of sorted) {\n if (packageFiles.has(file)) {\n const packageFile = packageFiles.get(file)!;\n const sortedLockFiles = [];\n // TODO(not7cd): this needs better test case\n for (const lockFile of packageFile.lockFiles!) {\n if (sorted.includes(lockFile)) {\n sortedLockFiles.push(lockFile);\n }\n }\n packageFile.lockFiles = sortedLockFiles;\n result.push(packageFile);\n }\n }\n // istanbul ignore if: should never happen\n if (result.length !== packageFiles.size) {\n throw new Error('Topological sort failed to include all package files');\n }\n return result;\n}\n\nexport function generateMermaidGraph(\n depsBetweenFiles: DependencyBetweenFiles[],\n lockFileArgs: Map<string, PipCompileArgs>,\n): string {\n const lockFiles = [];\n for (const lockFile of lockFileArgs.keys()) {\n // TODO: add extra args to the lock file ${extraArgs ? '\\n' + extraArgs : ''}\n // const extraArgs = pipCompileArgs.extra\n // ?.map((v) => '--extra=' + v)\n // .join('\\n');\n lockFiles.push(` ${lockFile}[[${lockFile}]]`);\n }\n const edges = depsBetweenFiles.map(({ sourceFile, outputFile, type }) => {\n return ` ${sourceFile} -${type === 'requirement' ? '' : '.'}-> ${outputFile}`;\n });\n return `graph TD\\n${lockFiles.join('\\n')}\\n${edges.join('\\n')}`;\n}\n\nexport function inferCommandExecDir(\n outputFilePath: string,\n outputFileArg: string | undefined,\n): string {\n if (!outputFileArg) {\n // implicit output file is in the same directory where command was executed\n return upath.normalize(upath.dirname(outputFilePath));\n }\n if (upath.normalize(outputFileArg).startsWith('..')) {\n throw new Error(\n `Cannot infer command execution directory from path ${outputFileArg}`,\n );\n }\n if (upath.basename(outputFileArg) !== upath.basename(outputFilePath)) {\n throw new Error(\n `Output file name mismatch: ${upath.basename(outputFileArg)} vs ${upath.basename(outputFilePath)}`,\n );\n }\n const outputFileDir = upath.normalize(upath.dirname(outputFileArg));\n let commandExecDir = upath.normalize(upath.dirname(outputFilePath));\n\n for (const dir of outputFileDir.split('/').reverse()) {\n if (commandExecDir.endsWith(dir)) {\n commandExecDir = upath.join(commandExecDir.slice(0, -dir.length), '.');\n // outputFileDir = upath.join(outputFileDir.slice(0, -dir.length), '.');\n } else {\n break;\n }\n }\n commandExecDir = upath.normalizeTrim(commandExecDir);\n if (commandExecDir !== '.') {\n logger.debug(\n {\n commandExecDir,\n outputFileArg,\n outputFilePath,\n },\n `pip-compile: command was not executed in repository root`,\n );\n }\n return commandExecDir;\n}\n"],"mappings":";;;;AAMA,SAAgB,iBACd,kBACA,cACe;CACf,MAAM,SAAwB,CAAC;CAC/B,MAAM,QAAQ,IAAI,MAAM;CACxB,iBAAiB,SAAS,EAAE,YAAY,iBAAiB;EACvD,MAAM,QAAQ,YAAY,UAAU;CACtC,CAAC;CACD,MAAM,SAAS,gBAAgB,KAAK;CACpC,KAAK,MAAM,QAAQ,QACjB,IAAI,aAAa,IAAI,IAAI,GAAG;EAC1B,MAAM,cAAc,aAAa,IAAI,IAAI;EACzC,MAAM,kBAAkB,CAAC;EAEzB,KAAK,MAAM,YAAY,YAAY,
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../../../lib/modules/manager/pip-compile/utils.ts"],"sourcesContent":["import { Graph, topologicalSort } from 'graph-data-structure';\nimport upath from 'upath';\nimport { logger } from '../../../logger/index.ts';\nimport type { PackageFile } from '../types.ts';\nimport type { DependencyBetweenFiles, PipCompileArgs } from './types.ts';\n\nexport function sortPackageFiles(\n depsBetweenFiles: DependencyBetweenFiles[],\n packageFiles: Map<string, PackageFile>,\n): PackageFile[] {\n const result: PackageFile[] = [];\n const graph = new Graph();\n depsBetweenFiles.forEach(({ sourceFile, outputFile }) => {\n graph.addEdge(sourceFile, outputFile);\n });\n const sorted = topologicalSort(graph);\n for (const file of sorted) {\n if (packageFiles.has(file)) {\n const packageFile = packageFiles.get(file)!;\n const sortedLockFiles = [];\n // TODO(not7cd): this needs better test case\n for (const lockFile of packageFile.lockFiles!) {\n // v8 ignore else -- every lock file of a package file is in the sorted list\n if (sorted.includes(lockFile)) {\n sortedLockFiles.push(lockFile);\n }\n }\n packageFile.lockFiles = sortedLockFiles;\n result.push(packageFile);\n }\n }\n // istanbul ignore if: should never happen\n if (result.length !== packageFiles.size) {\n throw new Error('Topological sort failed to include all package files');\n }\n return result;\n}\n\nexport function generateMermaidGraph(\n depsBetweenFiles: DependencyBetweenFiles[],\n lockFileArgs: Map<string, PipCompileArgs>,\n): string {\n const lockFiles = [];\n for (const lockFile of lockFileArgs.keys()) {\n // TODO: add extra args to the lock file ${extraArgs ? '\\n' + extraArgs : ''}\n // const extraArgs = pipCompileArgs.extra\n // ?.map((v) => '--extra=' + v)\n // .join('\\n');\n lockFiles.push(` ${lockFile}[[${lockFile}]]`);\n }\n const edges = depsBetweenFiles.map(({ sourceFile, outputFile, type }) => {\n return ` ${sourceFile} -${type === 'requirement' ? '' : '.'}-> ${outputFile}`;\n });\n return `graph TD\\n${lockFiles.join('\\n')}\\n${edges.join('\\n')}`;\n}\n\nexport function inferCommandExecDir(\n outputFilePath: string,\n outputFileArg: string | undefined,\n): string {\n if (!outputFileArg) {\n // implicit output file is in the same directory where command was executed\n return upath.normalize(upath.dirname(outputFilePath));\n }\n if (upath.normalize(outputFileArg).startsWith('..')) {\n throw new Error(\n `Cannot infer command execution directory from path ${outputFileArg}`,\n );\n }\n if (upath.basename(outputFileArg) !== upath.basename(outputFilePath)) {\n throw new Error(\n `Output file name mismatch: ${upath.basename(outputFileArg)} vs ${upath.basename(outputFilePath)}`,\n );\n }\n const outputFileDir = upath.normalize(upath.dirname(outputFileArg));\n let commandExecDir = upath.normalize(upath.dirname(outputFilePath));\n\n for (const dir of outputFileDir.split('/').reverse()) {\n if (commandExecDir.endsWith(dir)) {\n commandExecDir = upath.join(commandExecDir.slice(0, -dir.length), '.');\n // outputFileDir = upath.join(outputFileDir.slice(0, -dir.length), '.');\n } else {\n break;\n }\n }\n commandExecDir = upath.normalizeTrim(commandExecDir);\n if (commandExecDir !== '.') {\n logger.debug(\n {\n commandExecDir,\n outputFileArg,\n outputFilePath,\n },\n `pip-compile: command was not executed in repository root`,\n );\n }\n return commandExecDir;\n}\n"],"mappings":";;;;AAMA,SAAgB,iBACd,kBACA,cACe;CACf,MAAM,SAAwB,CAAC;CAC/B,MAAM,QAAQ,IAAI,MAAM;CACxB,iBAAiB,SAAS,EAAE,YAAY,iBAAiB;EACvD,MAAM,QAAQ,YAAY,UAAU;CACtC,CAAC;CACD,MAAM,SAAS,gBAAgB,KAAK;CACpC,KAAK,MAAM,QAAQ,QACjB,IAAI,aAAa,IAAI,IAAI,GAAG;EAC1B,MAAM,cAAc,aAAa,IAAI,IAAI;EACzC,MAAM,kBAAkB,CAAC;EAEzB,KAAK,MAAM,YAAY,YAAY;;EAEjC,IAAI,OAAO,SAAS,QAAQ,GAC1B,gBAAgB,KAAK,QAAQ;EAGjC,YAAY,YAAY;EACxB,OAAO,KAAK,WAAW;CACzB;;CAGF,IAAI,OAAO,WAAW,aAAa,MACjC,MAAM,IAAI,MAAM,sDAAsD;CAExE,OAAO;AACT;AAEA,SAAgB,qBACd,kBACA,cACQ;CACR,MAAM,YAAY,CAAC;CACnB,KAAK,MAAM,YAAY,aAAa,KAAK,GAKvC,UAAU,KAAK,KAAK,SAAS,IAAI,SAAS,GAAG;CAE/C,MAAM,QAAQ,iBAAiB,KAAK,EAAE,YAAY,YAAY,WAAW;EACvE,OAAO,KAAK,WAAW,IAAI,SAAS,gBAAgB,KAAK,IAAI,KAAK;CACpE,CAAC;CACD,OAAO,aAAa,UAAU,KAAK,IAAI,EAAE,IAAI,MAAM,KAAK,IAAI;AAC9D;AAEA,SAAgB,oBACd,gBACA,eACQ;CACR,IAAI,CAAC,eAEH,OAAO,MAAM,UAAU,MAAM,QAAQ,cAAc,CAAC;CAEtD,IAAI,MAAM,UAAU,aAAa,CAAC,CAAC,WAAW,IAAI,GAChD,MAAM,IAAI,MACR,sDAAsD,eACxD;CAEF,IAAI,MAAM,SAAS,aAAa,MAAM,MAAM,SAAS,cAAc,GACjE,MAAM,IAAI,MACR,8BAA8B,MAAM,SAAS,aAAa,EAAE,MAAM,MAAM,SAAS,cAAc,GACjG;CAEF,MAAM,gBAAgB,MAAM,UAAU,MAAM,QAAQ,aAAa,CAAC;CAClE,IAAI,iBAAiB,MAAM,UAAU,MAAM,QAAQ,cAAc,CAAC;CAElE,KAAK,MAAM,OAAO,cAAc,MAAM,GAAG,CAAC,CAAC,QAAQ,GACjD,IAAI,eAAe,SAAS,GAAG,GAC7B,iBAAiB,MAAM,KAAK,eAAe,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,GAAG;MAGrE;CAGJ,iBAAiB,MAAM,cAAc,cAAc;CACnD,IAAI,mBAAmB,KACrB,OAAO,MACL;EACE;EACA;EACA;CACF,GACA,0DACF;CAEF,OAAO;AACT"}
|
|
@@ -55,10 +55,13 @@ async function addCredentialsForSourceUrls(newPipfileContent, pipfileName, extra
|
|
|
55
55
|
for (const parsedSourceUrl of sourceUrls) {
|
|
56
56
|
logger.trace(`Trying to add credentials for ${parsedSourceUrl.toString()}`);
|
|
57
57
|
const matchingHostRule = getMatchingHostRule(parsedSourceUrl.toString());
|
|
58
|
+
// v8 ignore else -- needs a source url with no matching host rule
|
|
58
59
|
if (matchingHostRule) {
|
|
59
60
|
const usernameVariableName = extractEnvironmentVariableName(parsedSourceUrl.username);
|
|
61
|
+
// v8 ignore else -- needs a host rule carrying only one of the two
|
|
60
62
|
if (matchingHostRule.username && usernameVariableName) addExtraEnvVariable(extraEnv, usernameVariableName, matchingHostRule.username);
|
|
61
63
|
const passwordVariableName = extractEnvironmentVariableName(parsedSourceUrl.password);
|
|
64
|
+
// v8 ignore else -- needs a host rule carrying only one of the two
|
|
62
65
|
if (matchingHostRule.password && passwordVariableName) addExtraEnvVariable(extraEnv, passwordVariableName, matchingHostRule.password);
|
|
63
66
|
}
|
|
64
67
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifacts.js","names":["pipenvDetect"],"sources":["../../../../lib/modules/manager/pipenv/artifacts.ts"],"sourcesContent":["import { pipenv as pipenvDetect } from '@renovatebot/detect-tools';\nimport {\n isNonEmptyStringAndNotWhitespace,\n isUrlInstance,\n} from '@sindresorhus/is';\nimport { TEMPORARY_ERROR } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { HostRule } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { exec } from '../../../util/exec/index.ts';\nimport type { ExecOptions, ExtraEnv, Opt } from '../../../util/exec/types.ts';\nimport {\n deleteLocalFile,\n ensureCacheDir,\n getParentDir,\n localPathExists,\n readLocalFile,\n writeLocalFile,\n} from '../../../util/fs/index.ts';\nimport { ensureLocalPath } from '../../../util/fs/util.ts';\nimport { getRepoStatus } from '../../../util/git/index.ts';\nimport { find } from '../../../util/host-rules.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport { PypiDatasource } from '../../datasource/pypi/index.ts';\nimport type { UpdateArtifact, UpdateArtifactsResult } from '../types.ts';\nimport { resolveToolConstraint } from '../util.ts';\nimport { extractPackageFile } from './extract.ts';\n\nexport function getMatchingHostRule(url: string): HostRule | null {\n const parsedUrl = parseUrl(url);\n if (parsedUrl) {\n parsedUrl.username = '';\n parsedUrl.password = '';\n const urlWithoutCredentials = parsedUrl.toString();\n\n return find({ hostType: PypiDatasource.id, url: urlWithoutCredentials });\n }\n return null;\n}\n\nasync function findPipfileSourceUrlsWithCredentials(\n pipfileContent: string,\n pipfileName: string,\n): Promise<URL[]> {\n const pipfile = await extractPackageFile(pipfileContent, pipfileName);\n\n return coerceArray(\n pipfile?.registryUrls\n ?.map(parseUrl)\n .filter(isUrlInstance)\n .filter((url) => isNonEmptyStringAndNotWhitespace(url.username)),\n );\n}\n\n/**\n * This will extract the actual variable name from an environment-placeholder:\n * ${USERNAME:-defaultvalue} will yield 'USERNAME'\n */\nexport function extractEnvironmentVariableName(\n credential: string,\n): string | null {\n const match = regEx('([a-z0-9_]+)', 'i').exec(decodeURI(credential));\n return match?.length ? match[0] : null;\n}\n\nexport function addExtraEnvVariable(\n extraEnv: ExtraEnv,\n environmentVariableName: string,\n environmentValue: string,\n): void {\n logger.trace(\n `Adding ${environmentVariableName} environment variable for pipenv`,\n );\n if (\n extraEnv[environmentVariableName] &&\n extraEnv[environmentVariableName] !== environmentValue\n ) {\n logger.warn(\n { envVar: environmentVariableName },\n 'Possible misconfiguration, environment variable already set to a different value',\n );\n }\n extraEnv[environmentVariableName] = environmentValue;\n}\n\n/**\n * Pipenv allows configuring source-urls for remote repositories with placeholders for credentials, i.e. http://$USER:$PASS@myprivate.repo\n * if a matching host rule exists for that repository, we need to set the corresponding variables.\n * Simply substituting them in the URL is not an option as it would impact the hash for the resulting Pipfile.lock\n *\n */\nasync function addCredentialsForSourceUrls(\n newPipfileContent: string,\n pipfileName: string,\n extraEnv: ExtraEnv,\n): Promise<void> {\n const sourceUrls = await findPipfileSourceUrlsWithCredentials(\n newPipfileContent,\n pipfileName,\n );\n for (const parsedSourceUrl of sourceUrls) {\n logger.trace(`Trying to add credentials for ${parsedSourceUrl.toString()}`);\n const matchingHostRule = getMatchingHostRule(parsedSourceUrl.toString());\n if (matchingHostRule) {\n const usernameVariableName = extractEnvironmentVariableName(\n parsedSourceUrl.username,\n );\n if (matchingHostRule.username && usernameVariableName) {\n addExtraEnvVariable(\n extraEnv,\n usernameVariableName,\n matchingHostRule.username,\n );\n }\n const passwordVariableName = extractEnvironmentVariableName(\n parsedSourceUrl.password,\n );\n if (matchingHostRule.password && passwordVariableName) {\n addExtraEnvVariable(\n extraEnv,\n passwordVariableName,\n matchingHostRule.password,\n );\n }\n }\n }\n}\n\nexport async function updateArtifacts({\n packageFileName: pipfileName,\n newPackageFileContent: newPipfileContent,\n config,\n}: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {\n logger.debug(`pipenv.updateArtifacts(${pipfileName})`);\n\n const lockFileName = `${pipfileName}.lock`;\n if (!(await localPathExists(lockFileName))) {\n logger.debug('No Pipfile.lock found');\n return null;\n }\n try {\n await writeLocalFile(pipfileName, newPipfileContent);\n if (config.isLockFileMaintenance) {\n await deleteLocalFile(lockFileName);\n }\n const cmd = 'pipenv lock';\n const pipfileDir = getParentDir(ensureLocalPath(pipfileName));\n const tagConstraint = await resolveToolConstraint(config, 'python', () =>\n pipenvDetect.getPythonConstraint(pipfileDir),\n );\n const pipenvConstraint = await resolveToolConstraint(config, 'pipenv', () =>\n pipenvDetect.getPipenvConstraint(pipfileDir),\n );\n const extraEnv: Opt<ExtraEnv> = {\n PIPENV_CACHE_DIR: await ensureCacheDir('pipenv'),\n PIP_CACHE_DIR: await ensureCacheDir('pip'),\n WORKON_HOME: await ensureCacheDir('virtualenvs'),\n };\n const execOptions: ExecOptions = {\n cwdFile: pipfileName,\n docker: {},\n toolConstraints: [\n {\n toolName: 'python',\n constraint: tagConstraint,\n },\n {\n toolName: 'pipenv',\n constraint: pipenvConstraint,\n },\n ],\n };\n await addCredentialsForSourceUrls(newPipfileContent, pipfileName, extraEnv);\n execOptions.extraEnv = extraEnv;\n\n logger.trace({ cmd }, 'pipenv lock command');\n await exec(cmd, execOptions);\n const status = await getRepoStatus();\n if (!status?.modified.includes(lockFileName)) {\n return null;\n }\n logger.debug('Returning updated Pipfile.lock');\n return [\n {\n file: {\n type: 'addition',\n path: lockFileName,\n contents: await readLocalFile(lockFileName, 'utf8'),\n },\n },\n ];\n } catch (err) {\n // istanbul ignore if\n if (err.message === TEMPORARY_ERROR) {\n throw err;\n }\n logger.debug({ err }, 'Failed to update Pipfile.lock');\n return [\n {\n artifactError: {\n fileName: lockFileName,\n stderr: err.message,\n },\n },\n ];\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA6BA,SAAgB,oBAAoB,KAA8B;CAChE,MAAM,YAAY,SAAS,GAAG;CAC9B,IAAI,WAAW;EACb,UAAU,WAAW;EACrB,UAAU,WAAW;EACrB,MAAM,wBAAwB,UAAU,SAAS;EAEjD,OAAO,KAAK;GAAE,UAAU,eAAe;GAAI,KAAK;EAAsB,CAAC;CACzE;CACA,OAAO;AACT;AAEA,eAAe,qCACb,gBACA,aACgB;CAChB,MAAM,UAAU,MAAM,mBAAmB,gBAAgB,WAAW;CAEpE,OAAO,YACL,SAAS,cACL,IAAI,QAAQ,CAAC,CACd,OAAO,aAAa,CAAC,CACrB,QAAQ,QAAQ,iCAAiC,IAAI,QAAQ,CAAC,CACnE;AACF;;;;;AAMA,SAAgB,+BACd,YACe;CACf,MAAM,QAAQ,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,UAAU,UAAU,CAAC;CACnE,OAAO,OAAO,SAAS,MAAM,KAAK;AACpC;AAEA,SAAgB,oBACd,UACA,yBACA,kBACM;CACN,OAAO,MACL,UAAU,wBAAwB,iCACpC;CACA,IACE,SAAS,4BACT,SAAS,6BAA6B,kBAEtC,OAAO,KACL,EAAE,QAAQ,wBAAwB,GAClC,kFACF;CAEF,SAAS,2BAA2B;AACtC;;;;;;;AAQA,eAAe,4BACb,mBACA,aACA,UACe;CACf,MAAM,aAAa,MAAM,qCACvB,mBACA,WACF;CACA,KAAK,MAAM,mBAAmB,YAAY;EACxC,OAAO,MAAM,iCAAiC,gBAAgB,SAAS,GAAG;EAC1E,MAAM,mBAAmB,oBAAoB,gBAAgB,SAAS,CAAC
|
|
1
|
+
{"version":3,"file":"artifacts.js","names":["pipenvDetect"],"sources":["../../../../lib/modules/manager/pipenv/artifacts.ts"],"sourcesContent":["import { pipenv as pipenvDetect } from '@renovatebot/detect-tools';\nimport {\n isNonEmptyStringAndNotWhitespace,\n isUrlInstance,\n} from '@sindresorhus/is';\nimport { TEMPORARY_ERROR } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { HostRule } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { exec } from '../../../util/exec/index.ts';\nimport type { ExecOptions, ExtraEnv, Opt } from '../../../util/exec/types.ts';\nimport {\n deleteLocalFile,\n ensureCacheDir,\n getParentDir,\n localPathExists,\n readLocalFile,\n writeLocalFile,\n} from '../../../util/fs/index.ts';\nimport { ensureLocalPath } from '../../../util/fs/util.ts';\nimport { getRepoStatus } from '../../../util/git/index.ts';\nimport { find } from '../../../util/host-rules.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport { PypiDatasource } from '../../datasource/pypi/index.ts';\nimport type { UpdateArtifact, UpdateArtifactsResult } from '../types.ts';\nimport { resolveToolConstraint } from '../util.ts';\nimport { extractPackageFile } from './extract.ts';\n\nexport function getMatchingHostRule(url: string): HostRule | null {\n const parsedUrl = parseUrl(url);\n if (parsedUrl) {\n parsedUrl.username = '';\n parsedUrl.password = '';\n const urlWithoutCredentials = parsedUrl.toString();\n\n return find({ hostType: PypiDatasource.id, url: urlWithoutCredentials });\n }\n return null;\n}\n\nasync function findPipfileSourceUrlsWithCredentials(\n pipfileContent: string,\n pipfileName: string,\n): Promise<URL[]> {\n const pipfile = await extractPackageFile(pipfileContent, pipfileName);\n\n return coerceArray(\n pipfile?.registryUrls\n ?.map(parseUrl)\n .filter(isUrlInstance)\n .filter((url) => isNonEmptyStringAndNotWhitespace(url.username)),\n );\n}\n\n/**\n * This will extract the actual variable name from an environment-placeholder:\n * ${USERNAME:-defaultvalue} will yield 'USERNAME'\n */\nexport function extractEnvironmentVariableName(\n credential: string,\n): string | null {\n const match = regEx('([a-z0-9_]+)', 'i').exec(decodeURI(credential));\n return match?.length ? match[0] : null;\n}\n\nexport function addExtraEnvVariable(\n extraEnv: ExtraEnv,\n environmentVariableName: string,\n environmentValue: string,\n): void {\n logger.trace(\n `Adding ${environmentVariableName} environment variable for pipenv`,\n );\n if (\n extraEnv[environmentVariableName] &&\n extraEnv[environmentVariableName] !== environmentValue\n ) {\n logger.warn(\n { envVar: environmentVariableName },\n 'Possible misconfiguration, environment variable already set to a different value',\n );\n }\n extraEnv[environmentVariableName] = environmentValue;\n}\n\n/**\n * Pipenv allows configuring source-urls for remote repositories with placeholders for credentials, i.e. http://$USER:$PASS@myprivate.repo\n * if a matching host rule exists for that repository, we need to set the corresponding variables.\n * Simply substituting them in the URL is not an option as it would impact the hash for the resulting Pipfile.lock\n *\n */\nasync function addCredentialsForSourceUrls(\n newPipfileContent: string,\n pipfileName: string,\n extraEnv: ExtraEnv,\n): Promise<void> {\n const sourceUrls = await findPipfileSourceUrlsWithCredentials(\n newPipfileContent,\n pipfileName,\n );\n for (const parsedSourceUrl of sourceUrls) {\n logger.trace(`Trying to add credentials for ${parsedSourceUrl.toString()}`);\n const matchingHostRule = getMatchingHostRule(parsedSourceUrl.toString());\n // v8 ignore else -- needs a source url with no matching host rule\n if (matchingHostRule) {\n const usernameVariableName = extractEnvironmentVariableName(\n parsedSourceUrl.username,\n );\n // v8 ignore else -- needs a host rule carrying only one of the two\n if (matchingHostRule.username && usernameVariableName) {\n addExtraEnvVariable(\n extraEnv,\n usernameVariableName,\n matchingHostRule.username,\n );\n }\n const passwordVariableName = extractEnvironmentVariableName(\n parsedSourceUrl.password,\n );\n // v8 ignore else -- needs a host rule carrying only one of the two\n if (matchingHostRule.password && passwordVariableName) {\n addExtraEnvVariable(\n extraEnv,\n passwordVariableName,\n matchingHostRule.password,\n );\n }\n }\n }\n}\n\nexport async function updateArtifacts({\n packageFileName: pipfileName,\n newPackageFileContent: newPipfileContent,\n config,\n}: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {\n logger.debug(`pipenv.updateArtifacts(${pipfileName})`);\n\n const lockFileName = `${pipfileName}.lock`;\n if (!(await localPathExists(lockFileName))) {\n logger.debug('No Pipfile.lock found');\n return null;\n }\n try {\n await writeLocalFile(pipfileName, newPipfileContent);\n if (config.isLockFileMaintenance) {\n await deleteLocalFile(lockFileName);\n }\n const cmd = 'pipenv lock';\n const pipfileDir = getParentDir(ensureLocalPath(pipfileName));\n const tagConstraint = await resolveToolConstraint(config, 'python', () =>\n pipenvDetect.getPythonConstraint(pipfileDir),\n );\n const pipenvConstraint = await resolveToolConstraint(config, 'pipenv', () =>\n pipenvDetect.getPipenvConstraint(pipfileDir),\n );\n const extraEnv: Opt<ExtraEnv> = {\n PIPENV_CACHE_DIR: await ensureCacheDir('pipenv'),\n PIP_CACHE_DIR: await ensureCacheDir('pip'),\n WORKON_HOME: await ensureCacheDir('virtualenvs'),\n };\n const execOptions: ExecOptions = {\n cwdFile: pipfileName,\n docker: {},\n toolConstraints: [\n {\n toolName: 'python',\n constraint: tagConstraint,\n },\n {\n toolName: 'pipenv',\n constraint: pipenvConstraint,\n },\n ],\n };\n await addCredentialsForSourceUrls(newPipfileContent, pipfileName, extraEnv);\n execOptions.extraEnv = extraEnv;\n\n logger.trace({ cmd }, 'pipenv lock command');\n await exec(cmd, execOptions);\n const status = await getRepoStatus();\n if (!status?.modified.includes(lockFileName)) {\n return null;\n }\n logger.debug('Returning updated Pipfile.lock');\n return [\n {\n file: {\n type: 'addition',\n path: lockFileName,\n contents: await readLocalFile(lockFileName, 'utf8'),\n },\n },\n ];\n } catch (err) {\n // istanbul ignore if\n if (err.message === TEMPORARY_ERROR) {\n throw err;\n }\n logger.debug({ err }, 'Failed to update Pipfile.lock');\n return [\n {\n artifactError: {\n fileName: lockFileName,\n stderr: err.message,\n },\n },\n ];\n }\n}\n"],"mappings":"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"}
|
|
@@ -57,6 +57,7 @@ function extractFromSection(sectionName, pipfileSection, sources) {
|
|
|
57
57
|
if (nestedVersion) dep.managerData.nestedVersion = nestedVersion;
|
|
58
58
|
if (sources && isObject(requirements) && requirements.index) {
|
|
59
59
|
const source = sources.find((item) => item.name === requirements.index);
|
|
60
|
+
// v8 ignore else -- needs a requirement naming an index that is not declared
|
|
60
61
|
if (source) dep.registryUrls = [source.url];
|
|
61
62
|
}
|
|
62
63
|
return dep;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.js","names":["rangePattern","parseToml","pipenvDetect"],"sources":["../../../../lib/modules/manager/pipenv/extract.ts"],"sourcesContent":["import { pipenv as pipenvDetect } from '@renovatebot/detect-tools';\nimport { RANGE_PATTERN } from '@renovatebot/pep440';\nimport { isArray, isObject, isString, isTruthy } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport type { SkipReason } from '../../../types/index.ts';\nimport type { ConstraintName } from '../../../util/exec/types.ts';\nimport { getParentDir, localPathExists } from '../../../util/fs/index.ts';\nimport { ensureLocalPath } from '../../../util/fs/util.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parse as parseToml } from '../../../util/toml.ts';\nimport { normalizePythonDepName } from '../../datasource/pypi/common.ts';\nimport { PypiDatasource } from '../../datasource/pypi/index.ts';\nimport type { PackageDependency, PackageFileContent } from '../types.ts';\nimport type { PipFile, PipRequirement, PipSource } from './types.ts';\n\n// based on https://www.python.org/dev/peps/pep-0508/#names\nexport const packagePattern = '[A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9]';\nexport const extrasPattern = '(?:\\\\s*\\\\[[^\\\\]]+\\\\])*';\nconst packageRegex = regEx(`^(${packagePattern})(${extrasPattern})$`, 'i');\n\nconst rangePattern: string = RANGE_PATTERN;\n\nconst specifierPartPattern = `\\\\s*${rangePattern.replace(\n regEx(/\\?<\\w+>/g),\n '?:',\n)}\\\\s*`;\nconst specifierPattern = `${specifierPartPattern}(?:,${specifierPartPattern})*`;\nconst specifierRegex = regEx(`^${specifierPattern}$`);\nfunction extractFromSection(\n sectionName: string,\n pipfileSection: Record<string, PipRequirement>,\n sources?: PipSource[],\n): PackageDependency[] {\n const deps = Object.entries(pipfileSection)\n .map((x) => {\n const [packageNameString, requirements] = x;\n let depName = packageNameString;\n\n let currentValue: string | undefined;\n let nestedVersion = false;\n let skipReason: SkipReason | undefined;\n if (isObject(requirements)) {\n if (requirements.git) {\n skipReason = 'git-dependency';\n } else if (requirements.file) {\n skipReason = 'file-dependency';\n } else if (requirements.path) {\n skipReason = 'local-dependency';\n } else if (requirements.version) {\n currentValue = requirements.version;\n nestedVersion = true;\n } else {\n skipReason = 'unspecified-version';\n }\n } else {\n currentValue = requirements;\n }\n if (currentValue === '*') {\n skipReason = 'unspecified-version';\n }\n if (!skipReason) {\n const packageMatches = packageRegex.exec(packageNameString);\n if (packageMatches) {\n depName = packageMatches[1];\n } else {\n logger.debug(\n `Skipping dependency with malformed package name \"${packageNameString}\".`,\n );\n skipReason = 'invalid-name';\n }\n // validated above\n const specifierMatches = specifierRegex.exec(currentValue!);\n if (!specifierMatches) {\n logger.debug(\n `Skipping dependency with malformed version specifier \"${currentValue!}\".`,\n );\n skipReason = 'invalid-version';\n }\n }\n const dep: PackageDependency = {\n depType: sectionName,\n depName,\n packageName: normalizePythonDepName(depName),\n managerData: {},\n };\n if (currentValue) {\n dep.currentValue = currentValue;\n }\n if (skipReason) {\n dep.skipReason = skipReason;\n } else {\n dep.datasource = PypiDatasource.id;\n }\n if (!skipReason && currentValue?.startsWith('==')) {\n dep.currentVersion = currentValue.replace(regEx(/^==\\s*/), '');\n }\n if (nestedVersion) {\n // TODO #22198\n dep.managerData!.nestedVersion = nestedVersion;\n }\n if (sources && isObject(requirements) && requirements.index) {\n const source = sources.find((item) => item.name === requirements.index);\n if (source) {\n dep.registryUrls = [source.url];\n }\n }\n return dep;\n })\n .filter(isTruthy);\n return deps;\n}\n\nfunction isPipRequirements(\n section?:\n Record<string, PipRequirement> | Record<string, string> | PipSource[],\n): section is Record<string, PipRequirement> {\n return (\n !isArray(section) &&\n isObject(section) &&\n !Object.values(section).some((dep) => !isObject(dep) && !isString(dep))\n );\n}\n\nexport async function extractPackageFile(\n content: string,\n packageFile: string,\n): Promise<PackageFileContent | null> {\n logger.trace(`pipenv.extractPackageFile(${packageFile})`);\n\n let pipfile: PipFile;\n try {\n // TODO: fix type (#9610)\n pipfile = parseToml(content) as any;\n } catch (err) {\n logger.debug({ err, packageFile }, 'Error parsing Pipfile');\n return null;\n }\n const res: PackageFileContent = { deps: [] };\n\n const sources = pipfile?.source;\n\n if (sources) {\n res.registryUrls = sources.map((source) => source.url);\n }\n\n res.deps = Object.entries(pipfile)\n .map(([category, section]) => {\n if (\n category === 'source' ||\n category === 'requires' ||\n !isPipRequirements(section)\n ) {\n return [];\n }\n\n return extractFromSection(category, section, sources);\n })\n .flat();\n\n if (!res.deps.length) {\n return null;\n }\n\n const extractedConstraints: Partial<Record<ConstraintName, string>> = {};\n\n const pipfileDir = getParentDir(ensureLocalPath(packageFile));\n\n const pythonConstraint = await pipenvDetect.getPythonConstraint(pipfileDir);\n if (pythonConstraint) {\n extractedConstraints.python = pythonConstraint;\n }\n\n const pipenvConstraint = await pipenvDetect.getPipenvConstraint(pipfileDir);\n if (pipenvConstraint) {\n extractedConstraints.pipenv = pipenvConstraint;\n }\n\n const lockFileName = `${packageFile}.lock`;\n if (await localPathExists(lockFileName)) {\n res.lockFiles = [lockFileName];\n }\n\n res.extractedConstraints = extractedConstraints;\n return res;\n}\n"],"mappings":";;;;;;;;;;;AAgBA,MAAa,iBAAiB;AAC9B,MAAa,gBAAgB;AAC7B,MAAM,eAAe,MAAM,KAAK,eAAe,IAAI,cAAc,KAAK,GAAG;AAIzE,MAAM,uBAAuB,OAAOA,cAAa,QAC/C,MAAM,UAAU,GAChB,IACF,EAAE;AACF,MAAM,mBAAmB,GAAG,qBAAqB,MAAM,qBAAqB;AAC5E,MAAM,iBAAiB,MAAM,IAAI,iBAAiB,EAAE;AACpD,SAAS,mBACP,aACA,gBACA,SACqB;
|
|
1
|
+
{"version":3,"file":"extract.js","names":["rangePattern","parseToml","pipenvDetect"],"sources":["../../../../lib/modules/manager/pipenv/extract.ts"],"sourcesContent":["import { pipenv as pipenvDetect } from '@renovatebot/detect-tools';\nimport { RANGE_PATTERN } from '@renovatebot/pep440';\nimport { isArray, isObject, isString, isTruthy } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport type { SkipReason } from '../../../types/index.ts';\nimport type { ConstraintName } from '../../../util/exec/types.ts';\nimport { getParentDir, localPathExists } from '../../../util/fs/index.ts';\nimport { ensureLocalPath } from '../../../util/fs/util.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parse as parseToml } from '../../../util/toml.ts';\nimport { normalizePythonDepName } from '../../datasource/pypi/common.ts';\nimport { PypiDatasource } from '../../datasource/pypi/index.ts';\nimport type { PackageDependency, PackageFileContent } from '../types.ts';\nimport type { PipFile, PipRequirement, PipSource } from './types.ts';\n\n// based on https://www.python.org/dev/peps/pep-0508/#names\nexport const packagePattern = '[A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9]';\nexport const extrasPattern = '(?:\\\\s*\\\\[[^\\\\]]+\\\\])*';\nconst packageRegex = regEx(`^(${packagePattern})(${extrasPattern})$`, 'i');\n\nconst rangePattern: string = RANGE_PATTERN;\n\nconst specifierPartPattern = `\\\\s*${rangePattern.replace(\n regEx(/\\?<\\w+>/g),\n '?:',\n)}\\\\s*`;\nconst specifierPattern = `${specifierPartPattern}(?:,${specifierPartPattern})*`;\nconst specifierRegex = regEx(`^${specifierPattern}$`);\nfunction extractFromSection(\n sectionName: string,\n pipfileSection: Record<string, PipRequirement>,\n sources?: PipSource[],\n): PackageDependency[] {\n const deps = Object.entries(pipfileSection)\n .map((x) => {\n const [packageNameString, requirements] = x;\n let depName = packageNameString;\n\n let currentValue: string | undefined;\n let nestedVersion = false;\n let skipReason: SkipReason | undefined;\n if (isObject(requirements)) {\n if (requirements.git) {\n skipReason = 'git-dependency';\n } else if (requirements.file) {\n skipReason = 'file-dependency';\n } else if (requirements.path) {\n skipReason = 'local-dependency';\n } else if (requirements.version) {\n currentValue = requirements.version;\n nestedVersion = true;\n } else {\n skipReason = 'unspecified-version';\n }\n } else {\n currentValue = requirements;\n }\n if (currentValue === '*') {\n skipReason = 'unspecified-version';\n }\n if (!skipReason) {\n const packageMatches = packageRegex.exec(packageNameString);\n if (packageMatches) {\n depName = packageMatches[1];\n } else {\n logger.debug(\n `Skipping dependency with malformed package name \"${packageNameString}\".`,\n );\n skipReason = 'invalid-name';\n }\n // validated above\n const specifierMatches = specifierRegex.exec(currentValue!);\n if (!specifierMatches) {\n logger.debug(\n `Skipping dependency with malformed version specifier \"${currentValue!}\".`,\n );\n skipReason = 'invalid-version';\n }\n }\n const dep: PackageDependency = {\n depType: sectionName,\n depName,\n packageName: normalizePythonDepName(depName),\n managerData: {},\n };\n if (currentValue) {\n dep.currentValue = currentValue;\n }\n if (skipReason) {\n dep.skipReason = skipReason;\n } else {\n dep.datasource = PypiDatasource.id;\n }\n if (!skipReason && currentValue?.startsWith('==')) {\n dep.currentVersion = currentValue.replace(regEx(/^==\\s*/), '');\n }\n if (nestedVersion) {\n // TODO #22198\n dep.managerData!.nestedVersion = nestedVersion;\n }\n if (sources && isObject(requirements) && requirements.index) {\n const source = sources.find((item) => item.name === requirements.index);\n // v8 ignore else -- needs a requirement naming an index that is not declared\n if (source) {\n dep.registryUrls = [source.url];\n }\n }\n return dep;\n })\n .filter(isTruthy);\n return deps;\n}\n\nfunction isPipRequirements(\n section?:\n Record<string, PipRequirement> | Record<string, string> | PipSource[],\n): section is Record<string, PipRequirement> {\n return (\n !isArray(section) &&\n isObject(section) &&\n !Object.values(section).some((dep) => !isObject(dep) && !isString(dep))\n );\n}\n\nexport async function extractPackageFile(\n content: string,\n packageFile: string,\n): Promise<PackageFileContent | null> {\n logger.trace(`pipenv.extractPackageFile(${packageFile})`);\n\n let pipfile: PipFile;\n try {\n // TODO: fix type (#9610)\n pipfile = parseToml(content) as any;\n } catch (err) {\n logger.debug({ err, packageFile }, 'Error parsing Pipfile');\n return null;\n }\n const res: PackageFileContent = { deps: [] };\n\n const sources = pipfile?.source;\n\n if (sources) {\n res.registryUrls = sources.map((source) => source.url);\n }\n\n res.deps = Object.entries(pipfile)\n .map(([category, section]) => {\n if (\n category === 'source' ||\n category === 'requires' ||\n !isPipRequirements(section)\n ) {\n return [];\n }\n\n return extractFromSection(category, section, sources);\n })\n .flat();\n\n if (!res.deps.length) {\n return null;\n }\n\n const extractedConstraints: Partial<Record<ConstraintName, string>> = {};\n\n const pipfileDir = getParentDir(ensureLocalPath(packageFile));\n\n const pythonConstraint = await pipenvDetect.getPythonConstraint(pipfileDir);\n if (pythonConstraint) {\n extractedConstraints.python = pythonConstraint;\n }\n\n const pipenvConstraint = await pipenvDetect.getPipenvConstraint(pipfileDir);\n if (pipenvConstraint) {\n extractedConstraints.pipenv = pipenvConstraint;\n }\n\n const lockFileName = `${packageFile}.lock`;\n if (await localPathExists(lockFileName)) {\n res.lockFiles = [lockFileName];\n }\n\n res.extractedConstraints = extractedConstraints;\n return res;\n}\n"],"mappings":"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"}
|
|
@@ -40,6 +40,7 @@ function getUserPixiConfig(content, packageFile) {
|
|
|
40
40
|
}, `error parsing ${packageFile}`);
|
|
41
41
|
return null;
|
|
42
42
|
}
|
|
43
|
+
/* v8 ignore next -- a successful parse always yields a value */
|
|
43
44
|
return val ?? null;
|
|
44
45
|
}
|
|
45
46
|
async function extractPackageFile(content, packageFile) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.js","names":["defaultCondaRegistryApi"],"sources":["../../../../lib/modules/manager/pixi/extract.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport { z } from 'zod/v4';\n\nimport { logger } from '../../../logger/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { getSiblingFileName, localPathExists } from '../../../util/fs/index.ts';\nimport { coerceNumber } from '../../../util/number.ts';\nimport { Result } from '../../../util/result.ts';\nimport {\n ensureTrailingSlash,\n isHttpUrl,\n joinUrlParts,\n} from '../../../util/url.ts';\nimport { defaultRegistryUrl as defaultCondaRegistryApi } from '../../datasource/conda/common.ts';\nimport type { RegistryStrategy } from '../../datasource/index.ts';\nimport type { PackageFileContent } from '../types.ts';\nimport {\n type Channels,\n type PixiConfig,\n PixiFile,\n type PixiPackageDependency,\n PixiPyProject,\n} from './schema.ts';\n\nexport function getUserPixiConfig(\n content: string,\n packageFile: string,\n): null | PixiConfig {\n if (\n packageFile === 'pyproject.toml' ||\n packageFile.endsWith('/pyproject.toml')\n ) {\n const { val, err } = Result.parse(content, PixiPyProject).unwrap();\n if (err) {\n logger.debug({ packageFile, err }, `error parsing ${packageFile}`);\n return null;\n }\n\n return val.tool?.pixi ?? null;\n }\n\n if (packageFile === 'pixi.toml' || packageFile.endsWith('/pixi.toml')) {\n const { val, err } = Result.parse(content, PixiFile).unwrap();\n if (err) {\n logger.debug({ packageFile, err }, `error parsing ${packageFile}`);\n return null;\n }\n\n return val;\n }\n\n const { val, err } = Result.parse(\n content,\n z.union([PixiFile, PixiPyProject.transform((p) => p.tool?.pixi)]),\n ).unwrap();\n\n if (err) {\n logger.debug({ packageFile, err }, `error parsing ${packageFile}`);\n return null;\n }\n return val ?? null;\n}\n\nexport async function extractPackageFile(\n content: string,\n packageFile: string,\n): Promise<PackageFileContent | null> {\n logger.trace(`pixi.extractPackageFile(${packageFile})`);\n\n const val = getUserPixiConfig(content, packageFile);\n if (!val) {\n return null;\n }\n\n const lockfileName = getSiblingFileName(packageFile, 'pixi.lock');\n const lockFiles: string[] = [];\n if (await localPathExists(lockfileName)) {\n lockFiles.push(lockfileName);\n }\n\n const project = val.project;\n\n const channelPriority = project['channel-priority'];\n\n let registryStrategy: RegistryStrategy | undefined;\n\n if (channelPriority === 'disabled') {\n registryStrategy = 'merge';\n }\n\n // resolve channels and build registry urls for each channel with order\n const conda: PixiPackageDependency[] = [];\n\n for (const item of val.conda) {\n conda.push(\n addRegistryUrls({\n ...item,\n channels: project.channels,\n registryStrategy,\n }),\n );\n }\n\n for (const item of val.feature.conda) {\n conda.push(\n addRegistryUrls({\n ...item,\n registryStrategy,\n channels: [...coerceArray(item.channels), ...project.channels],\n }),\n );\n }\n\n return {\n lockFiles,\n deps: [conda, val.pypi, val.feature.pypi].flat(),\n };\n}\n\nfunction addRegistryUrls(item: PixiPackageDependency): PixiPackageDependency {\n const channels = orderChannels(item.channels);\n\n if (item.channel) {\n return {\n ...item,\n channels,\n registryUrls: [channelToRegistryUrl(item.channel)],\n };\n }\n\n if (channels.length === 0) {\n return {\n ...item,\n channels,\n skipStage: 'extract',\n skipReason: 'unknown-registry',\n };\n }\n\n const registryUrls: string[] = [];\n for (const channel of channels) {\n registryUrls.push(channelToRegistryUrl(channel));\n }\n\n return {\n ...item,\n channels,\n registryUrls,\n };\n}\n\nfunction channelToRegistryUrl(channel: string): string {\n if (isHttpUrl(channel)) {\n return ensureTrailingSlash(channel);\n }\n\n return ensureTrailingSlash(joinUrlParts(defaultCondaRegistryApi, channel));\n}\n\nfunction orderChannels(channels: Channels = []): string[] {\n return channels\n .map((channel, index) => {\n if (isString(channel)) {\n return { channel, priority: 0, index };\n }\n\n return { ...channel, priority: coerceNumber(channel.priority), index };\n })\n .toSorted((a, b) => {\n // first based on priority then based on index\n if (a.priority !== b.priority) {\n return b.priority - a.priority;\n }\n\n return a.index - b.index;\n })\n .map((c) => c.channel);\n}\n"],"mappings":";;;;;;;;;;;AAwBA,SAAgB,kBACd,SACA,aACmB;CACnB,IACE,gBAAgB,oBAChB,YAAY,SAAS,iBAAiB,GACtC;EACA,MAAM,EAAE,KAAK,QAAQ,OAAO,MAAM,SAAS,aAAa,CAAC,CAAC,OAAO;EACjE,IAAI,KAAK;GACP,OAAO,MAAM;IAAE;IAAa;GAAI,GAAG,iBAAiB,aAAa;GACjE,OAAO;EACT;EAEA,OAAO,IAAI,MAAM,QAAQ;CAC3B;CAEA,IAAI,gBAAgB,eAAe,YAAY,SAAS,YAAY,GAAG;EACrE,MAAM,EAAE,KAAK,QAAQ,OAAO,MAAM,SAAS,QAAQ,CAAC,CAAC,OAAO;EAC5D,IAAI,KAAK;GACP,OAAO,MAAM;IAAE;IAAa;GAAI,GAAG,iBAAiB,aAAa;GACjE,OAAO;EACT;EAEA,OAAO;CACT;CAEA,MAAM,EAAE,KAAK,QAAQ,OAAO,MAC1B,SACA,EAAE,MAAM,CAAC,UAAU,cAAc,WAAW,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC,CAClE,CAAC,CAAC,OAAO;CAET,IAAI,KAAK;EACP,OAAO,MAAM;GAAE;GAAa;EAAI,GAAG,iBAAiB,aAAa;EACjE,OAAO;CACT
|
|
1
|
+
{"version":3,"file":"extract.js","names":["defaultCondaRegistryApi"],"sources":["../../../../lib/modules/manager/pixi/extract.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport { z } from 'zod/v4';\n\nimport { logger } from '../../../logger/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { getSiblingFileName, localPathExists } from '../../../util/fs/index.ts';\nimport { coerceNumber } from '../../../util/number.ts';\nimport { Result } from '../../../util/result.ts';\nimport {\n ensureTrailingSlash,\n isHttpUrl,\n joinUrlParts,\n} from '../../../util/url.ts';\nimport { defaultRegistryUrl as defaultCondaRegistryApi } from '../../datasource/conda/common.ts';\nimport type { RegistryStrategy } from '../../datasource/index.ts';\nimport type { PackageFileContent } from '../types.ts';\nimport {\n type Channels,\n type PixiConfig,\n PixiFile,\n type PixiPackageDependency,\n PixiPyProject,\n} from './schema.ts';\n\nexport function getUserPixiConfig(\n content: string,\n packageFile: string,\n): null | PixiConfig {\n if (\n packageFile === 'pyproject.toml' ||\n packageFile.endsWith('/pyproject.toml')\n ) {\n const { val, err } = Result.parse(content, PixiPyProject).unwrap();\n if (err) {\n logger.debug({ packageFile, err }, `error parsing ${packageFile}`);\n return null;\n }\n\n return val.tool?.pixi ?? null;\n }\n\n if (packageFile === 'pixi.toml' || packageFile.endsWith('/pixi.toml')) {\n const { val, err } = Result.parse(content, PixiFile).unwrap();\n if (err) {\n logger.debug({ packageFile, err }, `error parsing ${packageFile}`);\n return null;\n }\n\n return val;\n }\n\n const { val, err } = Result.parse(\n content,\n z.union([PixiFile, PixiPyProject.transform((p) => p.tool?.pixi)]),\n ).unwrap();\n\n if (err) {\n logger.debug({ packageFile, err }, `error parsing ${packageFile}`);\n return null;\n }\n /* v8 ignore next -- a successful parse always yields a value */\n return val ?? null;\n}\n\nexport async function extractPackageFile(\n content: string,\n packageFile: string,\n): Promise<PackageFileContent | null> {\n logger.trace(`pixi.extractPackageFile(${packageFile})`);\n\n const val = getUserPixiConfig(content, packageFile);\n if (!val) {\n return null;\n }\n\n const lockfileName = getSiblingFileName(packageFile, 'pixi.lock');\n const lockFiles: string[] = [];\n if (await localPathExists(lockfileName)) {\n lockFiles.push(lockfileName);\n }\n\n const project = val.project;\n\n const channelPriority = project['channel-priority'];\n\n let registryStrategy: RegistryStrategy | undefined;\n\n if (channelPriority === 'disabled') {\n registryStrategy = 'merge';\n }\n\n // resolve channels and build registry urls for each channel with order\n const conda: PixiPackageDependency[] = [];\n\n for (const item of val.conda) {\n conda.push(\n addRegistryUrls({\n ...item,\n channels: project.channels,\n registryStrategy,\n }),\n );\n }\n\n for (const item of val.feature.conda) {\n conda.push(\n addRegistryUrls({\n ...item,\n registryStrategy,\n channels: [...coerceArray(item.channels), ...project.channels],\n }),\n );\n }\n\n return {\n lockFiles,\n deps: [conda, val.pypi, val.feature.pypi].flat(),\n };\n}\n\nfunction addRegistryUrls(item: PixiPackageDependency): PixiPackageDependency {\n const channels = orderChannels(item.channels);\n\n if (item.channel) {\n return {\n ...item,\n channels,\n registryUrls: [channelToRegistryUrl(item.channel)],\n };\n }\n\n if (channels.length === 0) {\n return {\n ...item,\n channels,\n skipStage: 'extract',\n skipReason: 'unknown-registry',\n };\n }\n\n const registryUrls: string[] = [];\n for (const channel of channels) {\n registryUrls.push(channelToRegistryUrl(channel));\n }\n\n return {\n ...item,\n channels,\n registryUrls,\n };\n}\n\nfunction channelToRegistryUrl(channel: string): string {\n if (isHttpUrl(channel)) {\n return ensureTrailingSlash(channel);\n }\n\n return ensureTrailingSlash(joinUrlParts(defaultCondaRegistryApi, channel));\n}\n\nfunction orderChannels(channels: Channels = []): string[] {\n return channels\n .map((channel, index) => {\n if (isString(channel)) {\n return { channel, priority: 0, index };\n }\n\n return { ...channel, priority: coerceNumber(channel.priority), index };\n })\n .toSorted((a, b) => {\n // first based on priority then based on index\n if (a.priority !== b.priority) {\n return b.priority - a.priority;\n }\n\n return a.index - b.index;\n })\n .map((c) => c.channel);\n}\n"],"mappings":";;;;;;;;;;;AAwBA,SAAgB,kBACd,SACA,aACmB;CACnB,IACE,gBAAgB,oBAChB,YAAY,SAAS,iBAAiB,GACtC;EACA,MAAM,EAAE,KAAK,QAAQ,OAAO,MAAM,SAAS,aAAa,CAAC,CAAC,OAAO;EACjE,IAAI,KAAK;GACP,OAAO,MAAM;IAAE;IAAa;GAAI,GAAG,iBAAiB,aAAa;GACjE,OAAO;EACT;EAEA,OAAO,IAAI,MAAM,QAAQ;CAC3B;CAEA,IAAI,gBAAgB,eAAe,YAAY,SAAS,YAAY,GAAG;EACrE,MAAM,EAAE,KAAK,QAAQ,OAAO,MAAM,SAAS,QAAQ,CAAC,CAAC,OAAO;EAC5D,IAAI,KAAK;GACP,OAAO,MAAM;IAAE;IAAa;GAAI,GAAG,iBAAiB,aAAa;GACjE,OAAO;EACT;EAEA,OAAO;CACT;CAEA,MAAM,EAAE,KAAK,QAAQ,OAAO,MAC1B,SACA,EAAE,MAAM,CAAC,UAAU,cAAc,WAAW,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC,CAClE,CAAC,CAAC,OAAO;CAET,IAAI,KAAK;EACP,OAAO,MAAM;GAAE;GAAa;EAAI,GAAG,iBAAiB,aAAa;EACjE,OAAO;CACT;;CAEA,OAAO,OAAO;AAChB;AAEA,eAAsB,mBACpB,SACA,aACoC;CACpC,OAAO,MAAM,2BAA2B,YAAY,EAAE;CAEtD,MAAM,MAAM,kBAAkB,SAAS,WAAW;CAClD,IAAI,CAAC,KACH,OAAO;CAGT,MAAM,eAAe,mBAAmB,aAAa,WAAW;CAChE,MAAM,YAAsB,CAAC;CAC7B,IAAI,MAAM,gBAAgB,YAAY,GACpC,UAAU,KAAK,YAAY;CAG7B,MAAM,UAAU,IAAI;CAEpB,MAAM,kBAAkB,QAAQ;CAEhC,IAAI;CAEJ,IAAI,oBAAoB,YACtB,mBAAmB;CAIrB,MAAM,QAAiC,CAAC;CAExC,KAAK,MAAM,QAAQ,IAAI,OACrB,MAAM,KACJ,gBAAgB;EACd,GAAG;EACH,UAAU,QAAQ;EAClB;CACF,CAAC,CACH;CAGF,KAAK,MAAM,QAAQ,IAAI,QAAQ,OAC7B,MAAM,KACJ,gBAAgB;EACd,GAAG;EACH;EACA,UAAU,CAAC,GAAG,YAAY,KAAK,QAAQ,GAAG,GAAG,QAAQ,QAAQ;CAC/D,CAAC,CACH;CAGF,OAAO;EACL;EACA,MAAM;GAAC;GAAO,IAAI;GAAM,IAAI,QAAQ;EAAI,CAAC,CAAC,KAAK;CACjD;AACF;AAEA,SAAS,gBAAgB,MAAoD;CAC3E,MAAM,WAAW,cAAc,KAAK,QAAQ;CAE5C,IAAI,KAAK,SACP,OAAO;EACL,GAAG;EACH;EACA,cAAc,CAAC,qBAAqB,KAAK,OAAO,CAAC;CACnD;CAGF,IAAI,SAAS,WAAW,GACtB,OAAO;EACL,GAAG;EACH;EACA,WAAW;EACX,YAAY;CACd;CAGF,MAAM,eAAyB,CAAC;CAChC,KAAK,MAAM,WAAW,UACpB,aAAa,KAAK,qBAAqB,OAAO,CAAC;CAGjD,OAAO;EACL,GAAG;EACH;EACA;CACF;AACF;AAEA,SAAS,qBAAqB,SAAyB;CACrD,IAAI,UAAU,OAAO,GACnB,OAAO,oBAAoB,OAAO;CAGpC,OAAO,oBAAoB,aAAaA,oBAAyB,OAAO,CAAC;AAC3E;AAEA,SAAS,cAAc,WAAqB,CAAC,GAAa;CACxD,OAAO,SACJ,KAAK,SAAS,UAAU;EACvB,IAAI,SAAS,OAAO,GAClB,OAAO;GAAE;GAAS,UAAU;GAAG;EAAM;EAGvC,OAAO;GAAE,GAAG;GAAS,UAAU,aAAa,QAAQ,QAAQ;GAAG;EAAM;CACvE,CAAC,CAAC,CACD,UAAU,GAAG,MAAM;EAElB,IAAI,EAAE,aAAa,EAAE,UACnB,OAAO,EAAE,WAAW,EAAE;EAGxB,OAAO,EAAE,QAAQ,EAAE;CACrB,CAAC,CAAC,CACD,KAAK,MAAM,EAAE,OAAO;AACzB"}
|
|
@@ -83,6 +83,7 @@ async function getMatchingHostRule(url) {
|
|
|
83
83
|
logger.once.debug(`Failed to parse URL ${url}`);
|
|
84
84
|
return {};
|
|
85
85
|
}
|
|
86
|
+
// v8 ignore else -- needs a non artifact-registry source url
|
|
86
87
|
if (parsedUrl.hostname.endsWith(".pkg.dev")) {
|
|
87
88
|
const hostRule = await getGoogleAuthHostRule();
|
|
88
89
|
if (hostRule && Object.keys(hostRule).length !== 0) return hostRule;
|