renovate 43.268.5 → 43.269.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/platform/gerrit/index.js +33 -11
- package/dist/modules/platform/gerrit/index.js.map +1 -1
- package/dist/modules/platform/gerrit/scm.js +35 -128
- package/dist/modules/platform/gerrit/scm.js.map +1 -1
- package/dist/util/git/index.d.ts +20 -8
- package/dist/util/git/index.js +79 -11
- package/dist/util/git/index.js.map +1 -1
- package/dist/util/git/types.d.ts +18 -1
- package/dist/util/git/types.js.map +1 -1
- package/package.json +2 -2
- package/renovate-schema.json +2 -2
|
@@ -4,9 +4,10 @@ import { regEx } from "../../../util/regex.js";
|
|
|
4
4
|
import { logger } from "../../../logger/index.js";
|
|
5
5
|
import { ensureTrailingSlash } from "../../../util/url.js";
|
|
6
6
|
import { parseJson } from "../../../util/common.js";
|
|
7
|
-
import {
|
|
7
|
+
import { toLongCommitSha } from "../../../util/schema-utils/git.js";
|
|
8
|
+
import { initRepo as initRepo$1, setVirtualBranch } from "../../../util/git/index.js";
|
|
8
9
|
import { setBaseUrl } from "../../../util/http/gerrit.js";
|
|
9
|
-
import { MAX_GERRIT_COMMENT_SIZE, REQUEST_DETAILS_FOR_PRS, TAG_PULL_REQUEST_BODY, getGerritRepoUrl, mapBranchStatusToLabel, mapGerritChangeToPr } from "./utils.js";
|
|
10
|
+
import { MAX_GERRIT_COMMENT_SIZE, REQUEST_DETAILS_FOR_PRS, TAG_PULL_REQUEST_BODY, extractSourceBranch, getGerritRepoUrl, mapBranchStatusToLabel, mapGerritChangeToPr } from "./utils.js";
|
|
10
11
|
import { client } from "./client.js";
|
|
11
12
|
import { configureScm, pushForReview } from "./scm.js";
|
|
12
13
|
import { repoFingerprint } from "../util.js";
|
|
@@ -104,15 +105,7 @@ async function initRepo({ repository, cloneSubmodules, cloneSubmodulesFilter, gi
|
|
|
104
105
|
config: projectInfo,
|
|
105
106
|
labels: projectInfo.labels ?? {}
|
|
106
107
|
};
|
|
107
|
-
const
|
|
108
|
-
const url = getGerritRepoUrl(repository, baseUrl, gitUrl, config.gerritUsername);
|
|
109
|
-
configureScm(repository, config.gerritUsername);
|
|
110
|
-
await initRepo$1({
|
|
111
|
-
url,
|
|
112
|
-
cloneSubmodules,
|
|
113
|
-
cloneSubmodulesFilter
|
|
114
|
-
});
|
|
115
|
-
const rejectedChanges = await client.findChanges(config.repository, {
|
|
108
|
+
const rejectedChanges = await client.findChanges(repository, {
|
|
116
109
|
branchName: "",
|
|
117
110
|
state: "open",
|
|
118
111
|
label: "-2"
|
|
@@ -121,6 +114,32 @@ async function initRepo({ repository, cloneSubmodules, cloneSubmodulesFilter, gi
|
|
|
121
114
|
await client.abandonChange(change._number, "This change has been abandoned as it was voted with Code-Review -2.");
|
|
122
115
|
logger.info(`Abandoned change ${change._number} with Code-Review -2 in repository ${repository}`);
|
|
123
116
|
}
|
|
117
|
+
const openChanges = await client.findChanges(repository, {
|
|
118
|
+
branchName: "",
|
|
119
|
+
state: "open",
|
|
120
|
+
requestDetails: ["CURRENT_REVISION", "COMMIT_FOOTERS"]
|
|
121
|
+
});
|
|
122
|
+
const virtualBranches = {};
|
|
123
|
+
for (const change of openChanges) {
|
|
124
|
+
const branchName = extractSourceBranch(change);
|
|
125
|
+
if (!branchName) continue;
|
|
126
|
+
const sha = toLongCommitSha(change.current_revision);
|
|
127
|
+
virtualBranches[branchName] = {
|
|
128
|
+
ref: change.revisions[sha].ref,
|
|
129
|
+
sha
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const virtualBranchCount = Object.keys(virtualBranches).length;
|
|
133
|
+
if (virtualBranchCount > 0) logger.debug(`Will fetch ${virtualBranchCount} Gerrit changes as virtual branches`);
|
|
134
|
+
const baseUrl = defaults.endpoint;
|
|
135
|
+
const url = getGerritRepoUrl(repository, baseUrl, gitUrl, config.gerritUsername);
|
|
136
|
+
configureScm(repository);
|
|
137
|
+
await initRepo$1({
|
|
138
|
+
url,
|
|
139
|
+
cloneSubmodules,
|
|
140
|
+
cloneSubmodulesFilter,
|
|
141
|
+
virtualBranches
|
|
142
|
+
});
|
|
124
143
|
return {
|
|
125
144
|
defaultBranch: config.head,
|
|
126
145
|
isFork: false,
|
|
@@ -171,6 +190,9 @@ async function createPr(prConfig) {
|
|
|
171
190
|
requestDetails: REQUEST_DETAILS_FOR_PRS
|
|
172
191
|
})).pop();
|
|
173
192
|
if (isUndefined(change)) throw new Error(`Could not find the Gerrit change after pushing to refs/for/${prConfig.targetBranch}`);
|
|
193
|
+
const sha = toLongCommitSha(change.current_revision);
|
|
194
|
+
const ref = change.revisions[sha].ref;
|
|
195
|
+
await setVirtualBranch(prConfig.sourceBranch, ref, sha);
|
|
174
196
|
await client.addMessage(change._number, prConfig.prBody, TAG_PULL_REQUEST_BODY);
|
|
175
197
|
return mapGerritChangeToPr(change, {
|
|
176
198
|
sourceBranch: prConfig.sourceBranch,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["git.initRepo"],"sources":["../../../../lib/modules/platform/gerrit/index.ts"],"sourcesContent":["import { isTruthy, isUndefined } from '@sindresorhus/is';\nimport semver from 'semver';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as git from '../../../util/git/index.ts';\nimport { setBaseUrl } from '../../../util/http/gerrit.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport type {\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfigByContent,\n EnsureCommentRemovalConfigByTopic,\n EnsureIssueConfig,\n EnsureIssueResult,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformResult,\n Pr,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\n\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport { readOnlyIssueBody } from '../utils/read-only-issue-body.ts';\nimport { client } from './client.ts';\nimport type { GerritLabelTypeInfo, GerritProjectInfo } from './schema.ts';\nimport { configureScm, pushForReview } from './scm.ts';\nimport {\n MAX_GERRIT_COMMENT_SIZE,\n REQUEST_DETAILS_FOR_PRS,\n TAG_PULL_REQUEST_BODY,\n getGerritRepoUrl,\n mapBranchStatusToLabel,\n mapGerritChangeToPr,\n} from './utils.ts';\n\nexport const id = 'gerrit';\nexport const experimental = true;\n\nconst defaults: {\n endpoint?: string;\n} = {};\n\nlet config: {\n repository?: string;\n head?: string;\n config?: GerritProjectInfo;\n labels: Record<string, GerritLabelTypeInfo>;\n gerritUsername?: string;\n} = {\n labels: {},\n};\n\nexport function writeToConfig(newConfig: typeof config): void {\n config = { ...config, ...newConfig };\n}\n\nexport async function initPlatform({\n endpoint,\n username,\n password,\n}: PlatformParams): Promise<PlatformResult> {\n logger.debug(`initPlatform(${endpoint!}, ${username!})`);\n if (!endpoint) {\n throw new Error('Init: You must configure a Gerrit Server endpoint');\n }\n if (!(username && password)) {\n throw new Error(\n 'Init: You must configure a Gerrit Server username/password',\n );\n }\n config.gerritUsername = username;\n defaults.endpoint = ensureTrailingSlash(endpoint);\n setBaseUrl(defaults.endpoint);\n\n let gerritVersion: string;\n try {\n const env = getEnv();\n /* v8 ignore if: experimental feature */\n if (env.RENOVATE_X_PLATFORM_VERSION) {\n gerritVersion = env.RENOVATE_X_PLATFORM_VERSION;\n } else {\n gerritVersion = await client.getGerritVersion({\n username,\n password,\n });\n }\n } catch (err) {\n logger.debug(\n { err },\n 'Error authenticating with Gerrit. Check your credentials',\n );\n throw new Error('Init: Authentication failure');\n }\n\n logger.debug(`Gerrit version is: ${gerritVersion}`);\n // Example: 3.13.0-rc3-148-gb478dbbb57\n const parsed = semver.parse(gerritVersion);\n if (!parsed) {\n throw new Error(`Unable to parse Gerrit version: ${gerritVersion}`);\n }\n gerritVersion = `${parsed.major}.${parsed.minor}.${parsed.patch}`;\n client.setGerritVersion(gerritVersion);\n\n const platformConfig: PlatformResult = {\n endpoint: defaults.endpoint,\n };\n return platformConfig;\n}\n\n/**\n * Get all state=\"ACTIVE\" and type=\"CODE\" repositories from gerrit\n */\nexport async function getRepos(): Promise<string[]> {\n logger.debug(`getRepos()`);\n return await client.getRepos();\n}\n\n/**\n * Clone repository to local directory\n * @param config\n */\nexport async function initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n gitUrl,\n}: RepoParams): Promise<RepoResult> {\n logger.debug(`initRepo(${repository}, ${gitUrl})`);\n const projectInfo = await client.getProjectInfo(repository);\n const branchInfo = await client.getBranchInfo(repository);\n\n config = {\n ...config,\n repository,\n head: branchInfo.revision,\n config: projectInfo,\n labels: projectInfo.labels ?? {},\n };\n const baseUrl = defaults.endpoint!;\n const url = getGerritRepoUrl(\n repository,\n baseUrl,\n gitUrl,\n config.gerritUsername!,\n );\n configureScm(repository, config.gerritUsername!);\n await git.initRepo({ url, cloneSubmodules, cloneSubmodulesFilter });\n\n //abandon \"open\" and \"rejected\" changes at startup\n const rejectedChanges = await client.findChanges(config.repository!, {\n branchName: '',\n state: 'open',\n label: '-2',\n });\n for (const change of rejectedChanges) {\n await client.abandonChange(\n change._number,\n 'This change has been abandoned as it was voted with Code-Review -2.',\n );\n logger.info(\n `Abandoned change ${change._number} with Code-Review -2 in repository ${repository}`,\n );\n }\n const repoConfig: RepoResult = {\n defaultBranch: config.head!,\n isFork: false,\n repoFingerprint: repoFingerprint(repository, baseUrl),\n };\n return repoConfig;\n}\n\nexport async function findPr(findPRConfig: FindPRConfig): Promise<Pr | null> {\n const change = (\n await client.findChanges(config.repository!, {\n ...findPRConfig,\n singleChange: true,\n requestDetails: REQUEST_DETAILS_FOR_PRS,\n })\n ).pop();\n return change\n ? mapGerritChangeToPr(change, {\n sourceBranch: findPRConfig.branchName,\n })\n : null;\n}\n\nexport async function getPr(number: number): Promise<Pr | null> {\n try {\n const change = await client.getChange(number, REQUEST_DETAILS_FOR_PRS);\n return mapGerritChangeToPr(change);\n } catch (err) {\n if (err.statusCode === 404) {\n return null;\n }\n throw err;\n }\n}\n\nexport async function updatePr(prConfig: UpdatePrConfig): Promise<void> {\n logger.debug(`updatePr(${prConfig.number}, ${prConfig.prTitle})`);\n if (prConfig.prBody) {\n await client.addMessageIfNotAlreadyExists(\n prConfig.number,\n prConfig.prBody,\n TAG_PULL_REQUEST_BODY,\n );\n }\n await client.setHashtags(prConfig.number, {\n add: prConfig.addLabels,\n remove: prConfig.removeLabels,\n });\n if (prConfig.targetBranch) {\n await client.moveChange(prConfig.number, prConfig.targetBranch);\n }\n if (prConfig.state && prConfig.state === 'closed') {\n await client.abandonChange(prConfig.number);\n }\n}\n\nexport async function createPr(prConfig: CreatePRConfig): Promise<Pr | null> {\n logger.debug(\n `createPr(${prConfig.sourceBranch}, ${prConfig.prTitle}, ${\n prConfig.labels?.toString() ?? ''\n })`,\n );\n\n logger.debug(\n `Pushing commit to refs/for/${prConfig.targetBranch} to create Gerrit change`,\n );\n const pushResult = await pushForReview({\n sourceRef: prConfig.sourceBranch,\n targetBranch: prConfig.targetBranch,\n files: [],\n autoApprove: prConfig.platformPrOptions?.autoApprove,\n labels: prConfig.labels ?? undefined,\n });\n\n if (!pushResult) {\n throw new Error(\n `Failed to push commit to refs/for/${prConfig.targetBranch} to create Gerrit change`,\n );\n }\n\n const change = (\n await client.findChanges(config.repository!, {\n branchName: prConfig.sourceBranch,\n targetBranch: prConfig.targetBranch,\n state: 'open',\n singleChange: true,\n requestDetails: REQUEST_DETAILS_FOR_PRS,\n })\n ).pop();\n if (isUndefined(change)) {\n throw new Error(\n `Could not find the Gerrit change after pushing to refs/for/${prConfig.targetBranch}`,\n );\n }\n await client.addMessage(\n change._number,\n prConfig.prBody,\n TAG_PULL_REQUEST_BODY,\n );\n return mapGerritChangeToPr(change, {\n sourceBranch: prConfig.sourceBranch,\n prBody: prConfig.prBody,\n });\n}\n\nexport async function getBranchPr(\n branchName: string,\n targetBranch?: string,\n): Promise<Pr | null> {\n const change = await client.getBranchChange(config.repository!, {\n branchName,\n state: 'open',\n targetBranch,\n requestDetails: REQUEST_DETAILS_FOR_PRS,\n });\n\n return change\n ? mapGerritChangeToPr(change, {\n sourceBranch: branchName,\n })\n : null;\n}\n\nexport async function getPrList(): Promise<Pr[]> {\n const changes = await client.findChanges(config.repository!, {\n branchName: '',\n requestDetails: REQUEST_DETAILS_FOR_PRS,\n });\n return changes.map((change) => mapGerritChangeToPr(change)).filter(isTruthy);\n}\n\nexport async function mergePr(config: MergePRConfig): Promise<boolean> {\n logger.debug(\n `mergePr(${config.id}, ${config.branchName!}, ${config.strategy!})`,\n );\n try {\n const change = await client.submitChange(config.id);\n return change.status === 'MERGED';\n } catch (err) {\n if (err.statusCode === 409) {\n logger.warn(\n { err },\n \"Can't submit the change, because the submit rule doesn't allow it.\",\n );\n return false;\n }\n throw err;\n }\n}\n\n/**\n * BranchStatus for Gerrit assumes that the branchName refers to a change.\n * @param branchName\n */\nexport async function getBranchStatus(\n branchName: string,\n): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n const change = (\n await client.findChanges(config.repository!, {\n state: 'open',\n branchName,\n singleChange: true,\n requestDetails: ['LABELS', 'SUBMITTABLE', 'CHECK'],\n })\n ).pop();\n if (change) {\n const hasProblems = change.problems && change.problems.length > 0;\n if (hasProblems) {\n return 'red';\n }\n const hasBlockingLabels = Object.values(change.labels ?? {}).some(\n (label) => label.blocking,\n );\n if (hasBlockingLabels) {\n return 'red';\n }\n // v8 ignore else -- TODO: add test #40625\n if (change.submittable) {\n return 'green';\n }\n }\n return 'yellow';\n}\n\n/**\n * check the gerrit-change for the presence of the corresponding \"$context\" Gerrit label if configured,\n * return 'yellow' if not configured or not set\n * @param branchName\n * @param context renovate/stability-days || ...\n */\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n const labelConfig = config.labels[context];\n if (labelConfig) {\n const change = (\n await client.findChanges(config.repository!, {\n branchName,\n state: 'open',\n singleChange: true,\n requestDetails: ['LABELS'],\n })\n ).pop();\n // v8 ignore else -- TODO: add test #40625\n if (change) {\n const label = change.labels![context];\n // v8 ignore else -- TODO: add test #40625\n if (label) {\n // Check for rejected or blocking first, as a label could have both rejected and approved\n if (label.rejected || label.blocking) {\n return 'red';\n }\n // v8 ignore else -- TODO: add test #40625\n if (label.approved) {\n return 'green';\n }\n }\n }\n }\n return 'yellow';\n}\n\n/**\n * Apply the branch state $context to the corresponding gerrit label (if available)\n * context === \"renovate/stability-days\" / \"renovate/merge-confidence\" and state === \"green\"/...\n * @param branchStatusConfig\n */\nexport async function setBranchStatus(\n branchStatusConfig: BranchStatusConfig,\n): Promise<void> {\n const label = config.labels[branchStatusConfig.context];\n const labelValue =\n label && mapBranchStatusToLabel(branchStatusConfig.state, label);\n if (branchStatusConfig.context && labelValue) {\n const change = (\n await client.findChanges(config.repository!, {\n branchName: branchStatusConfig.branchName,\n state: 'open',\n singleChange: true,\n requestDetails: ['LABELS'],\n })\n ).pop();\n\n const labelKey = branchStatusConfig.context;\n if (!change?.labels || !Object.hasOwn(change.labels, labelKey)) {\n return;\n }\n\n await client.setLabel(change._number, labelKey, labelValue);\n }\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const repo = repoName ?? config.repository;\n if (!repo) {\n logger.debug('No repo so cannot getRawFile');\n return null;\n }\n // v8 ignore next -- TODO: add test #40625\n const branch =\n branchOrTag ??\n (repo === config.repository ? (config.head ?? 'HEAD') : 'HEAD');\n const result = await client.getFile(repo, branch, fileName);\n return result;\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\nexport async function addReviewers(\n number: number,\n reviewers: string[],\n): Promise<void> {\n await client.addReviewers(number, reviewers);\n}\n\n/**\n * add \"CC\" (only one possible)\n */\nexport async function addAssignees(\n number: number,\n assignees: string[],\n): Promise<void> {\n // v8 ignore else -- TODO: add test #40625\n if (assignees.length) {\n // v8 ignore else -- TODO: add test #40625\n if (assignees.length > 1) {\n logger.debug(\n `addAssignees(${number}, ${assignees.toString()}) called with more then one assignee! Gerrit only supports one assignee! Using the first from list.`,\n );\n }\n await client.addAssignee(number, assignees[0]);\n }\n}\n\nexport async function ensureComment(\n ensureComment: EnsureCommentConfig,\n): Promise<boolean> {\n logger.debug(\n `ensureComment(${ensureComment.number}, ${ensureComment.topic!}, ${\n ensureComment.content\n })`,\n );\n await client.addMessageIfNotAlreadyExists(\n ensureComment.number,\n ensureComment.content,\n ensureComment.topic ?? undefined,\n );\n return true;\n}\n\nexport function massageMarkdown(prBody: string, rebaseLabel: string): string {\n return (\n smartTruncate(readOnlyIssueBody(prBody), maxBodyLength())\n .replace('Branch creation', 'Change creation')\n .replace(\n 'close this Pull Request unmerged',\n 'abandon or vote this change with Code-Review -2',\n )\n .replace(\n 'Close this PR',\n 'Abandon or vote this change with Code-Review -2',\n )\n .replace(\n 'you tick the rebase/retry checkbox',\n `you add the _${rebaseLabel}_ hashtag to this change`,\n )\n .replace(\n 'checking the rebase/retry box above',\n `adding the _${rebaseLabel}_ hashtag to this change`,\n )\n .replace(regEx(/\\b(?:Pull Request|PR)/g), 'change')\n // Remove HTML tags not supported in Gerrit markdown\n .replace(regEx(/<\\/?summary>/g), '**')\n .replace(regEx(/<\\/?(details|blockquote)>/g), '')\n .replace(regEx(`\\n---\\n\\n.*?<!-- rebase-check -->.*?\\n`), '')\n .replace(regEx(/<!--renovate-(?:debug|config-hash):.*?-->/g), '')\n // Remove zero-width-space not supported in Gerrit markdown\n .replace(regEx(/​/g), '')\n );\n}\n\nexport function maxBodyLength(): number {\n return MAX_GERRIT_COMMENT_SIZE;\n}\n\nexport async function deleteLabel(\n number: number,\n label: string,\n): Promise<void> {\n await client.setHashtags(number, { remove: [label] });\n}\n\nexport function ensureCommentRemoval(\n _ensureCommentRemoval:\n | EnsureCommentRemovalConfigByTopic\n | EnsureCommentRemovalConfigByContent,\n): Promise<void> {\n return Promise.resolve();\n}\n\nexport function ensureIssueClosing(_title: string): Promise<void> {\n return Promise.resolve();\n}\n\nexport function ensureIssue(\n _issueConfig: EnsureIssueConfig,\n): Promise<EnsureIssueResult | null> {\n return Promise.resolve(null);\n}\n\nexport function findIssue(_title: string): Promise<Issue | null> {\n return Promise.resolve(null);\n}\n\nexport function getIssueList(): Promise<Issue[]> {\n return Promise.resolve([]);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["git.initRepo","git.setVirtualBranch"],"sources":["../../../../lib/modules/platform/gerrit/index.ts"],"sourcesContent":["import { isTruthy, isUndefined } from '@sindresorhus/is';\nimport semver from 'semver';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as git from '../../../util/git/index.ts';\nimport type { VirtualBranch } from '../../../util/git/types.ts';\nimport { setBaseUrl } from '../../../util/http/gerrit.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { toLongCommitSha } from '../../../util/schema-utils/git.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport type {\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfigByContent,\n EnsureCommentRemovalConfigByTopic,\n EnsureIssueConfig,\n EnsureIssueResult,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformResult,\n Pr,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\n\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport { readOnlyIssueBody } from '../utils/read-only-issue-body.ts';\nimport { client } from './client.ts';\nimport type { GerritLabelTypeInfo, GerritProjectInfo } from './schema.ts';\nimport { configureScm, pushForReview } from './scm.ts';\nimport {\n MAX_GERRIT_COMMENT_SIZE,\n REQUEST_DETAILS_FOR_PRS,\n TAG_PULL_REQUEST_BODY,\n extractSourceBranch,\n getGerritRepoUrl,\n mapBranchStatusToLabel,\n mapGerritChangeToPr,\n} from './utils.ts';\n\nexport const id = 'gerrit';\nexport const experimental = true;\n\nconst defaults: {\n endpoint?: string;\n} = {};\n\nlet config: {\n repository?: string;\n head?: string;\n config?: GerritProjectInfo;\n labels: Record<string, GerritLabelTypeInfo>;\n gerritUsername?: string;\n} = {\n labels: {},\n};\n\nexport function writeToConfig(newConfig: typeof config): void {\n config = { ...config, ...newConfig };\n}\n\nexport async function initPlatform({\n endpoint,\n username,\n password,\n}: PlatformParams): Promise<PlatformResult> {\n logger.debug(`initPlatform(${endpoint!}, ${username!})`);\n if (!endpoint) {\n throw new Error('Init: You must configure a Gerrit Server endpoint');\n }\n if (!(username && password)) {\n throw new Error(\n 'Init: You must configure a Gerrit Server username/password',\n );\n }\n config.gerritUsername = username;\n defaults.endpoint = ensureTrailingSlash(endpoint);\n setBaseUrl(defaults.endpoint);\n\n let gerritVersion: string;\n try {\n const env = getEnv();\n /* v8 ignore if: experimental feature */\n if (env.RENOVATE_X_PLATFORM_VERSION) {\n gerritVersion = env.RENOVATE_X_PLATFORM_VERSION;\n } else {\n gerritVersion = await client.getGerritVersion({\n username,\n password,\n });\n }\n } catch (err) {\n logger.debug(\n { err },\n 'Error authenticating with Gerrit. Check your credentials',\n );\n throw new Error('Init: Authentication failure');\n }\n\n logger.debug(`Gerrit version is: ${gerritVersion}`);\n // Example: 3.13.0-rc3-148-gb478dbbb57\n const parsed = semver.parse(gerritVersion);\n if (!parsed) {\n throw new Error(`Unable to parse Gerrit version: ${gerritVersion}`);\n }\n gerritVersion = `${parsed.major}.${parsed.minor}.${parsed.patch}`;\n client.setGerritVersion(gerritVersion);\n\n const platformConfig: PlatformResult = {\n endpoint: defaults.endpoint,\n };\n return platformConfig;\n}\n\n/**\n * Get all state=\"ACTIVE\" and type=\"CODE\" repositories from gerrit\n */\nexport async function getRepos(): Promise<string[]> {\n logger.debug(`getRepos()`);\n return await client.getRepos();\n}\n\n/**\n * Clone repository to local directory\n * @param config\n */\nexport async function initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n gitUrl,\n}: RepoParams): Promise<RepoResult> {\n logger.debug(`initRepo(${repository}, ${gitUrl})`);\n const projectInfo = await client.getProjectInfo(repository);\n const branchInfo = await client.getBranchInfo(repository);\n\n config = {\n ...config,\n repository,\n head: branchInfo.revision,\n config: projectInfo,\n labels: projectInfo.labels ?? {},\n };\n\n //abandon \"open\" and \"rejected\" changes at startup\n const rejectedChanges = await client.findChanges(repository, {\n branchName: '',\n state: 'open',\n label: '-2',\n });\n for (const change of rejectedChanges) {\n await client.abandonChange(\n change._number,\n 'This change has been abandoned as it was voted with Code-Review -2.',\n );\n logger.info(\n `Abandoned change ${change._number} with Code-Review -2 in repository ${repository}`,\n );\n }\n\n // Collect open Gerrit changes to initialize as virtual branches.\n // This allows DefaultGitScm to treat them as regular Git branches.\n const openChanges = await client.findChanges(repository, {\n branchName: '',\n state: 'open',\n requestDetails: ['CURRENT_REVISION', 'COMMIT_FOOTERS'],\n });\n const virtualBranches: Record<string, VirtualBranch> = {};\n for (const change of openChanges) {\n const branchName = extractSourceBranch(change);\n if (!branchName) {\n continue;\n }\n const sha = toLongCommitSha(change.current_revision);\n const ref = change.revisions![sha].ref;\n virtualBranches[branchName] = { ref, sha };\n }\n\n const virtualBranchCount = Object.keys(virtualBranches).length;\n if (virtualBranchCount > 0) {\n logger.debug(\n `Will fetch ${virtualBranchCount} Gerrit changes as virtual branches`,\n );\n }\n\n const baseUrl = defaults.endpoint!;\n const url = getGerritRepoUrl(\n repository,\n baseUrl,\n gitUrl,\n config.gerritUsername!,\n );\n configureScm(repository);\n await git.initRepo({\n url,\n cloneSubmodules,\n cloneSubmodulesFilter,\n virtualBranches,\n });\n\n const repoConfig: RepoResult = {\n defaultBranch: config.head!,\n isFork: false,\n repoFingerprint: repoFingerprint(repository, baseUrl),\n };\n return repoConfig;\n}\n\nexport async function findPr(findPRConfig: FindPRConfig): Promise<Pr | null> {\n const change = (\n await client.findChanges(config.repository!, {\n ...findPRConfig,\n singleChange: true,\n requestDetails: REQUEST_DETAILS_FOR_PRS,\n })\n ).pop();\n return change\n ? mapGerritChangeToPr(change, {\n sourceBranch: findPRConfig.branchName,\n })\n : null;\n}\n\nexport async function getPr(number: number): Promise<Pr | null> {\n try {\n const change = await client.getChange(number, REQUEST_DETAILS_FOR_PRS);\n return mapGerritChangeToPr(change);\n } catch (err) {\n if (err.statusCode === 404) {\n return null;\n }\n throw err;\n }\n}\n\nexport async function updatePr(prConfig: UpdatePrConfig): Promise<void> {\n logger.debug(`updatePr(${prConfig.number}, ${prConfig.prTitle})`);\n if (prConfig.prBody) {\n await client.addMessageIfNotAlreadyExists(\n prConfig.number,\n prConfig.prBody,\n TAG_PULL_REQUEST_BODY,\n );\n }\n await client.setHashtags(prConfig.number, {\n add: prConfig.addLabels,\n remove: prConfig.removeLabels,\n });\n if (prConfig.targetBranch) {\n await client.moveChange(prConfig.number, prConfig.targetBranch);\n }\n if (prConfig.state && prConfig.state === 'closed') {\n await client.abandonChange(prConfig.number);\n }\n}\n\nexport async function createPr(prConfig: CreatePRConfig): Promise<Pr | null> {\n logger.debug(\n `createPr(${prConfig.sourceBranch}, ${prConfig.prTitle}, ${\n prConfig.labels?.toString() ?? ''\n })`,\n );\n\n logger.debug(\n `Pushing commit to refs/for/${prConfig.targetBranch} to create Gerrit change`,\n );\n const pushResult = await pushForReview({\n sourceRef: prConfig.sourceBranch,\n targetBranch: prConfig.targetBranch,\n files: [],\n autoApprove: prConfig.platformPrOptions?.autoApprove,\n labels: prConfig.labels ?? undefined,\n });\n\n if (!pushResult) {\n throw new Error(\n `Failed to push commit to refs/for/${prConfig.targetBranch} to create Gerrit change`,\n );\n }\n\n const change = (\n await client.findChanges(config.repository!, {\n branchName: prConfig.sourceBranch,\n targetBranch: prConfig.targetBranch,\n state: 'open',\n singleChange: true,\n requestDetails: REQUEST_DETAILS_FOR_PRS,\n })\n ).pop();\n if (isUndefined(change)) {\n throw new Error(\n `Could not find the Gerrit change after pushing to refs/for/${prConfig.targetBranch}`,\n );\n }\n\n // Register the virtual branch now that the change exists and we have the ref.\n const sha = toLongCommitSha(change.current_revision);\n const ref = change.revisions![sha].ref;\n await git.setVirtualBranch(prConfig.sourceBranch, ref, sha);\n\n await client.addMessage(\n change._number,\n prConfig.prBody,\n TAG_PULL_REQUEST_BODY,\n );\n return mapGerritChangeToPr(change, {\n sourceBranch: prConfig.sourceBranch,\n prBody: prConfig.prBody,\n });\n}\n\nexport async function getBranchPr(\n branchName: string,\n targetBranch?: string,\n): Promise<Pr | null> {\n const change = await client.getBranchChange(config.repository!, {\n branchName,\n state: 'open',\n targetBranch,\n requestDetails: REQUEST_DETAILS_FOR_PRS,\n });\n\n return change\n ? mapGerritChangeToPr(change, {\n sourceBranch: branchName,\n })\n : null;\n}\n\nexport async function getPrList(): Promise<Pr[]> {\n const changes = await client.findChanges(config.repository!, {\n branchName: '',\n requestDetails: REQUEST_DETAILS_FOR_PRS,\n });\n return changes.map((change) => mapGerritChangeToPr(change)).filter(isTruthy);\n}\n\nexport async function mergePr(config: MergePRConfig): Promise<boolean> {\n logger.debug(\n `mergePr(${config.id}, ${config.branchName!}, ${config.strategy!})`,\n );\n try {\n const change = await client.submitChange(config.id);\n return change.status === 'MERGED';\n } catch (err) {\n if (err.statusCode === 409) {\n logger.warn(\n { err },\n \"Can't submit the change, because the submit rule doesn't allow it.\",\n );\n return false;\n }\n throw err;\n }\n}\n\n/**\n * BranchStatus for Gerrit assumes that the branchName refers to a change.\n * @param branchName\n */\nexport async function getBranchStatus(\n branchName: string,\n): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n const change = (\n await client.findChanges(config.repository!, {\n state: 'open',\n branchName,\n singleChange: true,\n requestDetails: ['LABELS', 'SUBMITTABLE', 'CHECK'],\n })\n ).pop();\n if (change) {\n const hasProblems = change.problems && change.problems.length > 0;\n if (hasProblems) {\n return 'red';\n }\n const hasBlockingLabels = Object.values(change.labels ?? {}).some(\n (label) => label.blocking,\n );\n if (hasBlockingLabels) {\n return 'red';\n }\n // v8 ignore else -- TODO: add test #40625\n if (change.submittable) {\n return 'green';\n }\n }\n return 'yellow';\n}\n\n/**\n * check the gerrit-change for the presence of the corresponding \"$context\" Gerrit label if configured,\n * return 'yellow' if not configured or not set\n * @param branchName\n * @param context renovate/stability-days || ...\n */\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n const labelConfig = config.labels[context];\n if (labelConfig) {\n const change = (\n await client.findChanges(config.repository!, {\n branchName,\n state: 'open',\n singleChange: true,\n requestDetails: ['LABELS'],\n })\n ).pop();\n // v8 ignore else -- TODO: add test #40625\n if (change) {\n const label = change.labels![context];\n // v8 ignore else -- TODO: add test #40625\n if (label) {\n // Check for rejected or blocking first, as a label could have both rejected and approved\n if (label.rejected || label.blocking) {\n return 'red';\n }\n // v8 ignore else -- TODO: add test #40625\n if (label.approved) {\n return 'green';\n }\n }\n }\n }\n return 'yellow';\n}\n\n/**\n * Apply the branch state $context to the corresponding gerrit label (if available)\n * context === \"renovate/stability-days\" / \"renovate/merge-confidence\" and state === \"green\"/...\n * @param branchStatusConfig\n */\nexport async function setBranchStatus(\n branchStatusConfig: BranchStatusConfig,\n): Promise<void> {\n const label = config.labels[branchStatusConfig.context];\n const labelValue =\n label && mapBranchStatusToLabel(branchStatusConfig.state, label);\n if (branchStatusConfig.context && labelValue) {\n const change = (\n await client.findChanges(config.repository!, {\n branchName: branchStatusConfig.branchName,\n state: 'open',\n singleChange: true,\n requestDetails: ['LABELS'],\n })\n ).pop();\n\n const labelKey = branchStatusConfig.context;\n if (!change?.labels || !Object.hasOwn(change.labels, labelKey)) {\n return;\n }\n\n await client.setLabel(change._number, labelKey, labelValue);\n }\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const repo = repoName ?? config.repository;\n if (!repo) {\n logger.debug('No repo so cannot getRawFile');\n return null;\n }\n // v8 ignore next -- TODO: add test #40625\n const branch =\n branchOrTag ??\n (repo === config.repository ? (config.head ?? 'HEAD') : 'HEAD');\n const result = await client.getFile(repo, branch, fileName);\n return result;\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\nexport async function addReviewers(\n number: number,\n reviewers: string[],\n): Promise<void> {\n await client.addReviewers(number, reviewers);\n}\n\n/**\n * add \"CC\" (only one possible)\n */\nexport async function addAssignees(\n number: number,\n assignees: string[],\n): Promise<void> {\n // v8 ignore else -- TODO: add test #40625\n if (assignees.length) {\n // v8 ignore else -- TODO: add test #40625\n if (assignees.length > 1) {\n logger.debug(\n `addAssignees(${number}, ${assignees.toString()}) called with more then one assignee! Gerrit only supports one assignee! Using the first from list.`,\n );\n }\n await client.addAssignee(number, assignees[0]);\n }\n}\n\nexport async function ensureComment(\n ensureComment: EnsureCommentConfig,\n): Promise<boolean> {\n logger.debug(\n `ensureComment(${ensureComment.number}, ${ensureComment.topic!}, ${\n ensureComment.content\n })`,\n );\n await client.addMessageIfNotAlreadyExists(\n ensureComment.number,\n ensureComment.content,\n ensureComment.topic ?? undefined,\n );\n return true;\n}\n\nexport function massageMarkdown(prBody: string, rebaseLabel: string): string {\n return (\n smartTruncate(readOnlyIssueBody(prBody), maxBodyLength())\n .replace('Branch creation', 'Change creation')\n .replace(\n 'close this Pull Request unmerged',\n 'abandon or vote this change with Code-Review -2',\n )\n .replace(\n 'Close this PR',\n 'Abandon or vote this change with Code-Review -2',\n )\n .replace(\n 'you tick the rebase/retry checkbox',\n `you add the _${rebaseLabel}_ hashtag to this change`,\n )\n .replace(\n 'checking the rebase/retry box above',\n `adding the _${rebaseLabel}_ hashtag to this change`,\n )\n .replace(regEx(/\\b(?:Pull Request|PR)/g), 'change')\n // Remove HTML tags not supported in Gerrit markdown\n .replace(regEx(/<\\/?summary>/g), '**')\n .replace(regEx(/<\\/?(details|blockquote)>/g), '')\n .replace(regEx(`\\n---\\n\\n.*?<!-- rebase-check -->.*?\\n`), '')\n .replace(regEx(/<!--renovate-(?:debug|config-hash):.*?-->/g), '')\n // Remove zero-width-space not supported in Gerrit markdown\n .replace(regEx(/​/g), '')\n );\n}\n\nexport function maxBodyLength(): number {\n return MAX_GERRIT_COMMENT_SIZE;\n}\n\nexport async function deleteLabel(\n number: number,\n label: string,\n): Promise<void> {\n await client.setHashtags(number, { remove: [label] });\n}\n\nexport function ensureCommentRemoval(\n _ensureCommentRemoval:\n | EnsureCommentRemovalConfigByTopic\n | EnsureCommentRemovalConfigByContent,\n): Promise<void> {\n return Promise.resolve();\n}\n\nexport function ensureIssueClosing(_title: string): Promise<void> {\n return Promise.resolve();\n}\n\nexport function ensureIssue(\n _issueConfig: EnsureIssueConfig,\n): Promise<EnsureIssueResult | null> {\n return Promise.resolve(null);\n}\n\nexport function findIssue(_title: string): Promise<Issue | null> {\n return Promise.resolve(null);\n}\n\nexport function getIssueList(): Promise<Issue[]> {\n return Promise.resolve([]);\n}\n"],"mappings":"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"}
|
|
@@ -1,110 +1,34 @@
|
|
|
1
1
|
import { logger } from "../../../logger/index.js";
|
|
2
2
|
import { hash } from "../../../util/hash.js";
|
|
3
|
-
import {
|
|
4
|
-
import { branchExists, deleteBranch, fetchRevSpec, getBranchCommit, getBranchUpdateDate, hasDiff, mergeToLocal, prepareCommit, pushCommit } from "../../../util/git/index.js";
|
|
3
|
+
import { prepareCommit, pushCommit, setVirtualBranch } from "../../../util/git/index.js";
|
|
5
4
|
import { DefaultGitScm } from "../default-scm.js";
|
|
6
|
-
import { convertGerritDateToISO } from "./utils.js";
|
|
7
5
|
import { client } from "./client.js";
|
|
8
|
-
import { isNonEmptyArray } from "@sindresorhus/is";
|
|
6
|
+
import { isNonEmptyArray, isString } from "@sindresorhus/is";
|
|
9
7
|
import { randomUUID } from "node:crypto";
|
|
10
|
-
import { DateTime } from "luxon";
|
|
11
8
|
//#region lib/modules/platform/gerrit/scm.ts
|
|
9
|
+
/**
|
|
10
|
+
* Gerrit SCM strategy:
|
|
11
|
+
* Instead of implementing custom branch operations, we fetch all open Gerrit changes
|
|
12
|
+
* as virtual branches (refs/remotes/origin/<branchName>) after repository initialization.
|
|
13
|
+
* This allows us to leverage DefaultGitScm for most operations, treating virtual branches
|
|
14
|
+
* as regular Git branches, while minimizing Gerrit API requests.
|
|
15
|
+
*/
|
|
12
16
|
let repository;
|
|
13
|
-
|
|
14
|
-
function configureScm(repo, login) {
|
|
17
|
+
function configureScm(repo) {
|
|
15
18
|
repository = repo;
|
|
16
|
-
username = login;
|
|
17
19
|
}
|
|
18
|
-
/** Branches with a local commit but no Gerrit change yet (push deferred to createPr()). */
|
|
19
|
-
const pendingChangeBranches = /* @__PURE__ */ new Set();
|
|
20
20
|
async function pushForReview(options) {
|
|
21
21
|
const pushOptions = ["notify=NONE", "ready"];
|
|
22
22
|
if (options.autoApprove) pushOptions.push("label=Code-Review+2");
|
|
23
23
|
if (isNonEmptyArray(options.labels)) for (const label of options.labels) pushOptions.push(`hashtag=${label}`);
|
|
24
|
-
|
|
24
|
+
return pushCommit({
|
|
25
25
|
sourceRef: options.sourceRef,
|
|
26
26
|
targetRef: `refs/for/${options.targetBranch}`,
|
|
27
27
|
files: options.files,
|
|
28
28
|
pushOptions
|
|
29
29
|
});
|
|
30
|
-
if (result) pendingChangeBranches.delete(options.sourceRef);
|
|
31
|
-
return result;
|
|
32
30
|
}
|
|
33
31
|
var GerritScm = class extends DefaultGitScm {
|
|
34
|
-
async branchExists(branchName) {
|
|
35
|
-
const searchConfig = {
|
|
36
|
-
state: "open",
|
|
37
|
-
branchName,
|
|
38
|
-
singleChange: true
|
|
39
|
-
};
|
|
40
|
-
if ((await client.findChanges(repository, searchConfig)).pop()) return true;
|
|
41
|
-
return branchExists(branchName);
|
|
42
|
-
}
|
|
43
|
-
async getBranchCommit(branchName) {
|
|
44
|
-
const searchConfig = {
|
|
45
|
-
state: "open",
|
|
46
|
-
branchName,
|
|
47
|
-
singleChange: true,
|
|
48
|
-
requestDetails: ["CURRENT_REVISION"]
|
|
49
|
-
};
|
|
50
|
-
const change = (await client.findChanges(repository, searchConfig)).pop();
|
|
51
|
-
if (isLongCommitSha(change?.current_revision)) return change.current_revision;
|
|
52
|
-
return getBranchCommit(branchName);
|
|
53
|
-
}
|
|
54
|
-
async getBranchUpdateDate(branchName) {
|
|
55
|
-
const searchConfig = {
|
|
56
|
-
state: "open",
|
|
57
|
-
branchName,
|
|
58
|
-
singleChange: true,
|
|
59
|
-
refreshCache: true,
|
|
60
|
-
requestDetails: ["CURRENT_REVISION"]
|
|
61
|
-
};
|
|
62
|
-
const change = (await client.findChanges(repository, searchConfig)).pop();
|
|
63
|
-
if (change) {
|
|
64
|
-
const date = convertGerritDateToISO(change.revisions[change.current_revision].created);
|
|
65
|
-
return DateTime.fromISO(date).toUTC();
|
|
66
|
-
}
|
|
67
|
-
return getBranchUpdateDate(branchName);
|
|
68
|
-
}
|
|
69
|
-
async isBranchBehindBase(branchName, baseBranch) {
|
|
70
|
-
const searchConfig = {
|
|
71
|
-
state: "open",
|
|
72
|
-
branchName,
|
|
73
|
-
targetBranch: baseBranch,
|
|
74
|
-
singleChange: true,
|
|
75
|
-
requestDetails: ["CURRENT_REVISION", "CURRENT_ACTIONS"]
|
|
76
|
-
};
|
|
77
|
-
const change = (await client.findChanges(repository, searchConfig)).pop();
|
|
78
|
-
if (change) return change.revisions[change.current_revision].actions.rebase.enabled === true;
|
|
79
|
-
return true;
|
|
80
|
-
}
|
|
81
|
-
async isBranchConflicted(baseBranch, branch) {
|
|
82
|
-
const searchConfig = {
|
|
83
|
-
state: "open",
|
|
84
|
-
branchName: branch,
|
|
85
|
-
targetBranch: baseBranch,
|
|
86
|
-
singleChange: true
|
|
87
|
-
};
|
|
88
|
-
const change = (await client.findChanges(repository, searchConfig)).pop();
|
|
89
|
-
if (change) return !(await client.getMergeableInfo(change)).mergeable;
|
|
90
|
-
logger.warn({
|
|
91
|
-
branch,
|
|
92
|
-
baseBranch
|
|
93
|
-
}, "There is no open change with this branch");
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
async isBranchModified(branchName, baseBranch) {
|
|
97
|
-
const searchConfig = {
|
|
98
|
-
state: "open",
|
|
99
|
-
branchName,
|
|
100
|
-
targetBranch: baseBranch,
|
|
101
|
-
singleChange: true,
|
|
102
|
-
requestDetails: ["CURRENT_REVISION", "DETAILED_ACCOUNTS"]
|
|
103
|
-
};
|
|
104
|
-
const change = (await client.findChanges(repository, searchConfig)).pop();
|
|
105
|
-
if (change) return change.revisions[change.current_revision].uploader.username !== username;
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
32
|
async commitAndPush(commit) {
|
|
109
33
|
logger.debug(`commitAndPush(${commit.branchName})`);
|
|
110
34
|
const existingChange = await client.getBranchChange(repository, {
|
|
@@ -113,8 +37,7 @@ var GerritScm = class extends DefaultGitScm {
|
|
|
113
37
|
targetBranch: commit.baseBranch,
|
|
114
38
|
requestDetails: ["CURRENT_REVISION"]
|
|
115
39
|
});
|
|
116
|
-
|
|
117
|
-
const message = typeof commit.message === "string" ? [commit.message] : commit.message;
|
|
40
|
+
const message = isString(commit.message) ? [commit.message] : commit.message;
|
|
118
41
|
// v8 ignore else -- TODO: add test #40625
|
|
119
42
|
if (commit.prTitle) {
|
|
120
43
|
const firstMessageLines = message[0].split("\n");
|
|
@@ -123,57 +46,41 @@ var GerritScm = class extends DefaultGitScm {
|
|
|
123
46
|
}
|
|
124
47
|
const changeId = existingChange?.change_id ?? generateChangeId();
|
|
125
48
|
commit.message = [...message, `Renovate-Branch: ${commit.branchName}\nChange-Id: ${changeId}`];
|
|
126
|
-
const commitResult = await prepareCommit(
|
|
127
|
-
...commit,
|
|
128
|
-
force: true
|
|
129
|
-
});
|
|
49
|
+
const commitResult = await prepareCommit(commit);
|
|
130
50
|
if (commitResult) {
|
|
131
51
|
const { commitSha } = commitResult;
|
|
132
52
|
if (existingChange) {
|
|
133
|
-
|
|
134
|
-
await
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
})) return commitSha;
|
|
53
|
+
/* v8 ignore else -- should never happen */
|
|
54
|
+
if (await pushForReview({
|
|
55
|
+
sourceRef: commit.branchName,
|
|
56
|
+
targetBranch: existingChange.branch,
|
|
57
|
+
files: commit.files,
|
|
58
|
+
autoApprove: commit.autoApprove
|
|
59
|
+
})) {
|
|
60
|
+
const currentRef = existingChange.revisions[existingChange.current_revision].ref;
|
|
61
|
+
await setVirtualBranch(commit.branchName, nextPatchSetRef(currentRef), commitSha);
|
|
62
|
+
return commitSha;
|
|
144
63
|
}
|
|
145
64
|
} else {
|
|
146
65
|
logger.debug(`Commit prepared, push deferred to createPr()`);
|
|
147
|
-
pendingChangeBranches.add(commit.branchName);
|
|
148
66
|
return commitSha;
|
|
149
67
|
}
|
|
150
68
|
}
|
|
151
69
|
return null;
|
|
152
70
|
}
|
|
153
|
-
async deleteBranch(branchName) {
|
|
154
|
-
pendingChangeBranches.delete(branchName);
|
|
155
|
-
await deleteBranch(branchName, { localBranch: true });
|
|
156
|
-
}
|
|
157
|
-
async mergeToLocal(branchName) {
|
|
158
|
-
if (pendingChangeBranches.has(branchName)) {
|
|
159
|
-
logger.debug(`Merging local branch ${branchName} (not yet pushed)`);
|
|
160
|
-
return mergeToLocal(branchName, { localBranch: true });
|
|
161
|
-
}
|
|
162
|
-
const searchConfig = {
|
|
163
|
-
state: "open",
|
|
164
|
-
branchName,
|
|
165
|
-
singleChange: true,
|
|
166
|
-
requestDetails: ["CURRENT_REVISION"]
|
|
167
|
-
};
|
|
168
|
-
const change = (await client.findChanges(repository, searchConfig)).pop();
|
|
169
|
-
if (change) {
|
|
170
|
-
const currentRevision = change.revisions[change.current_revision];
|
|
171
|
-
return super.mergeToLocal(currentRevision.ref);
|
|
172
|
-
}
|
|
173
|
-
return super.mergeToLocal(branchName);
|
|
174
|
-
}
|
|
175
71
|
};
|
|
176
72
|
/**
|
|
73
|
+
* Derive the next patch-set ref from a Gerrit change ref.
|
|
74
|
+
* Gerrit refs follow the pattern `refs/changes/<NN>/<change>/<patchset>`.
|
|
75
|
+
* After a push, Gerrit creates the next patch-set, so we increment the
|
|
76
|
+
* trailing number to keep the virtual branch in sync.
|
|
77
|
+
*/
|
|
78
|
+
function nextPatchSetRef(currentRef) {
|
|
79
|
+
const lastSlash = currentRef.lastIndexOf("/");
|
|
80
|
+
const patchSet = Number(currentRef.slice(lastSlash + 1));
|
|
81
|
+
return `${currentRef.slice(0, lastSlash + 1)}${patchSet + 1}`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
177
84
|
* This function should generate a Gerrit Change-ID analogous to the commit hook. We avoid the commit hook cause of security concerns.
|
|
178
85
|
* random=$( (whoami ; hostname ; date; cat $1 ; echo $RANDOM) | git hash-object --stdin) prefixed with an 'I'.
|
|
179
86
|
* TODO: Gerrit don't accept longer Change-IDs (sha256), but what happens with this https://git-scm.com/docs/hash-function-transition/ ?
|
|
@@ -182,6 +89,6 @@ function generateChangeId() {
|
|
|
182
89
|
return `I${hash(randomUUID(), "sha1")}`;
|
|
183
90
|
}
|
|
184
91
|
//#endregion
|
|
185
|
-
export { GerritScm, configureScm,
|
|
92
|
+
export { GerritScm, configureScm, nextPatchSetRef, pushForReview };
|
|
186
93
|
|
|
187
94
|
//# sourceMappingURL=scm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scm.js","names":["git.pushCommit","git.branchExists","git.getBranchCommit","git.getBranchUpdateDate","git.prepareCommit","git.fetchRevSpec","git.hasDiff","git.deleteBranch","git.mergeToLocal"],"sources":["../../../../lib/modules/platform/gerrit/scm.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { isNonEmptyArray } from '@sindresorhus/is';\nimport { DateTime } from 'luxon';\nimport { logger } from '../../../logger/index.ts';\nimport * as git from '../../../util/git/index.ts';\nimport type { CommitFilesConfig, FileChange } from '../../../util/git/types.ts';\nimport { hash } from '../../../util/hash.ts';\nimport type { LongCommitSha } from '../../../util/schema-utils/git.ts';\nimport { isLongCommitSha } from '../../../util/schema-utils/git.ts';\nimport { DefaultGitScm } from '../default-scm.ts';\nimport { client } from './client.ts';\nimport type { GerritFindPRConfig } from './types.ts';\nimport { convertGerritDateToISO } from './utils.ts';\n\nlet repository: string;\nlet username: string;\nexport function configureScm(repo: string, login: string): void {\n repository = repo;\n username = login;\n}\n\n/** Branches with a local commit but no Gerrit change yet (push deferred to createPr()). */\nexport const pendingChangeBranches = new Set<string>();\n\nexport async function pushForReview(options: {\n sourceRef: string;\n targetBranch: string;\n files: FileChange[];\n autoApprove?: boolean;\n labels?: string[];\n}): Promise<boolean> {\n const pushOptions = ['notify=NONE', 'ready'];\n if (options.autoApprove) {\n pushOptions.push('label=Code-Review+2');\n }\n if (isNonEmptyArray(options.labels)) {\n for (const label of options.labels) {\n pushOptions.push(`hashtag=${label}`);\n }\n }\n\n const result = await git.pushCommit({\n sourceRef: options.sourceRef,\n targetRef: `refs/for/${options.targetBranch}`,\n files: options.files,\n pushOptions,\n });\n if (result) {\n pendingChangeBranches.delete(options.sourceRef);\n }\n return result;\n}\n\nexport class GerritScm extends DefaultGitScm {\n override async branchExists(branchName: string): Promise<boolean> {\n const searchConfig: GerritFindPRConfig = {\n state: 'open',\n branchName,\n singleChange: true,\n };\n const change = (await client.findChanges(repository, searchConfig)).pop();\n if (change) {\n return true;\n }\n return git.branchExists(branchName);\n }\n\n override async getBranchCommit(\n branchName: string,\n ): Promise<LongCommitSha | null> {\n const searchConfig: GerritFindPRConfig = {\n state: 'open',\n branchName,\n singleChange: true,\n requestDetails: ['CURRENT_REVISION'],\n };\n const change = (await client.findChanges(repository, searchConfig)).pop();\n if (isLongCommitSha(change?.current_revision)) {\n return change.current_revision;\n }\n return git.getBranchCommit(branchName);\n }\n\n override async getBranchUpdateDate(\n branchName: string,\n ): Promise<DateTime | null> {\n const searchConfig: GerritFindPRConfig = {\n state: 'open',\n branchName,\n singleChange: true,\n refreshCache: true,\n requestDetails: ['CURRENT_REVISION'],\n };\n const change = (await client.findChanges(repository, searchConfig)).pop();\n if (change) {\n const date = convertGerritDateToISO(\n change.revisions![change.current_revision!].created,\n );\n return DateTime.fromISO(date).toUTC();\n }\n return git.getBranchUpdateDate(branchName);\n }\n\n override async isBranchBehindBase(\n branchName: string,\n baseBranch: string,\n ): Promise<boolean> {\n const searchConfig: GerritFindPRConfig = {\n state: 'open',\n branchName,\n targetBranch: baseBranch,\n singleChange: true,\n requestDetails: ['CURRENT_REVISION', 'CURRENT_ACTIONS'],\n };\n const change = (await client.findChanges(repository, searchConfig)).pop();\n if (change) {\n const currentRevision = change.revisions![change.current_revision!];\n return currentRevision.actions!.rebase.enabled === true;\n }\n return true;\n }\n\n override async isBranchConflicted(\n baseBranch: string,\n branch: string,\n ): Promise<boolean> {\n const searchConfig: GerritFindPRConfig = {\n state: 'open',\n branchName: branch,\n targetBranch: baseBranch,\n singleChange: true,\n };\n const change = (await client.findChanges(repository, searchConfig)).pop();\n if (change) {\n const mergeInfo = await client.getMergeableInfo(change);\n return !mergeInfo.mergeable;\n }\n logger.warn(\n { branch, baseBranch },\n 'There is no open change with this branch',\n );\n return true;\n }\n\n override async isBranchModified(\n branchName: string,\n baseBranch: string,\n ): Promise<boolean> {\n const searchConfig: GerritFindPRConfig = {\n state: 'open',\n branchName,\n targetBranch: baseBranch,\n singleChange: true,\n requestDetails: ['CURRENT_REVISION', 'DETAILED_ACCOUNTS'],\n };\n const change = (await client.findChanges(repository, searchConfig)).pop();\n if (change) {\n const currentRevision = change.revisions![change.current_revision!];\n return currentRevision.uploader.username !== username;\n }\n return false;\n }\n\n override async commitAndPush(\n commit: CommitFilesConfig,\n ): Promise<LongCommitSha | null> {\n logger.debug(`commitAndPush(${commit.branchName})`);\n const existingChange = await client.getBranchChange(repository, {\n branchName: commit.branchName,\n state: 'open',\n targetBranch: commit.baseBranch,\n requestDetails: ['CURRENT_REVISION'],\n });\n\n let hasChanges = true;\n const message =\n typeof commit.message === 'string' ? [commit.message] : commit.message;\n\n // In Gerrit, the change subject/title is the first line of the commit message\n // v8 ignore else -- TODO: add test #40625\n if (commit.prTitle) {\n const firstMessageLines = message[0].split('\\n');\n firstMessageLines[0] = commit.prTitle;\n message[0] = firstMessageLines.join('\\n');\n }\n\n const changeId = existingChange?.change_id ?? generateChangeId();\n commit.message = [\n ...message,\n `Renovate-Branch: ${commit.branchName}\\nChange-Id: ${changeId}`,\n ];\n const commitResult = await git.prepareCommit({ ...commit, force: true });\n if (commitResult) {\n const { commitSha } = commitResult;\n if (existingChange) {\n const currentRevision =\n existingChange.revisions![existingChange.current_revision!];\n const fetchRefSpec = currentRevision.ref;\n await git.fetchRevSpec(fetchRefSpec); // fetch current ChangeSet for git diff\n hasChanges = await git.hasDiff('HEAD', 'FETCH_HEAD'); // avoid pushing empty patch sets\n if (hasChanges || commit.force) {\n // Since the change already exists, we push to the same target branch to\n // avoid creating a new change if the base branch has changed.\n // updatePr() will later take care of moving the existing change to a\n // different base branch if needed.\n const pushResult = await pushForReview({\n sourceRef: commit.branchName,\n targetBranch: existingChange.branch,\n files: commit.files,\n autoApprove: commit.autoApprove,\n });\n /* v8 ignore else -- should never happen */\n if (pushResult) {\n return commitSha;\n }\n }\n } else {\n logger.debug(`Commit prepared, push deferred to createPr()`);\n pendingChangeBranches.add(commit.branchName);\n return commitSha;\n }\n }\n return null; // empty commit, no changes in this Gerrit Change\n }\n\n override async deleteBranch(branchName: string): Promise<void> {\n pendingChangeBranches.delete(branchName);\n await git.deleteBranch(branchName, { localBranch: true });\n }\n\n override async mergeToLocal(branchName: string): Promise<void> {\n // Unpushed branches can't be fetched from origin, merge locally instead\n if (pendingChangeBranches.has(branchName)) {\n logger.debug(`Merging local branch ${branchName} (not yet pushed)`);\n return git.mergeToLocal(branchName, { localBranch: true });\n }\n\n const searchConfig: GerritFindPRConfig = {\n state: 'open',\n branchName,\n singleChange: true,\n requestDetails: ['CURRENT_REVISION'],\n };\n const change = (await client.findChanges(repository, searchConfig)).pop();\n if (change) {\n const currentRevision = change.revisions![change.current_revision!];\n return super.mergeToLocal(currentRevision.ref);\n }\n return super.mergeToLocal(branchName);\n }\n}\n\n/**\n * This function should generate a Gerrit Change-ID analogous to the commit hook. We avoid the commit hook cause of security concerns.\n * random=$( (whoami ; hostname ; date; cat $1 ; echo $RANDOM) | git hash-object --stdin) prefixed with an 'I'.\n * TODO: Gerrit don't accept longer Change-IDs (sha256), but what happens with this https://git-scm.com/docs/hash-function-transition/ ?\n */\nfunction generateChangeId(): string {\n return `I${hash(randomUUID(), 'sha1')}`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"scm.js","names":["git.pushCommit","git.prepareCommit","git.setVirtualBranch"],"sources":["../../../../lib/modules/platform/gerrit/scm.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { isNonEmptyArray, isString } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport * as git from '../../../util/git/index.ts';\nimport type { CommitFilesConfig, FileChange } from '../../../util/git/types.ts';\nimport { hash } from '../../../util/hash.ts';\nimport type { LongCommitSha } from '../../../util/schema-utils/git.ts';\nimport { DefaultGitScm } from '../default-scm.ts';\nimport { client } from './client.ts';\n\n/**\n * Gerrit SCM strategy:\n * Instead of implementing custom branch operations, we fetch all open Gerrit changes\n * as virtual branches (refs/remotes/origin/<branchName>) after repository initialization.\n * This allows us to leverage DefaultGitScm for most operations, treating virtual branches\n * as regular Git branches, while minimizing Gerrit API requests.\n */\n\nlet repository: string;\nexport function configureScm(repo: string): void {\n repository = repo;\n}\n\nexport async function pushForReview(options: {\n sourceRef: string;\n targetBranch: string;\n files: FileChange[];\n autoApprove?: boolean;\n labels?: string[];\n}): Promise<boolean> {\n const pushOptions = ['notify=NONE', 'ready'];\n if (options.autoApprove) {\n pushOptions.push('label=Code-Review+2');\n }\n if (isNonEmptyArray(options.labels)) {\n for (const label of options.labels) {\n pushOptions.push(`hashtag=${label}`);\n }\n }\n\n return git.pushCommit({\n sourceRef: options.sourceRef,\n targetRef: `refs/for/${options.targetBranch}`,\n files: options.files,\n pushOptions,\n });\n}\n\nexport class GerritScm extends DefaultGitScm {\n override async commitAndPush(\n commit: CommitFilesConfig,\n ): Promise<LongCommitSha | null> {\n logger.debug(`commitAndPush(${commit.branchName})`);\n\n const existingChange = await client.getBranchChange(repository, {\n branchName: commit.branchName,\n state: 'open',\n targetBranch: commit.baseBranch,\n requestDetails: ['CURRENT_REVISION'],\n });\n\n const message = isString(commit.message)\n ? [commit.message]\n : commit.message;\n\n // In Gerrit, the change subject/title is the first line of the commit message\n // v8 ignore else -- TODO: add test #40625\n if (commit.prTitle) {\n const firstMessageLines = message[0].split('\\n');\n firstMessageLines[0] = commit.prTitle;\n message[0] = firstMessageLines.join('\\n');\n }\n\n const changeId = existingChange?.change_id ?? generateChangeId();\n commit.message = [\n ...message,\n `Renovate-Branch: ${commit.branchName}\\nChange-Id: ${changeId}`,\n ];\n // prepareCommit already checks hasDiff('HEAD', 'origin/<branchName>') when\n // force is not set, which works because virtual branches are fetched as\n // refs/remotes/origin/<branchName> during init. This avoids pushing empty\n // patch sets without a separate diff check.\n const commitResult = await git.prepareCommit(commit);\n if (commitResult) {\n const { commitSha } = commitResult;\n if (existingChange) {\n // Since the change already exists, we push to the same target branch to\n // avoid creating a new change if the base branch has changed.\n // updatePr() will later take care of moving the existing change to a\n // different base branch if needed.\n const pushResult = await pushForReview({\n sourceRef: commit.branchName,\n targetBranch: existingChange.branch,\n files: commit.files,\n autoApprove: commit.autoApprove,\n });\n /* v8 ignore else -- should never happen */\n if (pushResult) {\n const currentRef =\n existingChange.revisions![existingChange.current_revision!].ref;\n await git.setVirtualBranch(\n commit.branchName,\n nextPatchSetRef(currentRef),\n commitSha,\n );\n return commitSha;\n }\n } else {\n logger.debug(`Commit prepared, push deferred to createPr()`);\n return commitSha;\n }\n }\n return null; // empty commit, no changes in this Gerrit Change\n }\n}\n\n/**\n * Derive the next patch-set ref from a Gerrit change ref.\n * Gerrit refs follow the pattern `refs/changes/<NN>/<change>/<patchset>`.\n * After a push, Gerrit creates the next patch-set, so we increment the\n * trailing number to keep the virtual branch in sync.\n */\nexport function nextPatchSetRef(currentRef: string): string {\n const lastSlash = currentRef.lastIndexOf('/');\n const patchSet = Number(currentRef.slice(lastSlash + 1));\n return `${currentRef.slice(0, lastSlash + 1)}${patchSet + 1}`;\n}\n\n/**\n * This function should generate a Gerrit Change-ID analogous to the commit hook. We avoid the commit hook cause of security concerns.\n * random=$( (whoami ; hostname ; date; cat $1 ; echo $RANDOM) | git hash-object --stdin) prefixed with an 'I'.\n * TODO: Gerrit don't accept longer Change-IDs (sha256), but what happens with this https://git-scm.com/docs/hash-function-transition/ ?\n */\nfunction generateChangeId(): string {\n return `I${hash(randomUUID(), 'sha1')}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,IAAI;AACJ,SAAgB,aAAa,MAAoB;CAC/C,aAAa;AACf;AAEA,eAAsB,cAAc,SAMf;CACnB,MAAM,cAAc,CAAC,eAAe,OAAO;CAC3C,IAAI,QAAQ,aACV,YAAY,KAAK,qBAAqB;CAExC,IAAI,gBAAgB,QAAQ,MAAM,GAChC,KAAK,MAAM,SAAS,QAAQ,QAC1B,YAAY,KAAK,WAAW,OAAO;CAIvC,OAAOA,WAAe;EACpB,WAAW,QAAQ;EACnB,WAAW,YAAY,QAAQ;EAC/B,OAAO,QAAQ;EACf;CACF,CAAC;AACH;AAEA,IAAa,YAAb,cAA+B,cAAc;CAC3C,MAAe,cACb,QAC+B;EAC/B,OAAO,MAAM,iBAAiB,OAAO,WAAW,EAAE;EAElD,MAAM,iBAAiB,MAAM,OAAO,gBAAgB,YAAY;GAC9D,YAAY,OAAO;GACnB,OAAO;GACP,cAAc,OAAO;GACrB,gBAAgB,CAAC,kBAAkB;EACrC,CAAC;EAED,MAAM,UAAU,SAAS,OAAO,OAAO,IACnC,CAAC,OAAO,OAAO,IACf,OAAO;;EAIX,IAAI,OAAO,SAAS;GAClB,MAAM,oBAAoB,QAAQ,EAAE,CAAC,MAAM,IAAI;GAC/C,kBAAkB,KAAK,OAAO;GAC9B,QAAQ,KAAK,kBAAkB,KAAK,IAAI;EAC1C;EAEA,MAAM,WAAW,gBAAgB,aAAa,iBAAiB;EAC/D,OAAO,UAAU,CACf,GAAG,SACH,oBAAoB,OAAO,WAAW,eAAe,UACvD;EAKA,MAAM,eAAe,MAAMC,cAAkB,MAAM;EACnD,IAAI,cAAc;GAChB,MAAM,EAAE,cAAc;GACtB,IAAI;;QAYE,MAPqB,cAAc;KACrC,WAAW,OAAO;KAClB,cAAc,eAAe;KAC7B,OAAO,OAAO;KACd,aAAa,OAAO;IACtB,CAAC,GAEe;KACd,MAAM,aACJ,eAAe,UAAW,eAAe,iBAAkB,CAAC;KAC9D,MAAMC,iBACJ,OAAO,YACP,gBAAgB,UAAU,GAC1B,SACF;KACA,OAAO;IACT;UACK;IACL,OAAO,MAAM,8CAA8C;IAC3D,OAAO;GACT;EACF;EACA,OAAO;CACT;AACF;;;;;;;AAQA,SAAgB,gBAAgB,YAA4B;CAC1D,MAAM,YAAY,WAAW,YAAY,GAAG;CAC5C,MAAM,WAAW,OAAO,WAAW,MAAM,YAAY,CAAC,CAAC;CACvD,OAAO,GAAG,WAAW,MAAM,GAAG,YAAY,CAAC,IAAI,WAAW;AAC5D;;;;;;AAOA,SAAS,mBAA2B;CAClC,OAAO,IAAI,KAAK,WAAW,GAAG,MAAM;AACtC"}
|
package/dist/util/git/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ declare function createSimpleGit({ config, env }?: {
|
|
|
16
16
|
declare function gitRetry<T>(gitFunc: () => Promise<T>): Promise<T>;
|
|
17
17
|
declare const GIT_MINIMUM_VERSION = "2.33.0";
|
|
18
18
|
declare function validateGitVersion(): Promise<boolean>;
|
|
19
|
-
declare function fetchRevSpec(revSpec: string): Promise<void>;
|
|
19
|
+
declare function fetchRevSpec(...revSpec: string[]): Promise<void>;
|
|
20
20
|
declare function initRepo(args: StorageConfig): Promise<void>;
|
|
21
21
|
declare function resetToCommit(commit: LongCommitSha): Promise<void>;
|
|
22
22
|
declare function setGitAuthor(gitAuthor: string | undefined): void;
|
|
@@ -34,6 +34,22 @@ declare function getBranchUpdateDate(branchName: string): Promise<DateTime | nul
|
|
|
34
34
|
declare function getCommitMessages(): Promise<string[]>;
|
|
35
35
|
declare function checkoutBranch(branchName: string): Promise<LongCommitSha>;
|
|
36
36
|
declare function checkoutBranchFromRemote(branchName: string, remoteName: string): Promise<LongCommitSha>;
|
|
37
|
+
/**
|
|
38
|
+
* Returns the remote-tracking ref path for a virtual branch.
|
|
39
|
+
*/
|
|
40
|
+
declare function remoteBranchRef(branchName: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Set a virtual branch's remote-tracking ref and add it to the
|
|
43
|
+
* virtual-branch registry (config.virtualBranches).
|
|
44
|
+
*
|
|
45
|
+
* Used after pushing (to keep tracking in sync with the remote) and in
|
|
46
|
+
* createPr() when the Gerrit change ref becomes available.
|
|
47
|
+
*
|
|
48
|
+
* @param branchName Virtual branch name to set
|
|
49
|
+
* @param ref The ref this virtual branch is fetched from (e.g., 'refs/changes/34/1234/1')
|
|
50
|
+
* @param commitSha The commit SHA the virtual branch points to.
|
|
51
|
+
*/
|
|
52
|
+
declare function setVirtualBranch(branchName: string, ref: string, commitSha: LongCommitSha): Promise<void>;
|
|
37
53
|
declare function resetHardFromRemote(remoteAndBranch: string): Promise<void>;
|
|
38
54
|
declare function forcePushToRemote(branchName: string, remote: string): Promise<void>;
|
|
39
55
|
declare function getFileList(): Promise<string[]>;
|
|
@@ -41,12 +57,8 @@ declare function getBranchList(): string[];
|
|
|
41
57
|
declare function isBranchBehindBase(branchName: string, baseBranch: string): Promise<boolean>;
|
|
42
58
|
declare function isBranchModified(branchName: string, baseBranch: string): Promise<boolean>;
|
|
43
59
|
declare function isBranchConflicted(baseBranch: string, branch: string): Promise<boolean>;
|
|
44
|
-
declare function deleteBranch(branchName: string
|
|
45
|
-
|
|
46
|
-
}): Promise<void>;
|
|
47
|
-
declare function mergeToLocal(refSpecToMerge: string, options?: {
|
|
48
|
-
localBranch?: boolean;
|
|
49
|
-
}): Promise<void>;
|
|
60
|
+
declare function deleteBranch(branchName: string): Promise<void>;
|
|
61
|
+
declare function mergeToLocal(branchName: string): Promise<void>;
|
|
50
62
|
declare function mergeBranch(branchName: string): Promise<void>;
|
|
51
63
|
declare function getBranchLastCommitTime(branchName: string): Promise<Date>;
|
|
52
64
|
declare function getBranchFiles(branchName: string): Promise<string[] | null>;
|
|
@@ -136,5 +148,5 @@ declare function diffCommitTree(parentCommitSha: LongCommitSha, commitSha: LongC
|
|
|
136
148
|
declare function syncForkWithUpstream(branchName: string): Promise<void>;
|
|
137
149
|
declare function getRemotes(): Promise<string[]>;
|
|
138
150
|
//#endregion
|
|
139
|
-
export { GIT_MINIMUM_VERSION, RENOVATE_FORK_UPSTREAM, branchExists, checkoutBranch, checkoutBranchFromRemote, clearRenovateRefs, cloneSubmodules, commitFiles, createSimpleGit, deleteBranch, diffCommitTree, fetchBranch, fetchRevSpec, forcePushToRemote, getBranchCommit, getBranchFiles, getBranchFilesFromCommit, getBranchLastCommitTime, getBranchList, getBranchUpdateDate, getCommitMessages, getCommitTreeSha, getFile, getFileList, getFiles, getRemotes, getRepoStatus, getSubmodules, getUrl, gitRetry, hasDiff, initRepo, isBranchBehindBase, isBranchConflicted, isBranchModified, isCloned, isFileModeEnabled, mergeBranch, mergeToLocal, prepareCommit, pushCommit, pushCommitToRenovateRef, resetHardFromRemote, resetToCommit, setGitAuthor, setNoVerify, setPrivateKey, setUserRepoConfig, syncForkWithUpstream, syncGit, validateGitVersion, writeGitAuthor };
|
|
151
|
+
export { GIT_MINIMUM_VERSION, RENOVATE_FORK_UPSTREAM, branchExists, checkoutBranch, checkoutBranchFromRemote, clearRenovateRefs, cloneSubmodules, commitFiles, createSimpleGit, deleteBranch, diffCommitTree, fetchBranch, fetchRevSpec, forcePushToRemote, getBranchCommit, getBranchFiles, getBranchFilesFromCommit, getBranchLastCommitTime, getBranchList, getBranchUpdateDate, getCommitMessages, getCommitTreeSha, getFile, getFileList, getFiles, getRemotes, getRepoStatus, getSubmodules, getUrl, gitRetry, hasDiff, initRepo, isBranchBehindBase, isBranchConflicted, isBranchModified, isCloned, isFileModeEnabled, mergeBranch, mergeToLocal, prepareCommit, pushCommit, pushCommitToRenovateRef, remoteBranchRef, resetHardFromRemote, resetToCommit, setGitAuthor, setNoVerify, setPrivateKey, setUserRepoConfig, setVirtualBranch, syncForkWithUpstream, syncGit, validateGitVersion, writeGitAuthor };
|
|
140
152
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/util/git/index.js
CHANGED
|
@@ -161,6 +161,7 @@ async function fetchBranchCommits(preferUpstream = true) {
|
|
|
161
161
|
lsRemoteRes.split(newlineRegex).filter(Boolean).map((line) => line.trim().split(regEx(/\s+/))).forEach(([sha, ref]) => {
|
|
162
162
|
config.branchCommits[ref.replace("refs/heads/", "")] = toLongCommitSha(sha);
|
|
163
163
|
});
|
|
164
|
+
if (isNonEmptyObject(config.virtualBranches)) for (const [name, branch] of Object.entries(config.virtualBranches)) config.branchCommits[name] = branch.sha;
|
|
164
165
|
logger.trace({ branchCommits: config.branchCommits }, "branch commits");
|
|
165
166
|
} catch (err) /* v8 ignore next -- TODO: add test #40625 */ {
|
|
166
167
|
const errChecked = checkForPlatformFailure(err);
|
|
@@ -170,14 +171,15 @@ async function fetchBranchCommits(preferUpstream = true) {
|
|
|
170
171
|
throw err;
|
|
171
172
|
}
|
|
172
173
|
}
|
|
173
|
-
async function fetchRevSpec(revSpec) {
|
|
174
|
-
await gitRetry(() => git.fetch(["origin", revSpec]));
|
|
174
|
+
async function fetchRevSpec(...revSpec) {
|
|
175
|
+
await gitRetry(() => git.fetch(["origin", ...revSpec]));
|
|
175
176
|
}
|
|
176
177
|
async function initRepo(args) {
|
|
177
178
|
config = { ...args };
|
|
178
179
|
config.ignoredAuthors = [];
|
|
179
180
|
config.additionalBranches = [];
|
|
180
181
|
config.branchIsModified = {};
|
|
182
|
+
config.virtualBranches ??= {};
|
|
181
183
|
git = instrumentGit(createSimpleGit({ config: { baseDir: GlobalConfig.get("localDir") } }));
|
|
182
184
|
gitInitialized = false;
|
|
183
185
|
submodulesInitizialized = false;
|
|
@@ -405,6 +407,13 @@ const syncGit = withInstrumenting({ name: "syncGit" }, async () => {
|
|
|
405
407
|
await fetchBranchCommits(false);
|
|
406
408
|
});
|
|
407
409
|
}
|
|
410
|
+
if (isNonEmptyObject(config.virtualBranches)) {
|
|
411
|
+
const virtualBranches = config.virtualBranches;
|
|
412
|
+
await instrument("fetch virtual branches", async () => {
|
|
413
|
+
await fetchRevSpec(...Object.entries(virtualBranches).map(([name, branch]) => `${branch.ref}:${remoteBranchRef(name)}`));
|
|
414
|
+
logger.debug(`Fetched ${Object.keys(virtualBranches).length} virtual branches`);
|
|
415
|
+
});
|
|
416
|
+
}
|
|
408
417
|
config.currentBranchSha = toLongCommitSha((await git.revparse("HEAD")).trim());
|
|
409
418
|
logger.debug(`Current branch SHA: ${config.currentBranchSha}`);
|
|
410
419
|
});
|
|
@@ -520,6 +529,47 @@ async function checkoutBranchFromRemote(branchName, remoteName) {
|
|
|
520
529
|
throw err;
|
|
521
530
|
}
|
|
522
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* Returns the remote-tracking ref path for a virtual branch.
|
|
534
|
+
*/
|
|
535
|
+
function remoteBranchRef(branchName) {
|
|
536
|
+
return `refs/remotes/origin/${branchName}`;
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Returns whether the given branch is tracked as a virtual branch.
|
|
540
|
+
*/
|
|
541
|
+
function isVirtualBranch(branchName) {
|
|
542
|
+
return branchName in config.virtualBranches;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Set a virtual branch's remote-tracking ref and add it to the
|
|
546
|
+
* virtual-branch registry (config.virtualBranches).
|
|
547
|
+
*
|
|
548
|
+
* Used after pushing (to keep tracking in sync with the remote) and in
|
|
549
|
+
* createPr() when the Gerrit change ref becomes available.
|
|
550
|
+
*
|
|
551
|
+
* @param branchName Virtual branch name to set
|
|
552
|
+
* @param ref The ref this virtual branch is fetched from (e.g., 'refs/changes/34/1234/1')
|
|
553
|
+
* @param commitSha The commit SHA the virtual branch points to.
|
|
554
|
+
*/
|
|
555
|
+
async function setVirtualBranch(branchName, ref, commitSha) {
|
|
556
|
+
logger.debug({
|
|
557
|
+
branchName,
|
|
558
|
+
ref,
|
|
559
|
+
commitSha
|
|
560
|
+
}, "setVirtualBranch()");
|
|
561
|
+
await git.raw([
|
|
562
|
+
"update-ref",
|
|
563
|
+
remoteBranchRef(branchName),
|
|
564
|
+
commitSha
|
|
565
|
+
]);
|
|
566
|
+
config.branchCommits[branchName] = commitSha;
|
|
567
|
+
config.virtualBranches[branchName] = {
|
|
568
|
+
ref,
|
|
569
|
+
sha: commitSha
|
|
570
|
+
};
|
|
571
|
+
config.branchIsModified[branchName] = false;
|
|
572
|
+
}
|
|
523
573
|
async function resetHardFromRemote(remoteAndBranch) {
|
|
524
574
|
try {
|
|
525
575
|
const resetLog = await git.reset(["--hard", remoteAndBranch]);
|
|
@@ -708,9 +758,21 @@ async function isBranchConflicted(baseBranch, branch) {
|
|
|
708
758
|
logger.debug(`branch.isConflicted(): ${result}`);
|
|
709
759
|
return result;
|
|
710
760
|
}
|
|
711
|
-
async function deleteBranch(branchName
|
|
761
|
+
async function deleteBranch(branchName) {
|
|
712
762
|
await syncGit();
|
|
713
|
-
if (
|
|
763
|
+
if (isVirtualBranch(branchName)) {
|
|
764
|
+
const ref = remoteBranchRef(branchName);
|
|
765
|
+
logger.debug({
|
|
766
|
+
branchName,
|
|
767
|
+
ref
|
|
768
|
+
}, "Deleting virtual branch");
|
|
769
|
+
await git.raw([
|
|
770
|
+
"update-ref",
|
|
771
|
+
"-d",
|
|
772
|
+
ref
|
|
773
|
+
]);
|
|
774
|
+
delete config.virtualBranches[branchName];
|
|
775
|
+
} else try {
|
|
714
776
|
const deleteCommand = [
|
|
715
777
|
"push",
|
|
716
778
|
"--delete",
|
|
@@ -738,7 +800,7 @@ async function deleteBranch(branchName, options) {
|
|
|
738
800
|
}
|
|
739
801
|
delete config.branchCommits[branchName];
|
|
740
802
|
}
|
|
741
|
-
async function mergeToLocal(
|
|
803
|
+
async function mergeToLocal(branchName) {
|
|
742
804
|
let status;
|
|
743
805
|
try {
|
|
744
806
|
await syncGit();
|
|
@@ -750,16 +812,22 @@ async function mergeToLocal(refSpecToMerge, options) {
|
|
|
750
812
|
`origin/${config.currentBranch}`
|
|
751
813
|
]));
|
|
752
814
|
status = await git.status();
|
|
753
|
-
if (
|
|
754
|
-
|
|
755
|
-
|
|
815
|
+
if (isVirtualBranch(branchName)) {
|
|
816
|
+
const ref = remoteBranchRef(branchName);
|
|
817
|
+
logger.debug({
|
|
818
|
+
branchName,
|
|
819
|
+
ref
|
|
820
|
+
}, "mergeToLocal(): merging virtual branch");
|
|
821
|
+
await git.merge([ref]);
|
|
822
|
+
} else {
|
|
823
|
+
await fetchRevSpec(branchName);
|
|
756
824
|
await gitRetry(() => git.merge(["FETCH_HEAD"]));
|
|
757
825
|
}
|
|
758
826
|
} catch (err) {
|
|
759
827
|
logger.debug({
|
|
760
828
|
baseBranch: config.currentBranch,
|
|
761
829
|
baseSha: config.currentBranchSha,
|
|
762
|
-
|
|
830
|
+
branchName,
|
|
763
831
|
status,
|
|
764
832
|
err
|
|
765
833
|
}, "mergeLocally error");
|
|
@@ -1002,7 +1070,7 @@ async function fetchBranch(branchName) {
|
|
|
1002
1070
|
await syncGit();
|
|
1003
1071
|
logger.debug(`Fetching branch ${branchName}`);
|
|
1004
1072
|
try {
|
|
1005
|
-
const ref = `refs/heads/${branchName}
|
|
1073
|
+
const ref = `refs/heads/${branchName}:${remoteBranchRef(branchName)}`;
|
|
1006
1074
|
await gitRetry(() => git.pull([
|
|
1007
1075
|
"origin",
|
|
1008
1076
|
ref,
|
|
@@ -1254,6 +1322,6 @@ async function getRemotes() {
|
|
|
1254
1322
|
}
|
|
1255
1323
|
}
|
|
1256
1324
|
//#endregion
|
|
1257
|
-
export { GIT_MINIMUM_VERSION, RENOVATE_FORK_UPSTREAM, branchExists, checkoutBranch, checkoutBranchFromRemote, clearRenovateRefs, cloneSubmodules, commitFiles, createSimpleGit, deleteBranch, diffCommitTree, fetchBranch, fetchRevSpec, forcePushToRemote, getBranchCommit, getBranchFiles, getBranchFilesFromCommit, getBranchLastCommitTime, getBranchList, getBranchUpdateDate, getCommitMessages, getCommitTreeSha, getFile, getFileList, getFiles, getRemotes, getRepoStatus, getSubmodules, getUrl, gitRetry, hasDiff, initRepo, isBranchBehindBase, isBranchConflicted, isBranchModified, isCloned, isFileModeEnabled, mergeBranch, mergeToLocal, prepareCommit, pushCommit, pushCommitToRenovateRef, resetHardFromRemote, resetToCommit, setGitAuthor, setNoVerify, setPrivateKey, setUserRepoConfig, syncForkWithUpstream, syncGit, validateGitVersion, writeGitAuthor };
|
|
1325
|
+
export { GIT_MINIMUM_VERSION, RENOVATE_FORK_UPSTREAM, branchExists, checkoutBranch, checkoutBranchFromRemote, clearRenovateRefs, cloneSubmodules, commitFiles, createSimpleGit, deleteBranch, diffCommitTree, fetchBranch, fetchRevSpec, forcePushToRemote, getBranchCommit, getBranchFiles, getBranchFilesFromCommit, getBranchLastCommitTime, getBranchList, getBranchUpdateDate, getCommitMessages, getCommitTreeSha, getFile, getFileList, getFiles, getRemotes, getRepoStatus, getSubmodules, getUrl, gitRetry, hasDiff, initRepo, isBranchBehindBase, isBranchConflicted, isBranchModified, isCloned, isFileModeEnabled, mergeBranch, mergeToLocal, prepareCommit, pushCommit, pushCommitToRenovateRef, remoteBranchRef, resetHardFromRemote, resetToCommit, setGitAuthor, setNoVerify, setPrivateKey, setUserRepoConfig, setVirtualBranch, syncForkWithUpstream, syncGit, validateGitVersion, writeGitAuthor };
|
|
1258
1326
|
|
|
1259
1327
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../lib/util/git/index.ts"],"sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport URL from 'node:url';\nimport { isBoolean, isNonEmptyObject, isString } from '@sindresorhus/is';\nimport fs from 'fs-extra';\nimport { DateTime } from 'luxon';\nimport semver from 'semver';\nimport type {\n Options,\n SimpleGit,\n SimpleGitOptions,\n TaskOptions,\n} from 'simple-git';\nimport { ResetMode, simpleGit } from 'simple-git';\nimport upath from 'upath';\nimport { getConfigFileNames } from '../../config/app-strings.ts';\nimport { GlobalConfig } from '../../config/global.ts';\nimport type { RenovateConfig } from '../../config/types.ts';\nimport {\n CONFIG_VALIDATION,\n INVALID_PATH,\n REPOSITORY_CHANGED,\n REPOSITORY_DISABLED,\n REPOSITORY_EMPTY,\n SYSTEM_INSUFFICIENT_DISK_SPACE,\n TEMPORARY_ERROR,\n UNKNOWN_ERROR,\n} from '../../constants/error-messages.ts';\nimport { instrument } from '../../instrumentation/index.ts';\nimport { withInstrumenting } from '../../instrumentation/with-instrumenting.ts';\nimport { logger } from '../../logger/index.ts';\nimport { ExternalHostError } from '../../types/errors/external-host-error.ts';\nimport type { GitProtocol } from '../../types/git.ts';\nimport { incCountValue, incLimitedValue } from '../../workers/global/limits.ts';\nimport { getCache } from '../cache/repository/index.ts';\nimport { getEnv } from '../env.ts';\nimport type { ExtraEnv } from '../exec/types.ts';\nimport { getChildEnv } from '../exec/utils.ts';\nimport { newlineRegex, regEx } from '../regex.ts';\nimport type { LongCommitSha } from '../schema-utils/git.ts';\nimport { toLongCommitSha } from '../schema-utils/git.ts';\nimport { matchRegexOrGlobList } from '../string-match.ts';\nimport { logWarningIfUnicodeHiddenCharactersInPackageFile } from '../unicode.ts';\nimport { getGitEnvironmentVariables } from './auth.ts';\nimport { parseGitAuthor } from './author.ts';\nimport {\n getCachedBehindBaseResult,\n setCachedBehindBaseResult,\n} from './behind-base-branch-cache.ts';\nimport { getNoVerify, simpleGitConfig } from './config.ts';\nimport {\n getCachedConflictResult,\n setCachedConflictResult,\n} from './conflicts-cache.ts';\nimport {\n bulkChangesDisallowed,\n checkForPlatformFailure,\n handleCommitError,\n} from './error.ts';\nimport type { InstrumentedSimpleGit } from './instrument.ts';\nimport { instrumentGit } from './instrument.ts';\nimport {\n getCachedModifiedResult,\n setCachedModifiedResult,\n} from './modified-cache.ts';\nimport { configSigningKey, writePrivateKey } from './private-key.ts';\nimport type {\n CommitFilesConfig,\n CommitResult,\n DiffTreeItem,\n GitObjectType,\n LocalConfig,\n PushFilesConfig,\n StatusResult,\n StorageConfig,\n} from './types.ts';\nimport { GitTreeMode } from './types.ts';\nimport {\n getCachedUpdateDateResult,\n setCachedUpdateDateResult,\n} from './update-date-cache.ts';\n\nexport { setNoVerify } from './config.ts';\nexport { setPrivateKey } from './private-key.ts';\n\n// Retry parameters\nconst retryCount = 5;\nconst delaySeconds = 3;\nconst delayFactor = 2;\n\nexport const RENOVATE_FORK_UPSTREAM = 'renovate-fork-upstream';\n\nexport function createSimpleGit({\n config,\n env,\n}: {\n config?: Partial<SimpleGitOptions>;\n env?: ExtraEnv;\n} = {}): SimpleGit {\n return simpleGit({ ...simpleGitConfig(), ...config }).env(\n getChildEnv({\n extraEnv: {\n // Git will prompt for known hosts or passwords, unless we activate BatchMode.\n // Set as extraEnv (lowest priority) so that process.env and\n // customEnvVariables can override it.\n GIT_SSH_COMMAND: 'ssh -o BatchMode=yes',\n },\n env: {\n ...env,\n // To ensure the simple-git parsers match correctly, we need\n // to set the `LANG` and `LC_ALL` environment variables to\n // the `C.UTF-8` locale. See the docs for more details:\n // https://github.com/steveukx/git-js/blob/1bb14df0595794a9353d28ccdaeeb06c0b9bf2a5/docs/NON_ENGLISH_LOCALE.md\n //\n // Use \"C.UTF-8\" instead of just \"C\" (as specified in docs) to handle special characters:\n // https://github.com/renovatebot/renovate/pull/18963\n LANG: 'C.UTF-8',\n LC_ALL: 'C.UTF-8',\n },\n }),\n );\n}\n\n// A generic wrapper for simpleGit.* calls to make them more fault-tolerant\nexport async function gitRetry<T>(gitFunc: () => Promise<T>): Promise<T> {\n let round = 0;\n let lastError: Error | undefined;\n\n while (round <= retryCount) {\n if (round > 0) {\n logger.debug(`gitRetry round ${round}`);\n }\n try {\n const res = await gitFunc();\n if (round > 1) {\n logger.debug('Successful retry of git function');\n }\n return res;\n } catch (err) {\n lastError = err;\n logger.debug({ err }, `Git function thrown`);\n // Try to transform the Error to ExternalHostError\n const errChecked = checkForPlatformFailure(err);\n if (errChecked instanceof ExternalHostError) {\n logger.debug(\n { err: errChecked },\n `ExternalHostError thrown in round ${\n round + 1\n } of ${retryCount} - retrying in the next round`,\n );\n } else {\n throw err;\n }\n }\n\n const nextDelay = delayFactor ^ ((round - 1) * delaySeconds);\n logger.trace({ nextDelay }, `Delay next round`);\n await setTimeout(1000 * nextDelay);\n\n round++;\n }\n\n throw lastError!;\n}\n\nasync function isDirectory(dir: string): Promise<boolean> {\n try {\n return (await fs.stat(dir)).isDirectory();\n } catch {\n return false;\n }\n}\n\nasync function getDefaultBranch(git: InstrumentedSimpleGit): Promise<string> {\n logger.debug('getDefaultBranch()');\n // see https://stackoverflow.com/a/62352647/3005034\n try {\n let res = await git.raw(['rev-parse', '--abbrev-ref', 'origin/HEAD']);\n /* v8 ignore next -- TODO: add test #40625 */\n if (!res) {\n logger.debug('Could not determine default branch using git rev-parse');\n const headPrefix = 'HEAD branch: ';\n res = (await git.raw(['remote', 'show', 'origin']))\n .split('\\n')\n .map((line) => line.trim())\n .find((line) => line.startsWith(headPrefix))!\n .replace(headPrefix, '');\n }\n\n return res.replace('origin/', '').trim();\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.debug({ err }, 'Error getting default branch');\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n if (\n err.message.startsWith(\n 'fatal: ref refs/remotes/origin/HEAD is not a symbolic ref',\n )\n ) {\n throw new Error(REPOSITORY_EMPTY);\n }\n if (err.message.includes(\"fatal: ambiguous argument 'origin/HEAD'\")) {\n logger.warn('Error getting default branch');\n throw new Error(TEMPORARY_ERROR);\n }\n throw err;\n }\n}\n\nlet config: LocalConfig = {} as any;\n\n// TODO: can be undefined\nlet git: InstrumentedSimpleGit;\nlet gitInitialized: boolean;\nlet submodulesInitizialized: boolean;\n\nlet privateKeySet = false;\n\nexport const GIT_MINIMUM_VERSION = '2.33.0'; // git show-current\n\nexport async function validateGitVersion(): Promise<boolean> {\n let version: string | undefined;\n const globalGit = instrumentGit(createSimpleGit());\n try {\n const { major, minor, patch, installed } = await globalGit.version();\n /* v8 ignore if -- TODO: add test #40625 */\n if (!installed) {\n logger.error('Git not installed');\n return false;\n }\n version = `${major}.${minor}.${patch}`;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.error({ err }, 'Error fetching git version');\n return false;\n }\n /* v8 ignore if -- TODO: add test #40625 */\n if (!(version && semver.gte(version, GIT_MINIMUM_VERSION))) {\n logger.error(\n { detectedVersion: version, minimumVersion: GIT_MINIMUM_VERSION },\n 'Git version needs upgrading',\n );\n return false;\n }\n logger.debug(`Found valid git version: ${version}`);\n return true;\n}\n\nasync function fetchBranchCommits(preferUpstream = true): Promise<void> {\n config.branchCommits = {};\n const url =\n preferUpstream && config.upstreamUrl ? config.upstreamUrl : config.url;\n logger.debug(`fetchBranchCommits(): url=${url}`);\n const opts = ['ls-remote', '--heads', url];\n const localDir = GlobalConfig.get('localDir');\n const repoExists = await fs.pathExists(upath.join(localDir, '.git/HEAD'));\n if (config.extraCloneOpts && !repoExists) {\n Object.entries(config.extraCloneOpts).forEach((e) =>\n // TODO: types (#22198)\n opts.unshift(e[0], `${e[1]!}`),\n );\n }\n try {\n const lsRemoteRes = await gitRetry(() => git.raw(opts));\n logger.trace({ lsRemoteRes }, 'git ls-remote result');\n lsRemoteRes\n .split(newlineRegex)\n .filter(Boolean)\n .map((line) => line.trim().split(regEx(/\\s+/)))\n .forEach(([sha, ref]) => {\n config.branchCommits[ref.replace('refs/heads/', '')] =\n toLongCommitSha(sha);\n });\n logger.trace({ branchCommits: config.branchCommits }, 'branch commits');\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n logger.debug({ err }, 'git error');\n if (err.message?.includes('Please ask the owner to check their account')) {\n throw new Error(REPOSITORY_DISABLED);\n }\n throw err;\n }\n}\n\nexport async function fetchRevSpec(revSpec: string): Promise<void> {\n await gitRetry(() => git.fetch(['origin', revSpec]));\n}\n\nexport async function initRepo(args: StorageConfig): Promise<void> {\n config = { ...args } as any;\n config.ignoredAuthors = [];\n config.additionalBranches = [];\n config.branchIsModified = {};\n git = instrumentGit(\n createSimpleGit({ config: { baseDir: GlobalConfig.get('localDir') } }),\n );\n gitInitialized = false;\n submodulesInitizialized = false;\n await fetchBranchCommits();\n}\n\nasync function resetToBranch(branchName: string): Promise<void> {\n logger.debug(`resetToBranch(${branchName})`);\n await git.raw(['reset', '--hard']);\n await gitRetry(() => git.checkout(branchName));\n await git.raw(['reset', '--hard', `origin/${branchName}`]);\n await git.raw(['clean', '-fd']);\n}\n\n/* v8 ignore next -- TODO: add test #40625 */\nexport async function resetToCommit(commit: LongCommitSha): Promise<void> {\n logger.debug(`resetToCommit(${commit})`);\n await git.raw(['reset', '--hard', commit]);\n}\n\nasync function deleteLocalBranch(branchName: string): Promise<void> {\n await git.branch(['-D', branchName]);\n}\n\nasync function cleanLocalBranches(): Promise<void> {\n const existingBranches = (await git.raw(['branch']))\n .split(newlineRegex)\n .map((branch) => branch.trim())\n .filter((branch) => branch.length > 0 && !branch.startsWith('* '));\n logger.debug({ existingBranches });\n for (const branchName of existingBranches) {\n await deleteLocalBranch(branchName);\n }\n}\n\nexport function setGitAuthor(gitAuthor: string | undefined): void {\n const gitAuthorParsed = parseGitAuthor(\n gitAuthor ?? 'Renovate Bot <renovate@whitesourcesoftware.com>',\n );\n if (!gitAuthorParsed) {\n const error = new Error(CONFIG_VALIDATION);\n error.validationSource = 'None';\n error.validationError = 'Invalid gitAuthor';\n error.validationMessage = `\\`gitAuthor\\` is not parsed as valid RFC5322 format: \\`${gitAuthor!}\\``;\n throw error;\n }\n config.gitAuthorName = gitAuthorParsed.name;\n config.gitAuthorEmail = gitAuthorParsed.address;\n}\n\nexport async function writeGitAuthor(): Promise<void> {\n const { gitAuthorName, gitAuthorEmail, writeGitDone } = config;\n /* v8 ignore if -- TODO: add test #40625 */\n if (writeGitDone) {\n return;\n }\n config.writeGitDone = true;\n try {\n // v8 ignore else -- TODO: add test #40625\n if (gitAuthorName) {\n logger.debug(`Setting git author name: ${gitAuthorName}`);\n await git.addConfig('user.name', gitAuthorName);\n }\n // v8 ignore else -- TODO: add test #40625\n if (gitAuthorEmail) {\n logger.debug(`Setting git author email: ${gitAuthorEmail}`);\n await git.addConfig('user.email', gitAuthorEmail);\n }\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n logger.debug(\n { err, gitAuthorName, gitAuthorEmail },\n 'Error setting git author config',\n );\n throw new Error(TEMPORARY_ERROR);\n }\n}\n\nexport function setUserRepoConfig({\n gitIgnoredAuthors,\n gitAuthor,\n}: RenovateConfig): void {\n config.ignoredAuthors = gitIgnoredAuthors ?? [];\n setGitAuthor(gitAuthor);\n}\n\nexport async function getSubmodules(): Promise<string[]> {\n try {\n return (\n (await git.raw([\n 'config',\n '--file',\n '.gitmodules',\n '--get-regexp',\n '\\\\.path',\n ])) || ''\n )\n .trim()\n .split(regEx(/[\\n\\s]/))\n .filter((_e: string, i: number) => i % 2);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.warn({ err }, 'Error getting submodules');\n return [];\n }\n}\n\nexport async function cloneSubmodules(\n shouldClone: boolean,\n cloneSubmodulesFilter: string[] | undefined,\n): Promise<void> {\n if (!shouldClone || submodulesInitizialized) {\n return;\n }\n submodulesInitizialized = true;\n const gitEnv = getChildEnv({ env: getGitEnvironmentVariables() });\n await syncGit();\n const submodules = await getSubmodules();\n for (const submodule of submodules) {\n if (!matchRegexOrGlobList(submodule, cloneSubmodulesFilter ?? ['*'])) {\n logger.debug(\n { cloneSubmodulesFilter },\n `Skipping submodule ${submodule}`,\n );\n continue;\n }\n try {\n logger.debug(`Cloning git submodule at ${submodule}`);\n await gitRetry(() =>\n git.env(gitEnv).submoduleUpdate(['--init', '--recursive', submodule]),\n );\n } catch (err) {\n logger.warn({ err, submodule }, `Unable to initialise git submodule`);\n }\n }\n}\n\nexport function isCloned(): boolean {\n return gitInitialized;\n}\n\nexport async function isFileModeEnabled(): Promise<boolean> {\n if (config.fileModeEnabled === undefined) {\n const value = await git.raw([\n 'config',\n '--type=bool',\n '--default=true',\n '--get',\n 'core.fileMode',\n ]);\n config.fileModeEnabled = value.trim() === 'true';\n }\n\n return config.fileModeEnabled;\n}\n\nexport const syncGit = withInstrumenting(\n { name: 'syncGit' },\n async (): Promise<void> => {\n if (gitInitialized) {\n if (getEnv().RENOVATE_X_CLEAR_HOOKS) {\n await git.raw(['config', 'core.hooksPath', '/dev/null']);\n }\n return;\n }\n /* v8 ignore if -- TODO: add test #40625 */\n if (GlobalConfig.get('platform') === 'local') {\n throw new Error('Cannot sync git when platform=local');\n }\n gitInitialized = true;\n const localDir = GlobalConfig.get('localDir');\n logger.debug(`syncGit(): Initializing git repository into ${localDir}`);\n const gitHead = upath.join(localDir, '.git/HEAD');\n let clone = true;\n\n if (await fs.pathExists(gitHead)) {\n await instrument('fetch', async () => {\n logger.debug(\n `syncGit(): Found existing git repository, attempting git fetch`,\n );\n try {\n await git.raw(['remote', 'set-url', 'origin', config.url]);\n const fetchStart = Date.now();\n await gitRetry(() => git.fetch(['--prune', 'origin']));\n config.currentBranch =\n config.currentBranch || (await getDefaultBranch(git));\n await resetToBranch(config.currentBranch);\n await cleanLocalBranches();\n const durationMs = Math.round(Date.now() - fetchStart);\n logger.info({ durationMs }, 'git fetch completed');\n clone = false;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (err.message === REPOSITORY_EMPTY) {\n throw err;\n }\n logger.info({ err }, 'git fetch error, falling back to git clone');\n }\n });\n }\n if (clone) {\n await instrument('clone', async () => {\n const cloneStart = Date.now();\n try {\n const opts: string[] = [];\n if (config.defaultBranch) {\n opts.push('-b', config.defaultBranch);\n }\n if (config.fullClone) {\n logger.debug('Performing full clone');\n } else {\n logger.debug('Performing blobless clone');\n opts.push('--filter=blob:none');\n }\n if (config.extraCloneOpts) {\n Object.entries(config.extraCloneOpts).forEach((e) =>\n // TODO: types (#22198)\n opts.push(e[0], `${e[1]!}`),\n );\n }\n const emptyDirAndClone = async (): Promise<void> => {\n await instrument(`fs.emptyDir(${localDir})`, () =>\n fs.emptyDir(localDir),\n );\n await git.clone(config.url, '.', opts);\n };\n await gitRetry(() =>\n instrument('emptyDirAndClone', emptyDirAndClone),\n );\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.debug({ err }, 'git clone error');\n if (err.message?.includes('No space left on device')) {\n throw new Error(SYSTEM_INSUFFICIENT_DISK_SPACE);\n }\n if (err.message === REPOSITORY_EMPTY) {\n throw err;\n }\n throw new ExternalHostError(err, 'git');\n }\n const durationMs = Math.round(Date.now() - cloneStart);\n logger.debug({ durationMs }, 'git clone completed');\n });\n }\n try {\n config.currentBranchSha = toLongCommitSha(\n (await git.raw(['rev-parse', 'HEAD'])).trim(),\n );\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (err.message?.includes('fatal: not a git repository')) {\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n // This will only happen now if set in global config\n await instrument('cloneSubmodules', () =>\n cloneSubmodules(!!config.cloneSubmodules, config.cloneSubmodulesFilter),\n );\n try {\n const latestCommit = (await git.log({ n: 1 })).latest;\n logger.debug({ latestCommit }, 'latest repository commit');\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n if (err.message.includes('does not have any commits yet')) {\n throw new Error(REPOSITORY_EMPTY);\n }\n logger.warn({ err }, 'Cannot retrieve latest commit');\n }\n config.currentBranch =\n config.currentBranch ??\n config.defaultBranch ??\n (await getDefaultBranch(git));\n /* v8 ignore next -- TODO: add test #40625 */\n delete getCache()?.semanticCommits;\n\n // If upstreamUrl is set then the bot is running in fork mode\n // The \"upstream\" remote is the original repository which was forked from\n if (config.upstreamUrl) {\n const { upstreamUrl } = config;\n await instrument('sync with upstreamUrl', async () => {\n logger.debug(\n `Bringing default branch up-to-date with ${RENOVATE_FORK_UPSTREAM}, to get latest config`,\n );\n // Add remote if it does not exist\n const remotes = await git.getRemotes(true);\n // v8 ignore else -- TODO: add test #40625\n if (!remotes.some((remote) => remote.name === RENOVATE_FORK_UPSTREAM)) {\n logger.debug(`Adding remote ${RENOVATE_FORK_UPSTREAM}`);\n await git.addRemote(RENOVATE_FORK_UPSTREAM, upstreamUrl);\n }\n await syncForkWithUpstream(config.currentBranch);\n await fetchBranchCommits(false);\n });\n }\n\n config.currentBranchSha = toLongCommitSha(\n (await git.revparse('HEAD')).trim(),\n );\n logger.debug(`Current branch SHA: ${config.currentBranchSha}`);\n },\n);\n\nexport async function getRepoStatus(path?: string): Promise<StatusResult> {\n if (isString(path)) {\n const localDir = GlobalConfig.get('localDir');\n const localPath = upath.resolve(localDir, path);\n if (!localPath.startsWith(upath.resolve(localDir))) {\n logger.warn(\n { localPath, localDir },\n 'Preventing access to file outside the local directory',\n );\n throw new Error(INVALID_PATH);\n }\n }\n\n await syncGit();\n return git.status(path ? [path] : []);\n}\n\nexport function branchExists(branchName: string): boolean {\n return !!config.branchCommits[branchName];\n}\n\n// Return the commit SHA for a branch\nexport function getBranchCommit(branchName: string): LongCommitSha | null {\n return config.branchCommits?.[branchName] || null;\n}\n\n// Return the date of the latest commit for a branch\nexport async function getBranchUpdateDate(\n branchName: string,\n): Promise<DateTime | null> {\n const branchSha = config.branchCommits[branchName];\n if (!branchSha) {\n return null;\n }\n const updateDate = getCachedUpdateDateResult(branchName, branchSha);\n if (updateDate !== null) {\n logger.debug(\n `getBranchUpdateDate(): using cached result \"${updateDate.toISO()}\"`,\n );\n return updateDate;\n }\n await syncGit();\n try {\n const result = await getCommitDate(branchSha);\n setCachedUpdateDateResult(branchName, result);\n return result;\n } catch (err) {\n logger.debug({ err, branchName }, 'Error getting branch update date');\n return null;\n }\n}\n\nexport async function getCommitMessages(): Promise<string[]> {\n logger.debug('getCommitMessages');\n // v8 ignore else -- TODO: add test #40625\n if (GlobalConfig.get('platform') !== 'local') {\n await syncGit();\n }\n try {\n const res = await git.log({\n n: 20,\n format: { message: '%s' },\n '--no-merges': null,\n });\n return res.all.map((commit) => commit.message);\n } catch /* v8 ignore next -- TODO: add test #40625 */ {\n return [];\n }\n}\n\nexport async function checkoutBranch(\n branchName: string,\n): Promise<LongCommitSha> {\n logger.debug(`Setting current branch to ${branchName}`);\n await syncGit();\n try {\n await gitRetry(() =>\n git.checkout(\n submodulesInitizialized\n ? ['-f', '--recurse-submodules', branchName, '--']\n : ['-f', branchName, '--'],\n ),\n );\n config.currentBranch = branchName;\n config.currentBranchSha = toLongCommitSha(\n (await git.raw(['rev-parse', 'HEAD'])).trim(),\n );\n const latestCommitDate = await getCommitDate(config.currentBranchSha);\n // v8 ignore else -- TODO: add test #40625\n if (latestCommitDate) {\n logger.debug(\n { branchName, latestCommitDate, sha: config.currentBranchSha },\n 'latest commit',\n );\n }\n await git.reset(ResetMode.HARD);\n return config.currentBranchSha;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n if (err.message?.includes('fatal: ambiguous argument')) {\n logger.warn({ err }, 'Failed to checkout branch');\n throw new Error(TEMPORARY_ERROR);\n }\n throw err;\n }\n}\n\nexport async function checkoutBranchFromRemote(\n branchName: string,\n remoteName: string,\n): Promise<LongCommitSha> {\n logger.debug(`Checking out branch ${branchName} from remote ${remoteName}`);\n await syncGit();\n try {\n await gitRetry(() =>\n git.checkoutBranch(branchName, `${remoteName}/${branchName}`),\n );\n config.currentBranch = branchName;\n config.currentBranchSha = toLongCommitSha(\n (await git.revparse('HEAD')).trim(),\n );\n logger.debug(`Checked out branch ${branchName} from remote ${remoteName}`);\n config.branchCommits[branchName] = config.currentBranchSha;\n return config.currentBranchSha;\n } catch (err) {\n const errChecked = checkForPlatformFailure(err);\n /* v8 ignore if -- TODO: add test #40625 */\n if (errChecked) {\n throw errChecked;\n }\n if (err.message?.includes('fatal: ambiguous argument')) {\n logger.warn({ err }, 'Failed to checkout branch');\n throw new Error(TEMPORARY_ERROR);\n }\n throw err;\n }\n}\n\nexport async function resetHardFromRemote(\n remoteAndBranch: string,\n): Promise<void> {\n try {\n const resetLog = await git.reset(['--hard', remoteAndBranch]);\n logger.debug({ resetLog }, 'git reset log');\n } catch (err) {\n logger.error({ err }, 'Error during git reset --hard');\n throw err;\n }\n}\n\nexport async function forcePushToRemote(\n branchName: string,\n remote: string,\n): Promise<void> {\n try {\n const pushLog = await git.push([remote, branchName, '--force']);\n logger.debug({ pushLog }, 'git push log');\n } catch (err) {\n logger.error({ err }, 'Error during git push --force');\n throw err;\n }\n}\n\nexport async function getFileList(): Promise<string[]> {\n await syncGit();\n const branch = config.currentBranch;\n let files: string;\n try {\n files = await git.raw(['ls-tree', '-r', `refs/heads/${branch}`]);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (err.message?.includes('fatal: Not a valid object name')) {\n logger.debug(\n { err },\n 'Branch not found when checking branch list - aborting',\n );\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n /* v8 ignore if -- TODO: add test #40625 */\n if (!files) {\n return [];\n }\n // submodules are starting with `160000 commit`\n return files\n .split(newlineRegex)\n .filter(isString)\n .filter((line) => line.startsWith('100'))\n .map((line) => line.split(regEx(/\\t/)).pop()!);\n}\n\nexport function getBranchList(): string[] {\n return Object.keys(config.branchCommits ?? {});\n}\n\nexport async function isBranchBehindBase(\n branchName: string,\n baseBranch: string,\n): Promise<boolean> {\n const baseBranchSha = getBranchCommit(baseBranch);\n const branchSha = getBranchCommit(branchName);\n let isBehind = getCachedBehindBaseResult(\n branchName,\n branchSha,\n baseBranch,\n baseBranchSha,\n );\n if (isBehind !== null) {\n logger.debug(`branch.isBehindBase(): using cached result \"${isBehind}\"`);\n return isBehind;\n }\n\n logger.debug(\n `branch.isBehindBase(): using git to calculate against baseBranch \"${baseBranch}\"`,\n );\n\n await syncGit();\n try {\n const behindCount = (\n await git.raw(['rev-list', '--count', `${branchSha!}..${baseBranchSha!}`])\n ).trim();\n isBehind = behindCount !== '0';\n logger.debug(\n { baseBranch, branchName },\n `branch.isBehindBase(): ${isBehind}`,\n );\n setCachedBehindBaseResult(branchName, isBehind);\n return isBehind;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n throw err;\n }\n}\n\nexport async function isBranchModified(\n branchName: string,\n baseBranch: string,\n): Promise<boolean> {\n if (!branchExists(branchName)) {\n logger.debug('branch.isModified(): no cache');\n return false;\n }\n // First check local config\n if (config.branchIsModified[branchName] !== undefined) {\n return config.branchIsModified[branchName];\n }\n // Second check repository cache\n const isModified = getCachedModifiedResult(\n branchName,\n getBranchCommit(branchName), // branch sha\n );\n if (isModified !== null) {\n logger.debug(`branch.isModified(): using cached result \"${isModified}\"`);\n config.branchIsModified[branchName] = isModified;\n return isModified;\n }\n\n logger.debug(\n `branch.isModified(): using git to calculate against baseBranch \"${baseBranch}\"`,\n );\n\n await syncGit();\n const committedAuthors = new Set<string>();\n try {\n const commits = await git.log([\n `origin/${baseBranch}..origin/${branchName}`,\n ]);\n\n for (const commit of commits.all) {\n committedAuthors.add(commit.author_email);\n }\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (err.message?.includes('fatal: bad revision')) {\n logger.debug(\n { err },\n 'Remote branch not found when checking last commit author - aborting run',\n );\n throw new Error(REPOSITORY_CHANGED);\n }\n logger.warn({ err }, 'Error checking last author for isBranchModified');\n }\n const { gitAuthorEmail, ignoredAuthors } = config;\n\n const includedAuthors = new Set(committedAuthors);\n\n // v8 ignore else -- TODO: add test #40625\n if (gitAuthorEmail) {\n includedAuthors.delete(gitAuthorEmail);\n }\n\n for (const ignoredAuthor of ignoredAuthors) {\n includedAuthors.delete(ignoredAuthor);\n }\n\n if (includedAuthors.size === 0) {\n // authors all match - branch has not been modified\n logger.trace(\n {\n branchName,\n baseBranch,\n committedAuthors: [...committedAuthors],\n includedAuthors: [...includedAuthors],\n gitAuthorEmail,\n ignoredAuthors,\n },\n 'branch.isModified() = false',\n );\n logger.debug('branch.isModified() = false');\n config.branchIsModified[branchName] = false;\n setCachedModifiedResult(branchName, false);\n return false;\n }\n logger.trace(\n {\n branchName,\n baseBranch,\n committedAuthors: [...committedAuthors],\n includedAuthors: [...includedAuthors],\n gitAuthorEmail,\n ignoredAuthors,\n },\n 'branch.isModified() = true',\n );\n logger.debug(\n { baseBranch, branchName, unrecognizedAuthors: [...includedAuthors] },\n 'branch.isModified() = true',\n );\n config.branchIsModified[branchName] = true;\n setCachedModifiedResult(branchName, true);\n return true;\n}\n\nexport async function isBranchConflicted(\n baseBranch: string,\n branch: string,\n): Promise<boolean> {\n logger.debug(`isBranchConflicted(${baseBranch}, ${branch})`);\n\n const baseBranchSha = getBranchCommit(baseBranch);\n const branchSha = getBranchCommit(branch);\n if (!baseBranchSha || !branchSha) {\n logger.warn(\n { baseBranch, branch },\n 'isBranchConflicted: branch does not exist',\n );\n return true;\n }\n\n const isConflicted = getCachedConflictResult(\n branch,\n branchSha,\n baseBranch,\n baseBranchSha,\n );\n if (isBoolean(isConflicted)) {\n logger.debug(\n `branch.isConflicted(): using cached result \"${isConflicted}\"`,\n );\n return isConflicted;\n }\n\n logger.debug(\n `branch.isConflicted(): using git to calculate against baseBranch ${baseBranch}`,\n );\n\n let result = false;\n await syncGit();\n await writeGitAuthor();\n\n const origBranch = config.currentBranch;\n try {\n await git.reset(ResetMode.HARD);\n //TODO: see #18600\n if (origBranch !== baseBranch) {\n await git.checkout(baseBranch);\n }\n await git.merge(['--no-commit', '--no-ff', `origin/${branch}`]);\n } catch (err) {\n result = true;\n /* v8 ignore if -- TODO: add test #40625 */\n if (!err?.git?.conflicts?.length) {\n logger.debug(\n { baseBranch, branch, err },\n 'isBranchConflicted: unknown error',\n );\n }\n } finally {\n try {\n await git.merge(['--abort']);\n if (origBranch !== baseBranch) {\n await git.checkout(origBranch);\n }\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.debug(\n { baseBranch, branch, err },\n 'isBranchConflicted: cleanup error',\n );\n }\n }\n\n setCachedConflictResult(branch, result);\n logger.debug(`branch.isConflicted(): ${result}`);\n return result;\n}\n\nexport async function deleteBranch(\n branchName: string,\n options?: { localBranch?: boolean },\n): Promise<void> {\n await syncGit();\n if (!options?.localBranch) {\n try {\n const deleteCommand = ['push', '--delete', 'origin', branchName];\n\n if (getNoVerify().includes('push')) {\n deleteCommand.push('--no-verify');\n }\n\n await gitRetry(() => git.raw(deleteCommand));\n logger.debug(`Deleted remote branch: ${branchName}`);\n } catch (err) {\n const errChecked = checkForPlatformFailure(err);\n /* v8 ignore if -- TODO: add test #40625 */\n if (errChecked) {\n throw errChecked;\n }\n logger.debug(`No remote branch to delete with name: ${branchName}`);\n }\n }\n try {\n await deleteLocalBranch(branchName);\n /* v8 ignore next -- TODO: add test #40625 (always throws) */\n logger.debug(`Deleted local branch: ${branchName}`);\n } catch (err) {\n const errChecked = checkForPlatformFailure(err);\n /* v8 ignore if -- TODO: add test #40625 */\n if (errChecked) {\n throw errChecked;\n }\n logger.debug(`No local branch to delete with name: ${branchName}`);\n }\n delete config.branchCommits[branchName];\n}\n\nexport async function mergeToLocal(\n refSpecToMerge: string,\n options?: { localBranch?: boolean },\n): Promise<void> {\n let status: StatusResult | undefined;\n try {\n await syncGit();\n await writeGitAuthor();\n await git.reset(ResetMode.HARD);\n await gitRetry(() =>\n git.checkout([\n '-B',\n config.currentBranch,\n `origin/${config.currentBranch}`,\n ]),\n );\n status = await git.status();\n if (options?.localBranch) {\n await git.merge([refSpecToMerge]);\n } else {\n await fetchRevSpec(refSpecToMerge);\n await gitRetry(() => git.merge(['FETCH_HEAD']));\n }\n } catch (err) {\n logger.debug(\n {\n baseBranch: config.currentBranch,\n baseSha: config.currentBranchSha,\n refSpecToMerge,\n status,\n err,\n },\n 'mergeLocally error',\n );\n throw err;\n }\n}\n\nexport async function mergeBranch(branchName: string): Promise<void> {\n let status: StatusResult | undefined;\n try {\n await syncGit();\n await writeGitAuthor();\n await git.reset(ResetMode.HARD);\n await gitRetry(() =>\n git.checkout(['-B', branchName, `origin/${branchName}`]),\n );\n await gitRetry(() =>\n git.checkout([\n '-B',\n config.currentBranch,\n `origin/${config.currentBranch}`,\n ]),\n );\n status = await git.status();\n await gitRetry(() => git.merge(['--ff-only', branchName]));\n await gitRetry(() => git.push('origin', config.currentBranch));\n incLimitedValue('Commits');\n } catch (err) {\n logger.debug(\n {\n baseBranch: config.currentBranch,\n baseSha: config.currentBranchSha,\n branchName,\n branchSha: getBranchCommit(branchName),\n status,\n err,\n },\n 'mergeBranch error',\n );\n throw err;\n }\n}\n\nasync function getCommitDate(ref: LongCommitSha | string): Promise<DateTime> {\n const output = await git.show(['-s', '--format=%cI', ref]);\n return DateTime.fromISO(output.trim()).toUTC();\n}\n\nexport async function getBranchLastCommitTime(\n branchName: string,\n): Promise<Date> {\n await syncGit();\n try {\n const time = await getCommitDate(`origin/${branchName}`);\n return time.toJSDate();\n } catch (err) {\n const errChecked = checkForPlatformFailure(err);\n /* v8 ignore next 3 -- TODO: add test */\n if (errChecked) {\n throw errChecked;\n }\n return new Date();\n }\n}\n\nexport function getBranchFiles(branchName: string): Promise<string[] | null> {\n return getBranchFilesFromRef(`origin/${branchName}`);\n}\n\nexport function getBranchFilesFromCommit(\n referenceCommit: LongCommitSha,\n): Promise<string[] | null> {\n return getBranchFilesFromRef(referenceCommit);\n}\n\nasync function getBranchFilesFromRef(\n refName: string,\n): Promise<string[] | null> {\n await syncGit();\n try {\n const diff = await gitRetry(() =>\n git.diffSummary([refName, `${refName}^`]),\n );\n return diff.files.map((file) => file.file);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.warn({ err }, 'getBranchFilesFromRef error');\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n return null;\n }\n}\n\nexport async function getFile(\n filePath: string,\n branchName?: string,\n): Promise<string | null> {\n await syncGit();\n try {\n const content = await git.show([\n `origin/${branchName ?? config.currentBranch}:${filePath}`,\n ]);\n\n logWarningIfUnicodeHiddenCharactersInPackageFile(filePath, content);\n\n return content;\n } catch (err) {\n const errChecked = checkForPlatformFailure(err);\n /* v8 ignore if -- TODO: add test #40625 */\n if (errChecked) {\n throw errChecked;\n }\n return null;\n }\n}\n\nexport async function getFiles(\n fileNames: string[],\n): Promise<Record<string, string | null>> {\n const fileContentMap: Record<string, string | null> = {};\n\n for (const fileName of fileNames) {\n fileContentMap[fileName] = await getFile(fileName);\n }\n\n return fileContentMap;\n}\n\nexport async function hasDiff(\n sourceRef: string,\n targetRef: string,\n): Promise<boolean> {\n await syncGit();\n try {\n return (\n (await gitRetry(() => git.diff([sourceRef, targetRef, '--']))) !== ''\n );\n } catch {\n return true;\n }\n}\n\nasync function handleCommitAuth(localDir: string): Promise<void> {\n if (!privateKeySet) {\n await writePrivateKey();\n privateKeySet = true;\n }\n await configSigningKey(localDir);\n await writeGitAuthor();\n}\n\n/**\n *\n * Prepare local branch with commit\n *\n * 0. Hard reset\n * 1. Creates local branch with `origin/` prefix\n * 2. Perform `git add` (respecting mode) and `git remove` for each file\n * 3. Perform commit\n * 4. Check whether resulting commit is empty or not (due to .gitignore)\n * 5. If not empty, return commit info for further processing\n *\n */\nexport async function prepareCommit({\n branchName,\n files,\n message,\n force = false,\n}: CommitFilesConfig): Promise<CommitResult | null> {\n const localDir = GlobalConfig.get('localDir');\n await syncGit();\n logger.debug(`Preparing files for committing to branch ${branchName}`);\n await handleCommitAuth(localDir);\n try {\n await git.reset(ResetMode.HARD);\n await git.raw(['clean', '-fd']);\n const parentCommitSha = config.currentBranchSha;\n await gitRetry(() =>\n git.checkout(['-B', branchName, `origin/${config.currentBranch}`]),\n );\n const deletedFiles: string[] = [];\n const addedModifiedFiles: string[] = [];\n const ignoredFiles: string[] = [];\n for (const file of files) {\n const fileName = file.path;\n if (file.type === 'deletion') {\n try {\n await git.rm([fileName]);\n deletedFiles.push(fileName);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n logger.trace({ err, fileName }, 'Cannot delete file');\n ignoredFiles.push(fileName);\n }\n } else {\n if (await isDirectory(upath.join(localDir, fileName))) {\n // This is usually a git submodule update\n logger.trace({ fileName }, 'Adding directory commit');\n } else if (file.contents === null) {\n continue;\n } else {\n let contents: Buffer;\n /* v8 ignore else -- TODO: add test #40625 */\n if (typeof file.contents === 'string') {\n contents = Buffer.from(file.contents);\n } else {\n contents = file.contents;\n }\n // some file systems including Windows don't support the mode\n // so the index should be manually updated after adding the file\n if (file.isSymlink) {\n await fs.symlink(file.contents, upath.join(localDir, fileName));\n } else {\n await fs.outputFile(upath.join(localDir, fileName), contents, {\n mode: file.isExecutable ? 0o777 : 0o666,\n });\n }\n }\n try {\n /* v8 ignore next -- TODO: add test #40625 */\n const addParams =\n fileName === getConfigFileNames()[0] ? ['-f', fileName] : fileName;\n await git.add(addParams);\n if (file.isExecutable) {\n await git.raw(['update-index', '--chmod=+x', fileName]);\n }\n addedModifiedFiles.push(fileName);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (\n !err.message.includes(\n 'The following paths are ignored by one of your .gitignore files',\n )\n ) {\n throw err;\n }\n logger.debug(`Cannot commit ignored file: ${fileName}`);\n ignoredFiles.push(file.path);\n }\n }\n }\n\n const commitOptions: Options = {};\n if (getNoVerify().includes('commit')) {\n commitOptions['--no-verify'] = null;\n }\n\n const commitRes = await git.commit(message, [], commitOptions);\n if (\n isNonEmptyObject(commitRes.summary) &&\n commitRes.summary.changes === 0 &&\n commitRes.summary.insertions === 0 &&\n commitRes.summary.deletions === 0\n ) {\n logger.warn({ commitRes }, 'Detected empty commit - aborting git push');\n return null;\n }\n logger.debug(\n { deletedFiles, ignoredFiles, result: commitRes },\n `git commit`,\n );\n if (!force && !(await hasDiff('HEAD', `origin/${branchName}`))) {\n logger.debug(\n { branchName, deletedFiles, addedModifiedFiles, ignoredFiles },\n 'No file changes detected. Skipping commit',\n );\n return null;\n }\n\n const commitSha = toLongCommitSha(\n (await git.revparse([branchName])).trim(),\n );\n const result: CommitResult = {\n parentCommitSha,\n commitSha,\n files: files.filter((fileChange) => {\n if (fileChange.type === 'deletion') {\n return deletedFiles.includes(fileChange.path);\n }\n return addedModifiedFiles.includes(fileChange.path);\n }),\n };\n\n return result;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n return handleCommitError(err, branchName, files);\n }\n}\n\nexport async function pushCommit({\n sourceRef,\n targetRef,\n files,\n pushOptions,\n}: PushFilesConfig): Promise<boolean> {\n await syncGit();\n logger.debug(`Pushing refSpec ${sourceRef}:${targetRef ?? sourceRef}`);\n let result = false;\n try {\n const gitOptions: TaskOptions = {\n '--force-with-lease': null,\n '-u': null,\n };\n if (getNoVerify().includes('push')) {\n gitOptions['--no-verify'] = null;\n }\n if (pushOptions) {\n gitOptions['--push-option'] = pushOptions;\n }\n\n const pushRes = await gitRetry(() =>\n git.push('origin', `${sourceRef}:${targetRef ?? sourceRef}`, gitOptions),\n );\n delete pushRes.repo;\n logger.debug({ result: pushRes }, 'git push');\n incLimitedValue('Commits');\n incCountValue('HourlyCommits');\n result = true;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n handleCommitError(err, sourceRef, files);\n }\n return result;\n}\n\nexport async function fetchBranch(\n branchName: string,\n): Promise<LongCommitSha | null> {\n await syncGit();\n logger.debug(`Fetching branch ${branchName}`);\n try {\n const ref = `refs/heads/${branchName}:refs/remotes/origin/${branchName}`;\n await gitRetry(() => git.pull(['origin', ref, '--force']));\n const commit = toLongCommitSha((await git.revparse([branchName])).trim());\n config.branchCommits[branchName] = commit;\n config.branchIsModified[branchName] = false;\n return commit;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n return handleCommitError(err, branchName);\n }\n}\n\nexport async function commitFiles(\n commitConfig: CommitFilesConfig,\n): Promise<LongCommitSha | null> {\n try {\n const commitResult = await prepareCommit(commitConfig);\n if (commitResult) {\n const pushResult = await pushCommit({\n sourceRef: commitConfig.branchName,\n files: commitConfig.files,\n });\n // v8 ignore else -- TODO: add test #40625\n if (pushResult) {\n const { branchName } = commitConfig;\n const { commitSha } = commitResult;\n config.branchCommits[branchName] = commitSha;\n config.branchIsModified[branchName] = false;\n return commitSha;\n }\n }\n return null;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (err.message.includes('[rejected] (stale info)')) {\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n}\n\nexport function getUrl({\n protocol,\n auth,\n hostname,\n host,\n repository,\n}: {\n protocol?: GitProtocol;\n auth?: string;\n hostname?: string;\n host?: string;\n repository: string;\n}): string {\n if (protocol === 'ssh') {\n // TODO: types (#22198)\n return `git@${hostname!}:${repository}.git`;\n }\n return URL.format({\n protocol: protocol ?? 'https',\n auth,\n hostname,\n host,\n pathname: `${repository}.git`,\n });\n}\n\nlet remoteRefsExist = false;\n\n/**\n *\n * Non-branch refs allow us to store git objects without triggering CI pipelines.\n * It's useful for API-based branch rebasing.\n *\n * @see https://stackoverflow.com/questions/63866947/pushing-git-non-branch-references-to-a-remote/63868286\n *\n */\nexport async function pushCommitToRenovateRef(\n commitSha: string,\n refName: string,\n): Promise<void> {\n const fullRefName = `refs/renovate/branches/${refName}`;\n await git.raw(['update-ref', fullRefName, commitSha]);\n await git.push(['--force', 'origin', fullRefName]);\n remoteRefsExist = true;\n}\n\n/**\n *\n * Removes all remote \"refs/renovate/branches/*\" refs in two steps:\n *\n * Step 1: list refs\n *\n * $ git ls-remote origin \"refs/renovate/branches/*\"\n *\n * > cca38e9ea6d10946bdb2d0ca5a52c205783897aa refs/renovate/branches/foo\n * > 29ac154936c880068994e17eb7f12da7fdca70e5 refs/renovate/branches/bar\n * > 3fafaddc339894b6d4f97595940fd91af71d0355 refs/renovate/branches/baz\n * > ...\n *\n * Step 2:\n *\n * $ git push --delete origin refs/renovate/branches/foo refs/renovate/branches/bar refs/renovate/branches/baz\n *\n * If Step 2 fails because the repo doesn't allow bulk changes, we'll remove them one by one instead:\n *\n * $ git push --delete origin refs/renovate/branches/foo\n * $ git push --delete origin refs/renovate/branches/bar\n * $ git push --delete origin refs/renovate/branches/baz\n */\nexport async function clearRenovateRefs(): Promise<void> {\n if (!gitInitialized || !remoteRefsExist) {\n return;\n }\n\n logger.debug(`Cleaning up Renovate refs: refs/renovate/branches/*`);\n const renovateRefs: string[] = [];\n\n try {\n const rawOutput = await git.listRemote([\n config.url,\n 'refs/renovate/branches/*',\n ]);\n const refs = rawOutput\n .split(newlineRegex)\n .map((line) => line.replace(regEx(/[0-9a-f]+\\s+/i), '').trim())\n .filter((line) => line.startsWith('refs/renovate/branches/'));\n renovateRefs.push(...refs);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.warn({ err }, `Renovate refs cleanup error`);\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (renovateRefs.length) {\n try {\n const pushOpts = ['--delete', 'origin', ...renovateRefs];\n await git.push(pushOpts);\n } catch (err) {\n /* v8 ignore else -- TODO: add test #40625 */\n if (bulkChangesDisallowed(err)) {\n for (const ref of renovateRefs) {\n try {\n const pushOpts = ['--delete', 'origin', ref];\n await git.push(pushOpts);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.debug({ err }, 'Error deleting \"refs/renovate/branches/*\"');\n break;\n }\n }\n } else {\n logger.warn({ err }, 'Error deleting \"refs/renovate/branches/*\"');\n }\n }\n }\n\n remoteRefsExist = false;\n}\n\nconst diffTreeLineRegex = regEx(\n /^:(?<oldMode>\\d{6})\\s+(?<newMode>\\d{6})\\s+(?<oldSha>[0-9a-f]{40})\\s+(?<newSha>[0-9a-f]{40})\\s+(?<status>[A-Z]\\d*)\\t(?<paths>.+)$/,\n);\n\nconst treeShaRegex = regEx(/tree\\s+(?<treeSha>[0-9a-f]{40})\\s*/);\n\n/**\n * Get the tree SHA for a commit.\n */\nexport async function getCommitTreeSha(\n commitSha: LongCommitSha,\n): Promise<LongCommitSha> {\n const commitOutput = await git.catFile(['-p', commitSha]);\n const { treeSha } = treeShaRegex.exec(commitOutput)?.groups ?? {};\n if (!treeSha) {\n const snippet = commitOutput.split(newlineRegex)[0];\n /* v8 ignore next -- tested, but v8 reports template literal as partial */\n throw new Error(\n `Could not extract tree SHA from commit ${commitSha}: ${snippet}`,\n );\n }\n return toLongCommitSha(treeSha);\n}\n\nfunction treeTypeFromMode(mode: string): GitObjectType {\n switch (mode) {\n case GitTreeMode.Gitlink:\n return 'commit';\n case GitTreeMode.Directory:\n return 'tree';\n default:\n return 'blob';\n }\n}\n\n/**\n * Return only the files that changed between two commits.\n * Deletions have `sha: null` (for use with GitHub's `base_tree` API).\n */\nexport async function diffCommitTree(\n parentCommitSha: LongCommitSha,\n commitSha: LongCommitSha,\n): Promise<DiffTreeItem[]> {\n const output = await git.raw([\n 'diff-tree',\n '-M',\n '-r',\n '--no-commit-id',\n parentCommitSha,\n commitSha,\n ]);\n const result: DiffTreeItem[] = [];\n for (const line of output.split(newlineRegex)) {\n const matchGroups = diffTreeLineRegex.exec(line)?.groups;\n if (matchGroups) {\n const { oldMode, newMode, newSha, status, paths } = matchGroups;\n const statusCode = status[0];\n // R has two tab-separated paths (old\\tnew); A/M/D/T have one.\n // C also has two paths but falls through to default (only the target matters).\n const [sourcePath, targetPath] = paths.split('\\t');\n switch (statusCode) {\n case 'D':\n result.push({\n path: sourcePath,\n mode: oldMode,\n type: treeTypeFromMode(oldMode),\n sha: null,\n });\n break;\n case 'R':\n // Rename: delete source, add target\n result.push({\n path: sourcePath,\n mode: oldMode,\n type: treeTypeFromMode(oldMode),\n sha: null,\n });\n result.push({\n path: targetPath,\n mode: newMode,\n type: treeTypeFromMode(newMode),\n sha: toLongCommitSha(newSha),\n });\n break;\n default:\n // A (add), M (modify), T (type change), C (copy)\n result.push({\n path: targetPath ?? sourcePath,\n mode: newMode,\n type: treeTypeFromMode(newMode),\n sha: toLongCommitSha(newSha),\n });\n break;\n }\n }\n }\n return result;\n}\n\nasync function localBranchExists(branchName: string): Promise<boolean> {\n await syncGit();\n const localBranches = await git.branchLocal();\n return localBranches.all.includes(branchName);\n}\n\n/**\n * Synchronize a forked branch with its upstream counterpart.\n *\n * syncForkWithUpstream updates the fork's branch, to match the corresponding branch in the upstream repository.\n * The steps are:\n * 1. Check if the branch exists locally.\n * 2. If the branch exists locally: checkout the local branch.\n * 3. If the branch does _not_ exist locally: checkout the upstream branch.\n * 4. Reset the local branch to match the upstream branch.\n * 5. Force push the (updated) local branch to the origin repository.\n *\n * @param {string} branchName - The name of the branch to synchronize.\n * @returns A promise that resolves to True if the synchronization is successful, or `false` if an error occurs.\n */\nexport async function syncForkWithUpstream(branchName: string): Promise<void> {\n if (!config.upstreamUrl) {\n return;\n }\n logger.debug(\n `Synchronizing fork with \"${RENOVATE_FORK_UPSTREAM}\" remote for branch ${branchName}`,\n );\n const remotes = await getRemotes();\n /* v8 ignore if -- this should not be possible if upstreamUrl exists */\n if (!remotes.some((r) => r === RENOVATE_FORK_UPSTREAM)) {\n throw new Error('No upstream remote exists, cannot sync fork');\n }\n try {\n await git.fetch([RENOVATE_FORK_UPSTREAM]);\n if (await localBranchExists(branchName)) {\n await checkoutBranch(branchName);\n } else {\n await checkoutBranchFromRemote(branchName, RENOVATE_FORK_UPSTREAM);\n }\n await resetHardFromRemote(`${RENOVATE_FORK_UPSTREAM}/${branchName}`);\n await forcePushToRemote(branchName, 'origin');\n } catch (err) /* v8 ignore next -- shouldn't happen */ {\n logger.error({ err }, 'Error synchronizing fork');\n throw new Error(UNKNOWN_ERROR);\n }\n}\n\nexport async function getRemotes(): Promise<string[]> {\n logger.debug('git.getRemotes()');\n try {\n await syncGit();\n const remotes = await git.getRemotes();\n logger.debug(`Found remotes: ${remotes.map((r) => r.name).join(', ')}`);\n return remotes.map((remote) => remote.name);\n } catch (err) /* v8 ignore next */ {\n logger.error({ err }, 'Error getting remotes');\n throw err;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../lib/util/git/index.ts"],"sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport URL from 'node:url';\nimport { isBoolean, isNonEmptyObject, isString } from '@sindresorhus/is';\nimport fs from 'fs-extra';\nimport { DateTime } from 'luxon';\nimport semver from 'semver';\nimport type {\n Options,\n SimpleGit,\n SimpleGitOptions,\n TaskOptions,\n} from 'simple-git';\nimport { ResetMode, simpleGit } from 'simple-git';\nimport upath from 'upath';\nimport { getConfigFileNames } from '../../config/app-strings.ts';\nimport { GlobalConfig } from '../../config/global.ts';\nimport type { RenovateConfig } from '../../config/types.ts';\nimport {\n CONFIG_VALIDATION,\n INVALID_PATH,\n REPOSITORY_CHANGED,\n REPOSITORY_DISABLED,\n REPOSITORY_EMPTY,\n SYSTEM_INSUFFICIENT_DISK_SPACE,\n TEMPORARY_ERROR,\n UNKNOWN_ERROR,\n} from '../../constants/error-messages.ts';\nimport { instrument } from '../../instrumentation/index.ts';\nimport { withInstrumenting } from '../../instrumentation/with-instrumenting.ts';\nimport { logger } from '../../logger/index.ts';\nimport { ExternalHostError } from '../../types/errors/external-host-error.ts';\nimport type { GitProtocol } from '../../types/git.ts';\nimport { incCountValue, incLimitedValue } from '../../workers/global/limits.ts';\nimport { getCache } from '../cache/repository/index.ts';\nimport { getEnv } from '../env.ts';\nimport type { ExtraEnv } from '../exec/types.ts';\nimport { getChildEnv } from '../exec/utils.ts';\nimport { newlineRegex, regEx } from '../regex.ts';\nimport type { LongCommitSha } from '../schema-utils/git.ts';\nimport { toLongCommitSha } from '../schema-utils/git.ts';\nimport { matchRegexOrGlobList } from '../string-match.ts';\nimport { logWarningIfUnicodeHiddenCharactersInPackageFile } from '../unicode.ts';\nimport { getGitEnvironmentVariables } from './auth.ts';\nimport { parseGitAuthor } from './author.ts';\nimport {\n getCachedBehindBaseResult,\n setCachedBehindBaseResult,\n} from './behind-base-branch-cache.ts';\nimport { getNoVerify, simpleGitConfig } from './config.ts';\nimport {\n getCachedConflictResult,\n setCachedConflictResult,\n} from './conflicts-cache.ts';\nimport {\n bulkChangesDisallowed,\n checkForPlatformFailure,\n handleCommitError,\n} from './error.ts';\nimport type { InstrumentedSimpleGit } from './instrument.ts';\nimport { instrumentGit } from './instrument.ts';\nimport {\n getCachedModifiedResult,\n setCachedModifiedResult,\n} from './modified-cache.ts';\nimport { configSigningKey, writePrivateKey } from './private-key.ts';\nimport type {\n CommitFilesConfig,\n CommitResult,\n DiffTreeItem,\n GitObjectType,\n LocalConfig,\n PushFilesConfig,\n StatusResult,\n StorageConfig,\n} from './types.ts';\nimport { GitTreeMode } from './types.ts';\nimport {\n getCachedUpdateDateResult,\n setCachedUpdateDateResult,\n} from './update-date-cache.ts';\n\nexport { setNoVerify } from './config.ts';\nexport { setPrivateKey } from './private-key.ts';\n\n// Retry parameters\nconst retryCount = 5;\nconst delaySeconds = 3;\nconst delayFactor = 2;\n\nexport const RENOVATE_FORK_UPSTREAM = 'renovate-fork-upstream';\n\nexport function createSimpleGit({\n config,\n env,\n}: {\n config?: Partial<SimpleGitOptions>;\n env?: ExtraEnv;\n} = {}): SimpleGit {\n return simpleGit({ ...simpleGitConfig(), ...config }).env(\n getChildEnv({\n extraEnv: {\n // Git will prompt for known hosts or passwords, unless we activate BatchMode.\n // Set as extraEnv (lowest priority) so that process.env and\n // customEnvVariables can override it.\n GIT_SSH_COMMAND: 'ssh -o BatchMode=yes',\n },\n env: {\n ...env,\n // To ensure the simple-git parsers match correctly, we need\n // to set the `LANG` and `LC_ALL` environment variables to\n // the `C.UTF-8` locale. See the docs for more details:\n // https://github.com/steveukx/git-js/blob/1bb14df0595794a9353d28ccdaeeb06c0b9bf2a5/docs/NON_ENGLISH_LOCALE.md\n //\n // Use \"C.UTF-8\" instead of just \"C\" (as specified in docs) to handle special characters:\n // https://github.com/renovatebot/renovate/pull/18963\n LANG: 'C.UTF-8',\n LC_ALL: 'C.UTF-8',\n },\n }),\n );\n}\n\n// A generic wrapper for simpleGit.* calls to make them more fault-tolerant\nexport async function gitRetry<T>(gitFunc: () => Promise<T>): Promise<T> {\n let round = 0;\n let lastError: Error | undefined;\n\n while (round <= retryCount) {\n if (round > 0) {\n logger.debug(`gitRetry round ${round}`);\n }\n try {\n const res = await gitFunc();\n if (round > 1) {\n logger.debug('Successful retry of git function');\n }\n return res;\n } catch (err) {\n lastError = err;\n logger.debug({ err }, `Git function thrown`);\n // Try to transform the Error to ExternalHostError\n const errChecked = checkForPlatformFailure(err);\n if (errChecked instanceof ExternalHostError) {\n logger.debug(\n { err: errChecked },\n `ExternalHostError thrown in round ${\n round + 1\n } of ${retryCount} - retrying in the next round`,\n );\n } else {\n throw err;\n }\n }\n\n const nextDelay = delayFactor ^ ((round - 1) * delaySeconds);\n logger.trace({ nextDelay }, `Delay next round`);\n await setTimeout(1000 * nextDelay);\n\n round++;\n }\n\n throw lastError!;\n}\n\nasync function isDirectory(dir: string): Promise<boolean> {\n try {\n return (await fs.stat(dir)).isDirectory();\n } catch {\n return false;\n }\n}\n\nasync function getDefaultBranch(git: InstrumentedSimpleGit): Promise<string> {\n logger.debug('getDefaultBranch()');\n // see https://stackoverflow.com/a/62352647/3005034\n try {\n let res = await git.raw(['rev-parse', '--abbrev-ref', 'origin/HEAD']);\n /* v8 ignore next -- TODO: add test #40625 */\n if (!res) {\n logger.debug('Could not determine default branch using git rev-parse');\n const headPrefix = 'HEAD branch: ';\n res = (await git.raw(['remote', 'show', 'origin']))\n .split('\\n')\n .map((line) => line.trim())\n .find((line) => line.startsWith(headPrefix))!\n .replace(headPrefix, '');\n }\n\n return res.replace('origin/', '').trim();\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.debug({ err }, 'Error getting default branch');\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n if (\n err.message.startsWith(\n 'fatal: ref refs/remotes/origin/HEAD is not a symbolic ref',\n )\n ) {\n throw new Error(REPOSITORY_EMPTY);\n }\n if (err.message.includes(\"fatal: ambiguous argument 'origin/HEAD'\")) {\n logger.warn('Error getting default branch');\n throw new Error(TEMPORARY_ERROR);\n }\n throw err;\n }\n}\n\nlet config: LocalConfig = {} as any;\n\n// TODO: can be undefined\nlet git: InstrumentedSimpleGit;\nlet gitInitialized: boolean;\nlet submodulesInitizialized: boolean;\n\nlet privateKeySet = false;\n\nexport const GIT_MINIMUM_VERSION = '2.33.0'; // git show-current\n\nexport async function validateGitVersion(): Promise<boolean> {\n let version: string | undefined;\n const globalGit = instrumentGit(createSimpleGit());\n try {\n const { major, minor, patch, installed } = await globalGit.version();\n /* v8 ignore if -- TODO: add test #40625 */\n if (!installed) {\n logger.error('Git not installed');\n return false;\n }\n version = `${major}.${minor}.${patch}`;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.error({ err }, 'Error fetching git version');\n return false;\n }\n /* v8 ignore if -- TODO: add test #40625 */\n if (!(version && semver.gte(version, GIT_MINIMUM_VERSION))) {\n logger.error(\n { detectedVersion: version, minimumVersion: GIT_MINIMUM_VERSION },\n 'Git version needs upgrading',\n );\n return false;\n }\n logger.debug(`Found valid git version: ${version}`);\n return true;\n}\n\nasync function fetchBranchCommits(preferUpstream = true): Promise<void> {\n config.branchCommits = {};\n const url =\n preferUpstream && config.upstreamUrl ? config.upstreamUrl : config.url;\n logger.debug(`fetchBranchCommits(): url=${url}`);\n const opts = ['ls-remote', '--heads', url];\n const localDir = GlobalConfig.get('localDir');\n const repoExists = await fs.pathExists(upath.join(localDir, '.git/HEAD'));\n if (config.extraCloneOpts && !repoExists) {\n Object.entries(config.extraCloneOpts).forEach((e) =>\n // TODO: types (#22198)\n opts.unshift(e[0], `${e[1]!}`),\n );\n }\n try {\n const lsRemoteRes = await gitRetry(() => git.raw(opts));\n logger.trace({ lsRemoteRes }, 'git ls-remote result');\n lsRemoteRes\n .split(newlineRegex)\n .filter(Boolean)\n .map((line) => line.trim().split(regEx(/\\s+/)))\n .forEach(([sha, ref]) => {\n config.branchCommits[ref.replace('refs/heads/', '')] =\n toLongCommitSha(sha);\n });\n\n if (isNonEmptyObject(config.virtualBranches)) {\n for (const [name, branch] of Object.entries(config.virtualBranches)) {\n config.branchCommits[name] = branch.sha;\n }\n }\n\n logger.trace({ branchCommits: config.branchCommits }, 'branch commits');\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n logger.debug({ err }, 'git error');\n if (err.message?.includes('Please ask the owner to check their account')) {\n throw new Error(REPOSITORY_DISABLED);\n }\n throw err;\n }\n}\n\nexport async function fetchRevSpec(...revSpec: string[]): Promise<void> {\n await gitRetry(() => git.fetch(['origin', ...revSpec]));\n}\n\nexport async function initRepo(args: StorageConfig): Promise<void> {\n config = { ...args } as any;\n config.ignoredAuthors = [];\n config.additionalBranches = [];\n config.branchIsModified = {};\n config.virtualBranches ??= {};\n git = instrumentGit(\n createSimpleGit({ config: { baseDir: GlobalConfig.get('localDir') } }),\n );\n gitInitialized = false;\n submodulesInitizialized = false;\n await fetchBranchCommits();\n}\n\nasync function resetToBranch(branchName: string): Promise<void> {\n logger.debug(`resetToBranch(${branchName})`);\n await git.raw(['reset', '--hard']);\n await gitRetry(() => git.checkout(branchName));\n await git.raw(['reset', '--hard', `origin/${branchName}`]);\n await git.raw(['clean', '-fd']);\n}\n\n/* v8 ignore next -- TODO: add test #40625 */\nexport async function resetToCommit(commit: LongCommitSha): Promise<void> {\n logger.debug(`resetToCommit(${commit})`);\n await git.raw(['reset', '--hard', commit]);\n}\n\nasync function deleteLocalBranch(branchName: string): Promise<void> {\n await git.branch(['-D', branchName]);\n}\n\nasync function cleanLocalBranches(): Promise<void> {\n const existingBranches = (await git.raw(['branch']))\n .split(newlineRegex)\n .map((branch) => branch.trim())\n .filter((branch) => branch.length > 0 && !branch.startsWith('* '));\n logger.debug({ existingBranches });\n for (const branchName of existingBranches) {\n await deleteLocalBranch(branchName);\n }\n}\n\nexport function setGitAuthor(gitAuthor: string | undefined): void {\n const gitAuthorParsed = parseGitAuthor(\n gitAuthor ?? 'Renovate Bot <renovate@whitesourcesoftware.com>',\n );\n if (!gitAuthorParsed) {\n const error = new Error(CONFIG_VALIDATION);\n error.validationSource = 'None';\n error.validationError = 'Invalid gitAuthor';\n error.validationMessage = `\\`gitAuthor\\` is not parsed as valid RFC5322 format: \\`${gitAuthor!}\\``;\n throw error;\n }\n config.gitAuthorName = gitAuthorParsed.name;\n config.gitAuthorEmail = gitAuthorParsed.address;\n}\n\nexport async function writeGitAuthor(): Promise<void> {\n const { gitAuthorName, gitAuthorEmail, writeGitDone } = config;\n /* v8 ignore if -- TODO: add test #40625 */\n if (writeGitDone) {\n return;\n }\n config.writeGitDone = true;\n try {\n // v8 ignore else -- TODO: add test #40625\n if (gitAuthorName) {\n logger.debug(`Setting git author name: ${gitAuthorName}`);\n await git.addConfig('user.name', gitAuthorName);\n }\n // v8 ignore else -- TODO: add test #40625\n if (gitAuthorEmail) {\n logger.debug(`Setting git author email: ${gitAuthorEmail}`);\n await git.addConfig('user.email', gitAuthorEmail);\n }\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n logger.debug(\n { err, gitAuthorName, gitAuthorEmail },\n 'Error setting git author config',\n );\n throw new Error(TEMPORARY_ERROR);\n }\n}\n\nexport function setUserRepoConfig({\n gitIgnoredAuthors,\n gitAuthor,\n}: RenovateConfig): void {\n config.ignoredAuthors = gitIgnoredAuthors ?? [];\n setGitAuthor(gitAuthor);\n}\n\nexport async function getSubmodules(): Promise<string[]> {\n try {\n return (\n (await git.raw([\n 'config',\n '--file',\n '.gitmodules',\n '--get-regexp',\n '\\\\.path',\n ])) || ''\n )\n .trim()\n .split(regEx(/[\\n\\s]/))\n .filter((_e: string, i: number) => i % 2);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.warn({ err }, 'Error getting submodules');\n return [];\n }\n}\n\nexport async function cloneSubmodules(\n shouldClone: boolean,\n cloneSubmodulesFilter: string[] | undefined,\n): Promise<void> {\n if (!shouldClone || submodulesInitizialized) {\n return;\n }\n submodulesInitizialized = true;\n const gitEnv = getChildEnv({ env: getGitEnvironmentVariables() });\n await syncGit();\n const submodules = await getSubmodules();\n for (const submodule of submodules) {\n if (!matchRegexOrGlobList(submodule, cloneSubmodulesFilter ?? ['*'])) {\n logger.debug(\n { cloneSubmodulesFilter },\n `Skipping submodule ${submodule}`,\n );\n continue;\n }\n try {\n logger.debug(`Cloning git submodule at ${submodule}`);\n await gitRetry(() =>\n git.env(gitEnv).submoduleUpdate(['--init', '--recursive', submodule]),\n );\n } catch (err) {\n logger.warn({ err, submodule }, `Unable to initialise git submodule`);\n }\n }\n}\n\nexport function isCloned(): boolean {\n return gitInitialized;\n}\n\nexport async function isFileModeEnabled(): Promise<boolean> {\n if (config.fileModeEnabled === undefined) {\n const value = await git.raw([\n 'config',\n '--type=bool',\n '--default=true',\n '--get',\n 'core.fileMode',\n ]);\n config.fileModeEnabled = value.trim() === 'true';\n }\n\n return config.fileModeEnabled;\n}\n\nexport const syncGit = withInstrumenting(\n { name: 'syncGit' },\n async (): Promise<void> => {\n if (gitInitialized) {\n if (getEnv().RENOVATE_X_CLEAR_HOOKS) {\n await git.raw(['config', 'core.hooksPath', '/dev/null']);\n }\n return;\n }\n /* v8 ignore if -- TODO: add test #40625 */\n if (GlobalConfig.get('platform') === 'local') {\n throw new Error('Cannot sync git when platform=local');\n }\n gitInitialized = true;\n const localDir = GlobalConfig.get('localDir');\n logger.debug(`syncGit(): Initializing git repository into ${localDir}`);\n const gitHead = upath.join(localDir, '.git/HEAD');\n let clone = true;\n\n if (await fs.pathExists(gitHead)) {\n await instrument('fetch', async () => {\n logger.debug(\n `syncGit(): Found existing git repository, attempting git fetch`,\n );\n try {\n await git.raw(['remote', 'set-url', 'origin', config.url]);\n const fetchStart = Date.now();\n await gitRetry(() => git.fetch(['--prune', 'origin']));\n config.currentBranch =\n config.currentBranch || (await getDefaultBranch(git));\n await resetToBranch(config.currentBranch);\n await cleanLocalBranches();\n const durationMs = Math.round(Date.now() - fetchStart);\n logger.info({ durationMs }, 'git fetch completed');\n clone = false;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (err.message === REPOSITORY_EMPTY) {\n throw err;\n }\n logger.info({ err }, 'git fetch error, falling back to git clone');\n }\n });\n }\n if (clone) {\n await instrument('clone', async () => {\n const cloneStart = Date.now();\n try {\n const opts: string[] = [];\n if (config.defaultBranch) {\n opts.push('-b', config.defaultBranch);\n }\n if (config.fullClone) {\n logger.debug('Performing full clone');\n } else {\n logger.debug('Performing blobless clone');\n opts.push('--filter=blob:none');\n }\n if (config.extraCloneOpts) {\n Object.entries(config.extraCloneOpts).forEach((e) =>\n // TODO: types (#22198)\n opts.push(e[0], `${e[1]!}`),\n );\n }\n const emptyDirAndClone = async (): Promise<void> => {\n await instrument(`fs.emptyDir(${localDir})`, () =>\n fs.emptyDir(localDir),\n );\n await git.clone(config.url, '.', opts);\n };\n await gitRetry(() =>\n instrument('emptyDirAndClone', emptyDirAndClone),\n );\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.debug({ err }, 'git clone error');\n if (err.message?.includes('No space left on device')) {\n throw new Error(SYSTEM_INSUFFICIENT_DISK_SPACE);\n }\n if (err.message === REPOSITORY_EMPTY) {\n throw err;\n }\n throw new ExternalHostError(err, 'git');\n }\n const durationMs = Math.round(Date.now() - cloneStart);\n logger.debug({ durationMs }, 'git clone completed');\n });\n }\n try {\n config.currentBranchSha = toLongCommitSha(\n (await git.raw(['rev-parse', 'HEAD'])).trim(),\n );\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (err.message?.includes('fatal: not a git repository')) {\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n // This will only happen now if set in global config\n await instrument('cloneSubmodules', () =>\n cloneSubmodules(!!config.cloneSubmodules, config.cloneSubmodulesFilter),\n );\n try {\n const latestCommit = (await git.log({ n: 1 })).latest;\n logger.debug({ latestCommit }, 'latest repository commit');\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n if (err.message.includes('does not have any commits yet')) {\n throw new Error(REPOSITORY_EMPTY);\n }\n logger.warn({ err }, 'Cannot retrieve latest commit');\n }\n config.currentBranch =\n config.currentBranch ??\n config.defaultBranch ??\n (await getDefaultBranch(git));\n /* v8 ignore next -- TODO: add test #40625 */\n delete getCache()?.semanticCommits;\n\n // If upstreamUrl is set then the bot is running in fork mode\n // The \"upstream\" remote is the original repository which was forked from\n if (config.upstreamUrl) {\n const { upstreamUrl } = config;\n await instrument('sync with upstreamUrl', async () => {\n logger.debug(\n `Bringing default branch up-to-date with ${RENOVATE_FORK_UPSTREAM}, to get latest config`,\n );\n // Add remote if it does not exist\n const remotes = await git.getRemotes(true);\n // v8 ignore else -- TODO: add test #40625\n if (!remotes.some((remote) => remote.name === RENOVATE_FORK_UPSTREAM)) {\n logger.debug(`Adding remote ${RENOVATE_FORK_UPSTREAM}`);\n await git.addRemote(RENOVATE_FORK_UPSTREAM, upstreamUrl);\n }\n await syncForkWithUpstream(config.currentBranch);\n await fetchBranchCommits(false);\n });\n }\n\n if (isNonEmptyObject(config.virtualBranches)) {\n const virtualBranches = config.virtualBranches;\n await instrument('fetch virtual branches', async () => {\n const refSpecs = Object.entries(virtualBranches).map(\n ([name, branch]) => `${branch.ref}:${remoteBranchRef(name)}`,\n );\n await fetchRevSpec(...refSpecs);\n logger.debug(\n `Fetched ${Object.keys(virtualBranches).length} virtual branches`,\n );\n });\n }\n\n config.currentBranchSha = toLongCommitSha(\n (await git.revparse('HEAD')).trim(),\n );\n logger.debug(`Current branch SHA: ${config.currentBranchSha}`);\n },\n);\n\nexport async function getRepoStatus(path?: string): Promise<StatusResult> {\n if (isString(path)) {\n const localDir = GlobalConfig.get('localDir');\n const localPath = upath.resolve(localDir, path);\n if (!localPath.startsWith(upath.resolve(localDir))) {\n logger.warn(\n { localPath, localDir },\n 'Preventing access to file outside the local directory',\n );\n throw new Error(INVALID_PATH);\n }\n }\n\n await syncGit();\n return git.status(path ? [path] : []);\n}\n\nexport function branchExists(branchName: string): boolean {\n return !!config.branchCommits[branchName];\n}\n\n// Return the commit SHA for a branch\nexport function getBranchCommit(branchName: string): LongCommitSha | null {\n return config.branchCommits?.[branchName] || null;\n}\n\n// Return the date of the latest commit for a branch\nexport async function getBranchUpdateDate(\n branchName: string,\n): Promise<DateTime | null> {\n const branchSha = config.branchCommits[branchName];\n if (!branchSha) {\n return null;\n }\n const updateDate = getCachedUpdateDateResult(branchName, branchSha);\n if (updateDate !== null) {\n logger.debug(\n `getBranchUpdateDate(): using cached result \"${updateDate.toISO()}\"`,\n );\n return updateDate;\n }\n await syncGit();\n try {\n const result = await getCommitDate(branchSha);\n setCachedUpdateDateResult(branchName, result);\n return result;\n } catch (err) {\n logger.debug({ err, branchName }, 'Error getting branch update date');\n return null;\n }\n}\n\nexport async function getCommitMessages(): Promise<string[]> {\n logger.debug('getCommitMessages');\n // v8 ignore else -- TODO: add test #40625\n if (GlobalConfig.get('platform') !== 'local') {\n await syncGit();\n }\n try {\n const res = await git.log({\n n: 20,\n format: { message: '%s' },\n '--no-merges': null,\n });\n return res.all.map((commit) => commit.message);\n } catch /* v8 ignore next -- TODO: add test #40625 */ {\n return [];\n }\n}\n\nexport async function checkoutBranch(\n branchName: string,\n): Promise<LongCommitSha> {\n logger.debug(`Setting current branch to ${branchName}`);\n await syncGit();\n try {\n await gitRetry(() =>\n git.checkout(\n submodulesInitizialized\n ? ['-f', '--recurse-submodules', branchName, '--']\n : ['-f', branchName, '--'],\n ),\n );\n config.currentBranch = branchName;\n config.currentBranchSha = toLongCommitSha(\n (await git.raw(['rev-parse', 'HEAD'])).trim(),\n );\n const latestCommitDate = await getCommitDate(config.currentBranchSha);\n // v8 ignore else -- TODO: add test #40625\n if (latestCommitDate) {\n logger.debug(\n { branchName, latestCommitDate, sha: config.currentBranchSha },\n 'latest commit',\n );\n }\n await git.reset(ResetMode.HARD);\n return config.currentBranchSha;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n if (err.message?.includes('fatal: ambiguous argument')) {\n logger.warn({ err }, 'Failed to checkout branch');\n throw new Error(TEMPORARY_ERROR);\n }\n throw err;\n }\n}\n\nexport async function checkoutBranchFromRemote(\n branchName: string,\n remoteName: string,\n): Promise<LongCommitSha> {\n logger.debug(`Checking out branch ${branchName} from remote ${remoteName}`);\n await syncGit();\n try {\n await gitRetry(() =>\n git.checkoutBranch(branchName, `${remoteName}/${branchName}`),\n );\n config.currentBranch = branchName;\n config.currentBranchSha = toLongCommitSha(\n (await git.revparse('HEAD')).trim(),\n );\n logger.debug(`Checked out branch ${branchName} from remote ${remoteName}`);\n config.branchCommits[branchName] = config.currentBranchSha;\n return config.currentBranchSha;\n } catch (err) {\n const errChecked = checkForPlatformFailure(err);\n /* v8 ignore if -- TODO: add test #40625 */\n if (errChecked) {\n throw errChecked;\n }\n if (err.message?.includes('fatal: ambiguous argument')) {\n logger.warn({ err }, 'Failed to checkout branch');\n throw new Error(TEMPORARY_ERROR);\n }\n throw err;\n }\n}\n\n/**\n * Returns the remote-tracking ref path for a virtual branch.\n */\nexport function remoteBranchRef(branchName: string): string {\n return `refs/remotes/origin/${branchName}`;\n}\n\n/**\n * Returns whether the given branch is tracked as a virtual branch.\n */\nfunction isVirtualBranch(branchName: string): boolean {\n return branchName in config.virtualBranches;\n}\n\n/**\n * Set a virtual branch's remote-tracking ref and add it to the\n * virtual-branch registry (config.virtualBranches).\n *\n * Used after pushing (to keep tracking in sync with the remote) and in\n * createPr() when the Gerrit change ref becomes available.\n *\n * @param branchName Virtual branch name to set\n * @param ref The ref this virtual branch is fetched from (e.g., 'refs/changes/34/1234/1')\n * @param commitSha The commit SHA the virtual branch points to.\n */\nexport async function setVirtualBranch(\n branchName: string,\n ref: string,\n commitSha: LongCommitSha,\n): Promise<void> {\n logger.debug({ branchName, ref, commitSha }, 'setVirtualBranch()');\n await git.raw(['update-ref', remoteBranchRef(branchName), commitSha]);\n config.branchCommits[branchName] = commitSha;\n config.virtualBranches[branchName] = { ref, sha: commitSha };\n config.branchIsModified[branchName] = false;\n}\n\nexport async function resetHardFromRemote(\n remoteAndBranch: string,\n): Promise<void> {\n try {\n const resetLog = await git.reset(['--hard', remoteAndBranch]);\n logger.debug({ resetLog }, 'git reset log');\n } catch (err) {\n logger.error({ err }, 'Error during git reset --hard');\n throw err;\n }\n}\n\nexport async function forcePushToRemote(\n branchName: string,\n remote: string,\n): Promise<void> {\n try {\n const pushLog = await git.push([remote, branchName, '--force']);\n logger.debug({ pushLog }, 'git push log');\n } catch (err) {\n logger.error({ err }, 'Error during git push --force');\n throw err;\n }\n}\n\nexport async function getFileList(): Promise<string[]> {\n await syncGit();\n const branch = config.currentBranch;\n let files: string;\n try {\n files = await git.raw(['ls-tree', '-r', `refs/heads/${branch}`]);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (err.message?.includes('fatal: Not a valid object name')) {\n logger.debug(\n { err },\n 'Branch not found when checking branch list - aborting',\n );\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n /* v8 ignore if -- TODO: add test #40625 */\n if (!files) {\n return [];\n }\n // submodules are starting with `160000 commit`\n return files\n .split(newlineRegex)\n .filter(isString)\n .filter((line) => line.startsWith('100'))\n .map((line) => line.split(regEx(/\\t/)).pop()!);\n}\n\nexport function getBranchList(): string[] {\n return Object.keys(config.branchCommits ?? {});\n}\n\nexport async function isBranchBehindBase(\n branchName: string,\n baseBranch: string,\n): Promise<boolean> {\n const baseBranchSha = getBranchCommit(baseBranch);\n const branchSha = getBranchCommit(branchName);\n let isBehind = getCachedBehindBaseResult(\n branchName,\n branchSha,\n baseBranch,\n baseBranchSha,\n );\n if (isBehind !== null) {\n logger.debug(`branch.isBehindBase(): using cached result \"${isBehind}\"`);\n return isBehind;\n }\n\n logger.debug(\n `branch.isBehindBase(): using git to calculate against baseBranch \"${baseBranch}\"`,\n );\n\n await syncGit();\n try {\n const behindCount = (\n await git.raw(['rev-list', '--count', `${branchSha!}..${baseBranchSha!}`])\n ).trim();\n isBehind = behindCount !== '0';\n logger.debug(\n { baseBranch, branchName },\n `branch.isBehindBase(): ${isBehind}`,\n );\n setCachedBehindBaseResult(branchName, isBehind);\n return isBehind;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n throw err;\n }\n}\n\nexport async function isBranchModified(\n branchName: string,\n baseBranch: string,\n): Promise<boolean> {\n if (!branchExists(branchName)) {\n logger.debug('branch.isModified(): no cache');\n return false;\n }\n // First check local config\n if (config.branchIsModified[branchName] !== undefined) {\n return config.branchIsModified[branchName];\n }\n // Second check repository cache\n const isModified = getCachedModifiedResult(\n branchName,\n getBranchCommit(branchName), // branch sha\n );\n if (isModified !== null) {\n logger.debug(`branch.isModified(): using cached result \"${isModified}\"`);\n config.branchIsModified[branchName] = isModified;\n return isModified;\n }\n\n logger.debug(\n `branch.isModified(): using git to calculate against baseBranch \"${baseBranch}\"`,\n );\n\n await syncGit();\n const committedAuthors = new Set<string>();\n try {\n const commits = await git.log([\n `origin/${baseBranch}..origin/${branchName}`,\n ]);\n\n for (const commit of commits.all) {\n committedAuthors.add(commit.author_email);\n }\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (err.message?.includes('fatal: bad revision')) {\n logger.debug(\n { err },\n 'Remote branch not found when checking last commit author - aborting run',\n );\n throw new Error(REPOSITORY_CHANGED);\n }\n logger.warn({ err }, 'Error checking last author for isBranchModified');\n }\n const { gitAuthorEmail, ignoredAuthors } = config;\n\n const includedAuthors = new Set(committedAuthors);\n\n // v8 ignore else -- TODO: add test #40625\n if (gitAuthorEmail) {\n includedAuthors.delete(gitAuthorEmail);\n }\n\n for (const ignoredAuthor of ignoredAuthors) {\n includedAuthors.delete(ignoredAuthor);\n }\n\n if (includedAuthors.size === 0) {\n // authors all match - branch has not been modified\n logger.trace(\n {\n branchName,\n baseBranch,\n committedAuthors: [...committedAuthors],\n includedAuthors: [...includedAuthors],\n gitAuthorEmail,\n ignoredAuthors,\n },\n 'branch.isModified() = false',\n );\n logger.debug('branch.isModified() = false');\n config.branchIsModified[branchName] = false;\n setCachedModifiedResult(branchName, false);\n return false;\n }\n logger.trace(\n {\n branchName,\n baseBranch,\n committedAuthors: [...committedAuthors],\n includedAuthors: [...includedAuthors],\n gitAuthorEmail,\n ignoredAuthors,\n },\n 'branch.isModified() = true',\n );\n logger.debug(\n { baseBranch, branchName, unrecognizedAuthors: [...includedAuthors] },\n 'branch.isModified() = true',\n );\n config.branchIsModified[branchName] = true;\n setCachedModifiedResult(branchName, true);\n return true;\n}\n\nexport async function isBranchConflicted(\n baseBranch: string,\n branch: string,\n): Promise<boolean> {\n logger.debug(`isBranchConflicted(${baseBranch}, ${branch})`);\n\n const baseBranchSha = getBranchCommit(baseBranch);\n const branchSha = getBranchCommit(branch);\n if (!baseBranchSha || !branchSha) {\n logger.warn(\n { baseBranch, branch },\n 'isBranchConflicted: branch does not exist',\n );\n return true;\n }\n\n const isConflicted = getCachedConflictResult(\n branch,\n branchSha,\n baseBranch,\n baseBranchSha,\n );\n if (isBoolean(isConflicted)) {\n logger.debug(\n `branch.isConflicted(): using cached result \"${isConflicted}\"`,\n );\n return isConflicted;\n }\n\n logger.debug(\n `branch.isConflicted(): using git to calculate against baseBranch ${baseBranch}`,\n );\n\n let result = false;\n await syncGit();\n await writeGitAuthor();\n\n const origBranch = config.currentBranch;\n try {\n await git.reset(ResetMode.HARD);\n //TODO: see #18600\n if (origBranch !== baseBranch) {\n await git.checkout(baseBranch);\n }\n await git.merge(['--no-commit', '--no-ff', `origin/${branch}`]);\n } catch (err) {\n result = true;\n /* v8 ignore if -- TODO: add test #40625 */\n if (!err?.git?.conflicts?.length) {\n logger.debug(\n { baseBranch, branch, err },\n 'isBranchConflicted: unknown error',\n );\n }\n } finally {\n try {\n await git.merge(['--abort']);\n if (origBranch !== baseBranch) {\n await git.checkout(origBranch);\n }\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.debug(\n { baseBranch, branch, err },\n 'isBranchConflicted: cleanup error',\n );\n }\n }\n\n setCachedConflictResult(branch, result);\n logger.debug(`branch.isConflicted(): ${result}`);\n return result;\n}\n\nexport async function deleteBranch(branchName: string): Promise<void> {\n await syncGit();\n if (isVirtualBranch(branchName)) {\n // Delete the remote-tracking ref.\n // Note: git update-ref -d succeeds even if the ref doesn't exist.\n const ref = remoteBranchRef(branchName);\n logger.debug({ branchName, ref }, 'Deleting virtual branch');\n await git.raw(['update-ref', '-d', ref]);\n delete config.virtualBranches[branchName];\n } else {\n try {\n const deleteCommand = ['push', '--delete', 'origin', branchName];\n\n if (getNoVerify().includes('push')) {\n deleteCommand.push('--no-verify');\n }\n\n await gitRetry(() => git.raw(deleteCommand));\n logger.debug(`Deleted remote branch: ${branchName}`);\n } catch (err) {\n const errChecked = checkForPlatformFailure(err);\n /* v8 ignore if -- TODO: add test #40625 */\n if (errChecked) {\n throw errChecked;\n }\n logger.debug(`No remote branch to delete with name: ${branchName}`);\n }\n }\n try {\n await deleteLocalBranch(branchName);\n /* v8 ignore next -- TODO: add test #40625 (always throws) */\n logger.debug(`Deleted local branch: ${branchName}`);\n } catch (err) {\n const errChecked = checkForPlatformFailure(err);\n /* v8 ignore if -- TODO: add test #40625 */\n if (errChecked) {\n throw errChecked;\n }\n logger.debug(`No local branch to delete with name: ${branchName}`);\n }\n delete config.branchCommits[branchName];\n}\n\nexport async function mergeToLocal(branchName: string): Promise<void> {\n let status: StatusResult | undefined;\n try {\n await syncGit();\n await writeGitAuthor();\n await git.reset(ResetMode.HARD);\n await gitRetry(() =>\n git.checkout([\n '-B',\n config.currentBranch,\n `origin/${config.currentBranch}`,\n ]),\n );\n status = await git.status();\n if (isVirtualBranch(branchName)) {\n // Virtual branches are already local and tracked as a remote-tracking ref,\n // so merge it directly without fetching from origin.\n const ref = remoteBranchRef(branchName);\n logger.debug(\n { branchName, ref },\n 'mergeToLocal(): merging virtual branch',\n );\n await git.merge([ref]);\n } else {\n await fetchRevSpec(branchName);\n await gitRetry(() => git.merge(['FETCH_HEAD']));\n }\n } catch (err) {\n logger.debug(\n {\n baseBranch: config.currentBranch,\n baseSha: config.currentBranchSha,\n branchName,\n status,\n err,\n },\n 'mergeLocally error',\n );\n throw err;\n }\n}\n\nexport async function mergeBranch(branchName: string): Promise<void> {\n let status: StatusResult | undefined;\n try {\n await syncGit();\n await writeGitAuthor();\n await git.reset(ResetMode.HARD);\n await gitRetry(() =>\n git.checkout(['-B', branchName, `origin/${branchName}`]),\n );\n await gitRetry(() =>\n git.checkout([\n '-B',\n config.currentBranch,\n `origin/${config.currentBranch}`,\n ]),\n );\n status = await git.status();\n await gitRetry(() => git.merge(['--ff-only', branchName]));\n await gitRetry(() => git.push('origin', config.currentBranch));\n incLimitedValue('Commits');\n } catch (err) {\n logger.debug(\n {\n baseBranch: config.currentBranch,\n baseSha: config.currentBranchSha,\n branchName,\n branchSha: getBranchCommit(branchName),\n status,\n err,\n },\n 'mergeBranch error',\n );\n throw err;\n }\n}\n\nasync function getCommitDate(ref: LongCommitSha | string): Promise<DateTime> {\n const output = await git.show(['-s', '--format=%cI', ref]);\n return DateTime.fromISO(output.trim()).toUTC();\n}\n\nexport async function getBranchLastCommitTime(\n branchName: string,\n): Promise<Date> {\n await syncGit();\n try {\n const time = await getCommitDate(`origin/${branchName}`);\n return time.toJSDate();\n } catch (err) {\n const errChecked = checkForPlatformFailure(err);\n /* v8 ignore next 3 -- TODO: add test */\n if (errChecked) {\n throw errChecked;\n }\n return new Date();\n }\n}\n\nexport function getBranchFiles(branchName: string): Promise<string[] | null> {\n return getBranchFilesFromRef(`origin/${branchName}`);\n}\n\nexport function getBranchFilesFromCommit(\n referenceCommit: LongCommitSha,\n): Promise<string[] | null> {\n return getBranchFilesFromRef(referenceCommit);\n}\n\nasync function getBranchFilesFromRef(\n refName: string,\n): Promise<string[] | null> {\n await syncGit();\n try {\n const diff = await gitRetry(() =>\n git.diffSummary([refName, `${refName}^`]),\n );\n return diff.files.map((file) => file.file);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.warn({ err }, 'getBranchFilesFromRef error');\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n return null;\n }\n}\n\nexport async function getFile(\n filePath: string,\n branchName?: string,\n): Promise<string | null> {\n await syncGit();\n try {\n const content = await git.show([\n `origin/${branchName ?? config.currentBranch}:${filePath}`,\n ]);\n\n logWarningIfUnicodeHiddenCharactersInPackageFile(filePath, content);\n\n return content;\n } catch (err) {\n const errChecked = checkForPlatformFailure(err);\n /* v8 ignore if -- TODO: add test #40625 */\n if (errChecked) {\n throw errChecked;\n }\n return null;\n }\n}\n\nexport async function getFiles(\n fileNames: string[],\n): Promise<Record<string, string | null>> {\n const fileContentMap: Record<string, string | null> = {};\n\n for (const fileName of fileNames) {\n fileContentMap[fileName] = await getFile(fileName);\n }\n\n return fileContentMap;\n}\n\nexport async function hasDiff(\n sourceRef: string,\n targetRef: string,\n): Promise<boolean> {\n await syncGit();\n try {\n return (\n (await gitRetry(() => git.diff([sourceRef, targetRef, '--']))) !== ''\n );\n } catch {\n return true;\n }\n}\n\nasync function handleCommitAuth(localDir: string): Promise<void> {\n if (!privateKeySet) {\n await writePrivateKey();\n privateKeySet = true;\n }\n await configSigningKey(localDir);\n await writeGitAuthor();\n}\n\n/**\n *\n * Prepare local branch with commit\n *\n * 0. Hard reset\n * 1. Creates local branch with `origin/` prefix\n * 2. Perform `git add` (respecting mode) and `git remove` for each file\n * 3. Perform commit\n * 4. Check whether resulting commit is empty or not (due to .gitignore)\n * 5. If not empty, return commit info for further processing\n *\n */\nexport async function prepareCommit({\n branchName,\n files,\n message,\n force = false,\n}: CommitFilesConfig): Promise<CommitResult | null> {\n const localDir = GlobalConfig.get('localDir');\n await syncGit();\n logger.debug(`Preparing files for committing to branch ${branchName}`);\n await handleCommitAuth(localDir);\n try {\n await git.reset(ResetMode.HARD);\n await git.raw(['clean', '-fd']);\n const parentCommitSha = config.currentBranchSha;\n await gitRetry(() =>\n git.checkout(['-B', branchName, `origin/${config.currentBranch}`]),\n );\n const deletedFiles: string[] = [];\n const addedModifiedFiles: string[] = [];\n const ignoredFiles: string[] = [];\n for (const file of files) {\n const fileName = file.path;\n if (file.type === 'deletion') {\n try {\n await git.rm([fileName]);\n deletedFiles.push(fileName);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n const errChecked = checkForPlatformFailure(err);\n if (errChecked) {\n throw errChecked;\n }\n logger.trace({ err, fileName }, 'Cannot delete file');\n ignoredFiles.push(fileName);\n }\n } else {\n if (await isDirectory(upath.join(localDir, fileName))) {\n // This is usually a git submodule update\n logger.trace({ fileName }, 'Adding directory commit');\n } else if (file.contents === null) {\n continue;\n } else {\n let contents: Buffer;\n /* v8 ignore else -- TODO: add test #40625 */\n if (typeof file.contents === 'string') {\n contents = Buffer.from(file.contents);\n } else {\n contents = file.contents;\n }\n // some file systems including Windows don't support the mode\n // so the index should be manually updated after adding the file\n if (file.isSymlink) {\n await fs.symlink(file.contents, upath.join(localDir, fileName));\n } else {\n await fs.outputFile(upath.join(localDir, fileName), contents, {\n mode: file.isExecutable ? 0o777 : 0o666,\n });\n }\n }\n try {\n /* v8 ignore next -- TODO: add test #40625 */\n const addParams =\n fileName === getConfigFileNames()[0] ? ['-f', fileName] : fileName;\n await git.add(addParams);\n if (file.isExecutable) {\n await git.raw(['update-index', '--chmod=+x', fileName]);\n }\n addedModifiedFiles.push(fileName);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (\n !err.message.includes(\n 'The following paths are ignored by one of your .gitignore files',\n )\n ) {\n throw err;\n }\n logger.debug(`Cannot commit ignored file: ${fileName}`);\n ignoredFiles.push(file.path);\n }\n }\n }\n\n const commitOptions: Options = {};\n if (getNoVerify().includes('commit')) {\n commitOptions['--no-verify'] = null;\n }\n\n const commitRes = await git.commit(message, [], commitOptions);\n if (\n isNonEmptyObject(commitRes.summary) &&\n commitRes.summary.changes === 0 &&\n commitRes.summary.insertions === 0 &&\n commitRes.summary.deletions === 0\n ) {\n logger.warn({ commitRes }, 'Detected empty commit - aborting git push');\n return null;\n }\n logger.debug(\n { deletedFiles, ignoredFiles, result: commitRes },\n `git commit`,\n );\n if (!force && !(await hasDiff('HEAD', `origin/${branchName}`))) {\n logger.debug(\n { branchName, deletedFiles, addedModifiedFiles, ignoredFiles },\n 'No file changes detected. Skipping commit',\n );\n return null;\n }\n\n const commitSha = toLongCommitSha(\n (await git.revparse([branchName])).trim(),\n );\n const result: CommitResult = {\n parentCommitSha,\n commitSha,\n files: files.filter((fileChange) => {\n if (fileChange.type === 'deletion') {\n return deletedFiles.includes(fileChange.path);\n }\n return addedModifiedFiles.includes(fileChange.path);\n }),\n };\n\n return result;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n return handleCommitError(err, branchName, files);\n }\n}\n\nexport async function pushCommit({\n sourceRef,\n targetRef,\n files,\n pushOptions,\n}: PushFilesConfig): Promise<boolean> {\n await syncGit();\n logger.debug(`Pushing refSpec ${sourceRef}:${targetRef ?? sourceRef}`);\n let result = false;\n try {\n const gitOptions: TaskOptions = {\n '--force-with-lease': null,\n '-u': null,\n };\n if (getNoVerify().includes('push')) {\n gitOptions['--no-verify'] = null;\n }\n if (pushOptions) {\n gitOptions['--push-option'] = pushOptions;\n }\n\n const pushRes = await gitRetry(() =>\n git.push('origin', `${sourceRef}:${targetRef ?? sourceRef}`, gitOptions),\n );\n delete pushRes.repo;\n logger.debug({ result: pushRes }, 'git push');\n incLimitedValue('Commits');\n incCountValue('HourlyCommits');\n result = true;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n handleCommitError(err, sourceRef, files);\n }\n return result;\n}\n\nexport async function fetchBranch(\n branchName: string,\n): Promise<LongCommitSha | null> {\n await syncGit();\n logger.debug(`Fetching branch ${branchName}`);\n try {\n const ref = `refs/heads/${branchName}:${remoteBranchRef(branchName)}`;\n await gitRetry(() => git.pull(['origin', ref, '--force']));\n const commit = toLongCommitSha((await git.revparse([branchName])).trim());\n config.branchCommits[branchName] = commit;\n config.branchIsModified[branchName] = false;\n return commit;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n return handleCommitError(err, branchName);\n }\n}\n\nexport async function commitFiles(\n commitConfig: CommitFilesConfig,\n): Promise<LongCommitSha | null> {\n try {\n const commitResult = await prepareCommit(commitConfig);\n if (commitResult) {\n const pushResult = await pushCommit({\n sourceRef: commitConfig.branchName,\n files: commitConfig.files,\n });\n // v8 ignore else -- TODO: add test #40625\n if (pushResult) {\n const { branchName } = commitConfig;\n const { commitSha } = commitResult;\n config.branchCommits[branchName] = commitSha;\n config.branchIsModified[branchName] = false;\n return commitSha;\n }\n }\n return null;\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n if (err.message.includes('[rejected] (stale info)')) {\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n}\n\nexport function getUrl({\n protocol,\n auth,\n hostname,\n host,\n repository,\n}: {\n protocol?: GitProtocol;\n auth?: string;\n hostname?: string;\n host?: string;\n repository: string;\n}): string {\n if (protocol === 'ssh') {\n // TODO: types (#22198)\n return `git@${hostname!}:${repository}.git`;\n }\n return URL.format({\n protocol: protocol ?? 'https',\n auth,\n hostname,\n host,\n pathname: `${repository}.git`,\n });\n}\n\nlet remoteRefsExist = false;\n\n/**\n *\n * Non-branch refs allow us to store git objects without triggering CI pipelines.\n * It's useful for API-based branch rebasing.\n *\n * @see https://stackoverflow.com/questions/63866947/pushing-git-non-branch-references-to-a-remote/63868286\n *\n */\nexport async function pushCommitToRenovateRef(\n commitSha: string,\n refName: string,\n): Promise<void> {\n const fullRefName = `refs/renovate/branches/${refName}`;\n await git.raw(['update-ref', fullRefName, commitSha]);\n await git.push(['--force', 'origin', fullRefName]);\n remoteRefsExist = true;\n}\n\n/**\n *\n * Removes all remote \"refs/renovate/branches/*\" refs in two steps:\n *\n * Step 1: list refs\n *\n * $ git ls-remote origin \"refs/renovate/branches/*\"\n *\n * > cca38e9ea6d10946bdb2d0ca5a52c205783897aa refs/renovate/branches/foo\n * > 29ac154936c880068994e17eb7f12da7fdca70e5 refs/renovate/branches/bar\n * > 3fafaddc339894b6d4f97595940fd91af71d0355 refs/renovate/branches/baz\n * > ...\n *\n * Step 2:\n *\n * $ git push --delete origin refs/renovate/branches/foo refs/renovate/branches/bar refs/renovate/branches/baz\n *\n * If Step 2 fails because the repo doesn't allow bulk changes, we'll remove them one by one instead:\n *\n * $ git push --delete origin refs/renovate/branches/foo\n * $ git push --delete origin refs/renovate/branches/bar\n * $ git push --delete origin refs/renovate/branches/baz\n */\nexport async function clearRenovateRefs(): Promise<void> {\n if (!gitInitialized || !remoteRefsExist) {\n return;\n }\n\n logger.debug(`Cleaning up Renovate refs: refs/renovate/branches/*`);\n const renovateRefs: string[] = [];\n\n try {\n const rawOutput = await git.listRemote([\n config.url,\n 'refs/renovate/branches/*',\n ]);\n const refs = rawOutput\n .split(newlineRegex)\n .map((line) => line.replace(regEx(/[0-9a-f]+\\s+/i), '').trim())\n .filter((line) => line.startsWith('refs/renovate/branches/'));\n renovateRefs.push(...refs);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.warn({ err }, `Renovate refs cleanup error`);\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (renovateRefs.length) {\n try {\n const pushOpts = ['--delete', 'origin', ...renovateRefs];\n await git.push(pushOpts);\n } catch (err) {\n /* v8 ignore else -- TODO: add test #40625 */\n if (bulkChangesDisallowed(err)) {\n for (const ref of renovateRefs) {\n try {\n const pushOpts = ['--delete', 'origin', ref];\n await git.push(pushOpts);\n } catch (err) /* v8 ignore next -- TODO: add test #40625 */ {\n logger.debug({ err }, 'Error deleting \"refs/renovate/branches/*\"');\n break;\n }\n }\n } else {\n logger.warn({ err }, 'Error deleting \"refs/renovate/branches/*\"');\n }\n }\n }\n\n remoteRefsExist = false;\n}\n\nconst diffTreeLineRegex = regEx(\n /^:(?<oldMode>\\d{6})\\s+(?<newMode>\\d{6})\\s+(?<oldSha>[0-9a-f]{40})\\s+(?<newSha>[0-9a-f]{40})\\s+(?<status>[A-Z]\\d*)\\t(?<paths>.+)$/,\n);\n\nconst treeShaRegex = regEx(/tree\\s+(?<treeSha>[0-9a-f]{40})\\s*/);\n\n/**\n * Get the tree SHA for a commit.\n */\nexport async function getCommitTreeSha(\n commitSha: LongCommitSha,\n): Promise<LongCommitSha> {\n const commitOutput = await git.catFile(['-p', commitSha]);\n const { treeSha } = treeShaRegex.exec(commitOutput)?.groups ?? {};\n if (!treeSha) {\n const snippet = commitOutput.split(newlineRegex)[0];\n /* v8 ignore next -- tested, but v8 reports template literal as partial */\n throw new Error(\n `Could not extract tree SHA from commit ${commitSha}: ${snippet}`,\n );\n }\n return toLongCommitSha(treeSha);\n}\n\nfunction treeTypeFromMode(mode: string): GitObjectType {\n switch (mode) {\n case GitTreeMode.Gitlink:\n return 'commit';\n case GitTreeMode.Directory:\n return 'tree';\n default:\n return 'blob';\n }\n}\n\n/**\n * Return only the files that changed between two commits.\n * Deletions have `sha: null` (for use with GitHub's `base_tree` API).\n */\nexport async function diffCommitTree(\n parentCommitSha: LongCommitSha,\n commitSha: LongCommitSha,\n): Promise<DiffTreeItem[]> {\n const output = await git.raw([\n 'diff-tree',\n '-M',\n '-r',\n '--no-commit-id',\n parentCommitSha,\n commitSha,\n ]);\n const result: DiffTreeItem[] = [];\n for (const line of output.split(newlineRegex)) {\n const matchGroups = diffTreeLineRegex.exec(line)?.groups;\n if (matchGroups) {\n const { oldMode, newMode, newSha, status, paths } = matchGroups;\n const statusCode = status[0];\n // R has two tab-separated paths (old\\tnew); A/M/D/T have one.\n // C also has two paths but falls through to default (only the target matters).\n const [sourcePath, targetPath] = paths.split('\\t');\n switch (statusCode) {\n case 'D':\n result.push({\n path: sourcePath,\n mode: oldMode,\n type: treeTypeFromMode(oldMode),\n sha: null,\n });\n break;\n case 'R':\n // Rename: delete source, add target\n result.push({\n path: sourcePath,\n mode: oldMode,\n type: treeTypeFromMode(oldMode),\n sha: null,\n });\n result.push({\n path: targetPath,\n mode: newMode,\n type: treeTypeFromMode(newMode),\n sha: toLongCommitSha(newSha),\n });\n break;\n default:\n // A (add), M (modify), T (type change), C (copy)\n result.push({\n path: targetPath ?? sourcePath,\n mode: newMode,\n type: treeTypeFromMode(newMode),\n sha: toLongCommitSha(newSha),\n });\n break;\n }\n }\n }\n return result;\n}\n\nasync function localBranchExists(branchName: string): Promise<boolean> {\n await syncGit();\n const localBranches = await git.branchLocal();\n return localBranches.all.includes(branchName);\n}\n\n/**\n * Synchronize a forked branch with its upstream counterpart.\n *\n * syncForkWithUpstream updates the fork's branch, to match the corresponding branch in the upstream repository.\n * The steps are:\n * 1. Check if the branch exists locally.\n * 2. If the branch exists locally: checkout the local branch.\n * 3. If the branch does _not_ exist locally: checkout the upstream branch.\n * 4. Reset the local branch to match the upstream branch.\n * 5. Force push the (updated) local branch to the origin repository.\n *\n * @param {string} branchName - The name of the branch to synchronize.\n * @returns A promise that resolves to True if the synchronization is successful, or `false` if an error occurs.\n */\nexport async function syncForkWithUpstream(branchName: string): Promise<void> {\n if (!config.upstreamUrl) {\n return;\n }\n logger.debug(\n `Synchronizing fork with \"${RENOVATE_FORK_UPSTREAM}\" remote for branch ${branchName}`,\n );\n const remotes = await getRemotes();\n /* v8 ignore if -- this should not be possible if upstreamUrl exists */\n if (!remotes.some((r) => r === RENOVATE_FORK_UPSTREAM)) {\n throw new Error('No upstream remote exists, cannot sync fork');\n }\n try {\n await git.fetch([RENOVATE_FORK_UPSTREAM]);\n if (await localBranchExists(branchName)) {\n await checkoutBranch(branchName);\n } else {\n await checkoutBranchFromRemote(branchName, RENOVATE_FORK_UPSTREAM);\n }\n await resetHardFromRemote(`${RENOVATE_FORK_UPSTREAM}/${branchName}`);\n await forcePushToRemote(branchName, 'origin');\n } catch (err) /* v8 ignore next -- shouldn't happen */ {\n logger.error({ err }, 'Error synchronizing fork');\n throw new Error(UNKNOWN_ERROR);\n }\n}\n\nexport async function getRemotes(): Promise<string[]> {\n logger.debug('git.getRemotes()');\n try {\n await syncGit();\n const remotes = await git.getRemotes();\n logger.debug(`Found remotes: ${remotes.map((r) => r.name).join(', ')}`);\n return remotes.map((remote) => remote.name);\n } catch (err) /* v8 ignore next */ {\n logger.error({ err }, 'Error getting remotes');\n throw err;\n }\n}\n"],"mappings":"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"}
|
package/dist/util/git/types.d.ts
CHANGED
|
@@ -5,6 +5,17 @@ import { PlatformCommitOptions } from "../../config/types.js";
|
|
|
5
5
|
import { StatusResult } from "simple-git";
|
|
6
6
|
//#region lib/util/git/types.d.ts
|
|
7
7
|
type GitNoVerifyOption = 'commit' | 'push';
|
|
8
|
+
/**
|
|
9
|
+
* Represents a virtual branch tracked as `refs/remotes/origin/<name>`.
|
|
10
|
+
* Used by platforms like Gerrit where changes are represented as refs
|
|
11
|
+
* (e.g., refs/changes/34/1234/1) instead of regular branches.
|
|
12
|
+
*/
|
|
13
|
+
interface VirtualBranch {
|
|
14
|
+
/** The ref this virtual branch is fetched from (e.g., 'refs/changes/34/1234/1') */
|
|
15
|
+
ref: string;
|
|
16
|
+
/** The commit SHA this virtual branch points to */
|
|
17
|
+
sha: LongCommitSha;
|
|
18
|
+
}
|
|
8
19
|
interface StorageConfig {
|
|
9
20
|
currentBranch?: string;
|
|
10
21
|
defaultBranch?: string;
|
|
@@ -14,6 +25,12 @@ interface StorageConfig {
|
|
|
14
25
|
cloneSubmodules?: boolean;
|
|
15
26
|
cloneSubmodulesFilter?: string[];
|
|
16
27
|
fullClone?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Virtual branches to initialize from non-standard refs (e.g., Gerrit change refs).
|
|
30
|
+
* Each virtual branch is fetched and stored as refs/remotes/origin/<name>.
|
|
31
|
+
* Keyed by branch name.
|
|
32
|
+
*/
|
|
33
|
+
virtualBranches?: Record<string, VirtualBranch>;
|
|
17
34
|
}
|
|
18
35
|
interface FileAddition {
|
|
19
36
|
/**
|
|
@@ -145,5 +162,5 @@ type GitOperationType =
|
|
|
145
162
|
*/
|
|
146
163
|
'other';
|
|
147
164
|
//#endregion
|
|
148
|
-
export { CommitFilesConfig, CommitResult, DiffTreeItem, FileAddition, FileChange, FileDeletion, GitNoVerifyOption, GitObjectType, GitOperationType, PushFilesConfig, type StatusResult, StorageConfig };
|
|
165
|
+
export { CommitFilesConfig, CommitResult, DiffTreeItem, FileAddition, FileChange, FileDeletion, GitNoVerifyOption, GitObjectType, GitOperationType, PushFilesConfig, type StatusResult, StorageConfig, VirtualBranch };
|
|
149
166
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../../lib/util/git/types.ts"],"sourcesContent":["import type { PlatformCommitOptions } from '../../config/types.ts';\nimport type { GitOptions } from '../../types/git.ts';\nimport type { LongCommitSha } from '../schema-utils/git.ts';\nimport type { EmailAddress } from '../schema-utils/index.ts';\n\nexport type { DiffResult, StatusResult } from 'simple-git';\n\nexport interface GitAuthor {\n name?: string | null;\n address?: string;\n}\n\nexport type GitNoVerifyOption = 'commit' | 'push';\n\nexport interface StorageConfig {\n currentBranch?: string;\n defaultBranch?: string;\n url: string;\n upstreamUrl?: string | undefined;\n extraCloneOpts?: GitOptions;\n cloneSubmodules?: boolean;\n cloneSubmodulesFilter?: string[];\n fullClone?: boolean;\n}\n\nexport interface LocalConfig extends StorageConfig {\n additionalBranches: string[];\n currentBranch: string;\n currentBranchSha: LongCommitSha;\n branchCommits: Record<string, LongCommitSha>;\n branchIsModified: Record<string, boolean>;\n commitBranches: Record<string, string[]>;\n ignoredAuthors: string[];\n gitAuthorName?: string | null;\n gitAuthorEmail?: EmailAddress;\n fileModeEnabled?: boolean;\n\n writeGitDone?: boolean;\n}\n\nexport interface FileAddition {\n /**\n * Addition creates new file or modifies existing one\n */\n type: 'addition';\n\n /**\n * Relative file path\n */\n path: string;\n\n /**\n * File contents\n */\n contents: string | Buffer | null;\n\n /**\n * The executable bit\n */\n isExecutable?: boolean;\n\n isSymlink?: boolean;\n}\n\nexport interface FileDeletion {\n /**\n * Deletion removes the file\n */\n type: 'deletion';\n\n /**\n * Relative file path\n */\n path: string;\n}\n\nexport type FileChange = FileAddition | FileDeletion;\n\nexport interface CommitFilesConfig {\n baseBranch?: string;\n branchName: string;\n files: FileChange[];\n message: string | string[];\n force?: boolean;\n platformCommit?: PlatformCommitOptions;\n /** Only needed by Gerrit platform */\n prTitle?: string;\n /** Only needed by Gerrit platform */\n autoApprove?: boolean;\n}\n\nexport interface PushFilesConfig {\n sourceRef: string;\n targetRef?: string;\n files: FileChange[];\n pushOptions?: string[];\n}\n\nexport type BranchName = string;\n\nexport interface CommitResult {\n parentCommitSha: LongCommitSha;\n commitSha: LongCommitSha;\n files: FileChange[];\n}\n\nexport type GitObjectType = 'blob' | 'tree' | 'commit';\n\n/**\n * Git tree entry modes (octal file-type representations).\n * @see https://git-scm.com/docs/gitdatamodel\n */\nexport const GitTreeMode = {\n /** Regular non-executable file */\n RegularFile: '100644',\n /** Regular executable file */\n ExecutableFile: '100755',\n /** Symbolic link */\n SymbolicLink: '120000',\n /** Directory / subtree */\n Directory: '040000',\n /** Gitlink (submodule) */\n Gitlink: '160000',\n} as const;\n\nexport interface DiffTreeItem {\n path: string;\n mode: string;\n type: GitObjectType;\n sha: LongCommitSha | null;\n}\n\n/**\n * Represents a git authentication rule in the form of e.g.:\n * git config --global url.\"https://api@github.com/\".insteadOf \"https://github.com/\"\n */\nexport interface AuthenticationRule {\n url: string;\n insteadOf: string;\n}\n\nexport type GitOperationType =\n /**\n * The `git clone` sub-command.\n */\n | 'clone'\n /**\n * The `git reset` sub-command.\n */\n | 'reset'\n /**\n * The `git checkout` sub-command.\n */\n | 'checkout'\n /**\n * The `git fetch` sub-command.\n */\n | 'fetch'\n /**\n * The `git pull` sub-command.\n */\n | 'pull'\n /**\n * The `git push` sub-command.\n */\n | 'push'\n /**\n * The `git clean` sub-command.\n */\n | 'clean'\n /**\n * The `git merge` sub-command.\n */\n | 'merge'\n /**\n * The `git submodule` sub-command.\n */\n | 'submodule'\n /**\n * The `git commit` sub-command.\n */\n | 'commit'\n /**\n * The `git branch` sub-command.\n */\n | 'branch'\n /**\n * Any internal \"plumbing\" commands\n *\n * - `git update-index`\n *\n * See also: https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain\n */\n | 'plumbing'\n /**\n * Any other operations i.e.\n *\n * - `git add`\n * - `git branch`\n * - `git config`\n * - `git diff`\n * - `git log`\n * - `git ls-remote`\n * - `git remote`\n * - `git rev-parse`\n * - `git status`\n *\n * See also: https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain\n */\n | 'other';\n"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../../lib/util/git/types.ts"],"sourcesContent":["import type { PlatformCommitOptions } from '../../config/types.ts';\nimport type { GitOptions } from '../../types/git.ts';\nimport type { LongCommitSha } from '../schema-utils/git.ts';\nimport type { EmailAddress } from '../schema-utils/index.ts';\n\nexport type { DiffResult, StatusResult } from 'simple-git';\n\nexport interface GitAuthor {\n name?: string | null;\n address?: string;\n}\n\nexport type GitNoVerifyOption = 'commit' | 'push';\n\n/**\n * Represents a virtual branch tracked as `refs/remotes/origin/<name>`.\n * Used by platforms like Gerrit where changes are represented as refs\n * (e.g., refs/changes/34/1234/1) instead of regular branches.\n */\nexport interface VirtualBranch {\n /** The ref this virtual branch is fetched from (e.g., 'refs/changes/34/1234/1') */\n ref: string;\n /** The commit SHA this virtual branch points to */\n sha: LongCommitSha;\n}\n\nexport interface StorageConfig {\n currentBranch?: string;\n defaultBranch?: string;\n url: string;\n upstreamUrl?: string | undefined;\n extraCloneOpts?: GitOptions;\n cloneSubmodules?: boolean;\n cloneSubmodulesFilter?: string[];\n fullClone?: boolean;\n /**\n * Virtual branches to initialize from non-standard refs (e.g., Gerrit change refs).\n * Each virtual branch is fetched and stored as refs/remotes/origin/<name>.\n * Keyed by branch name.\n */\n virtualBranches?: Record<string, VirtualBranch>;\n}\n\nexport interface LocalConfig extends StorageConfig {\n additionalBranches: string[];\n currentBranch: string;\n currentBranchSha: LongCommitSha;\n branchCommits: Record<string, LongCommitSha>;\n /** Single registry of virtual branches, always initialized in initRepo. Keyed by branch name. */\n virtualBranches: Record<string, VirtualBranch>;\n branchIsModified: Record<string, boolean>;\n commitBranches: Record<string, string[]>;\n ignoredAuthors: string[];\n gitAuthorName?: string | null;\n gitAuthorEmail?: EmailAddress;\n fileModeEnabled?: boolean;\n\n writeGitDone?: boolean;\n}\n\nexport interface FileAddition {\n /**\n * Addition creates new file or modifies existing one\n */\n type: 'addition';\n\n /**\n * Relative file path\n */\n path: string;\n\n /**\n * File contents\n */\n contents: string | Buffer | null;\n\n /**\n * The executable bit\n */\n isExecutable?: boolean;\n\n isSymlink?: boolean;\n}\n\nexport interface FileDeletion {\n /**\n * Deletion removes the file\n */\n type: 'deletion';\n\n /**\n * Relative file path\n */\n path: string;\n}\n\nexport type FileChange = FileAddition | FileDeletion;\n\nexport interface CommitFilesConfig {\n baseBranch?: string;\n branchName: string;\n files: FileChange[];\n message: string | string[];\n force?: boolean;\n platformCommit?: PlatformCommitOptions;\n /** Only needed by Gerrit platform */\n prTitle?: string;\n /** Only needed by Gerrit platform */\n autoApprove?: boolean;\n}\n\nexport interface PushFilesConfig {\n sourceRef: string;\n targetRef?: string;\n files: FileChange[];\n pushOptions?: string[];\n}\n\nexport type BranchName = string;\n\nexport interface CommitResult {\n parentCommitSha: LongCommitSha;\n commitSha: LongCommitSha;\n files: FileChange[];\n}\n\nexport type GitObjectType = 'blob' | 'tree' | 'commit';\n\n/**\n * Git tree entry modes (octal file-type representations).\n * @see https://git-scm.com/docs/gitdatamodel\n */\nexport const GitTreeMode = {\n /** Regular non-executable file */\n RegularFile: '100644',\n /** Regular executable file */\n ExecutableFile: '100755',\n /** Symbolic link */\n SymbolicLink: '120000',\n /** Directory / subtree */\n Directory: '040000',\n /** Gitlink (submodule) */\n Gitlink: '160000',\n} as const;\n\nexport interface DiffTreeItem {\n path: string;\n mode: string;\n type: GitObjectType;\n sha: LongCommitSha | null;\n}\n\n/**\n * Represents a git authentication rule in the form of e.g.:\n * git config --global url.\"https://api@github.com/\".insteadOf \"https://github.com/\"\n */\nexport interface AuthenticationRule {\n url: string;\n insteadOf: string;\n}\n\nexport type GitOperationType =\n /**\n * The `git clone` sub-command.\n */\n | 'clone'\n /**\n * The `git reset` sub-command.\n */\n | 'reset'\n /**\n * The `git checkout` sub-command.\n */\n | 'checkout'\n /**\n * The `git fetch` sub-command.\n */\n | 'fetch'\n /**\n * The `git pull` sub-command.\n */\n | 'pull'\n /**\n * The `git push` sub-command.\n */\n | 'push'\n /**\n * The `git clean` sub-command.\n */\n | 'clean'\n /**\n * The `git merge` sub-command.\n */\n | 'merge'\n /**\n * The `git submodule` sub-command.\n */\n | 'submodule'\n /**\n * The `git commit` sub-command.\n */\n | 'commit'\n /**\n * The `git branch` sub-command.\n */\n | 'branch'\n /**\n * Any internal \"plumbing\" commands\n *\n * - `git update-index`\n *\n * See also: https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain\n */\n | 'plumbing'\n /**\n * Any other operations i.e.\n *\n * - `git add`\n * - `git branch`\n * - `git config`\n * - `git diff`\n * - `git log`\n * - `git ls-remote`\n * - `git remote`\n * - `git rev-parse`\n * - `git status`\n *\n * See also: https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain\n */\n | 'other';\n"],"mappings":";;;;;AAoIA,MAAa,cAAc;;CAEzB,aAAa;;CAEb,gBAAgB;;CAEhB,cAAc;;CAEd,WAAW;;CAEX,SAAS;AACX"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "renovate",
|
|
3
3
|
"description": "Automated dependency updates. Flexible so you don't need to be.",
|
|
4
|
-
"version": "43.
|
|
4
|
+
"version": "43.269.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"renovate": "dist/renovate.js",
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
"@redis/client": "5.12.1",
|
|
118
118
|
"@renovatebot/detect-tools": "4.0.10",
|
|
119
119
|
"@renovatebot/good-enough-parser": "2.0.1",
|
|
120
|
-
"@renovatebot/osv-offline": "3.0.
|
|
120
|
+
"@renovatebot/osv-offline": "3.0.9",
|
|
121
121
|
"@renovatebot/pep440": "5.0.0",
|
|
122
122
|
"@renovatebot/pgp": "1.3.16",
|
|
123
123
|
"@renovatebot/ruby-semver": "5.0.0",
|
package/renovate-schema.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$id": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
-
"title": "JSON schema for Renovate 43.
|
|
3
|
+
"title": "JSON schema for Renovate 43.269.0 config files (https://renovatebot.com/)",
|
|
4
4
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
5
|
-
"x-renovate-version": "43.
|
|
5
|
+
"x-renovate-version": "43.269.0",
|
|
6
6
|
"allowComments": true,
|
|
7
7
|
"type": "object",
|
|
8
8
|
"definitions": {
|