From 65f77605c087408bbcd9625573126b12c4059ebf Mon Sep 17 00:00:00 2001 From: Nacho Orlandoni Date: Sat, 28 Oct 2023 11:30:25 -0400 Subject: [PATCH] Reference support * Add support for reference repository parameter --------- Co-authored-by: Diego Dompe --- README.md | 5 +++++ __test__/git-auth-helper.test.ts | 4 +++- __test__/git-directory-helper.test.ts | 1 + __test__/input-helper.test.ts | 1 + action.yml | 6 ++++++ dist/index.js | 20 ++++++++++++++++++++ src/git-command-manager.ts | 10 ++++++++++ src/git-source-provider.ts | 12 ++++++++++++ src/git-source-settings.ts | 10 ++++++++++ src/input-helper.ts | 3 +++ 10 files changed, 71 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bfecf464d..dd9d9fc32 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,11 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/ # Default: true show-progress: '' + # Path to a local bare git [reference repository to minimize network + # usage](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---reference-if-ableltrepositorygt). + # If the directory doesn't exists this option will ignore it and log a message. + reference: '' + # Whether to download Git-LFS files # Default: false lfs: '' diff --git a/__test__/git-auth-helper.test.ts b/__test__/git-auth-helper.test.ts index 411faed05..a16551b86 100644 --- a/__test__/git-auth-helper.test.ts +++ b/__test__/git-auth-helper.test.ts @@ -762,6 +762,7 @@ async function setup(testName: string): Promise { lfsInstall: jest.fn(), log1: jest.fn(), remoteAdd: jest.fn(), + referenceAdd: jest.fn(), removeEnvironmentVariable: jest.fn((name: string) => delete git.env[name]), revParse: jest.fn(), setEnvironmentVariable: jest.fn((name: string, value: string) => { @@ -821,7 +822,8 @@ async function setup(testName: string): Promise { sshStrict: true, workflowOrganizationId: 123456, setSafeDirectory: true, - githubServerUrl: githubServerUrl + githubServerUrl: githubServerUrl, + reference: '/some/path' } } diff --git a/__test__/git-directory-helper.test.ts b/__test__/git-directory-helper.test.ts index 362133f4c..8e25354ee 100644 --- a/__test__/git-directory-helper.test.ts +++ b/__test__/git-directory-helper.test.ts @@ -477,6 +477,7 @@ async function setup(testName: string): Promise { lfsInstall: jest.fn(), log1: jest.fn(), remoteAdd: jest.fn(), + referenceAdd: jest.fn(), removeEnvironmentVariable: jest.fn(), revParse: jest.fn(), setEnvironmentVariable: jest.fn(), diff --git a/__test__/input-helper.test.ts b/__test__/input-helper.test.ts index 9514cb42d..c14f17dfc 100644 --- a/__test__/input-helper.test.ts +++ b/__test__/input-helper.test.ts @@ -91,6 +91,7 @@ describe('input-helper tests', () => { expect(settings.repositoryOwner).toBe('some-owner') expect(settings.repositoryPath).toBe(gitHubWorkspace) expect(settings.setSafeDirectory).toBe(true) + expect(settings.reference).toBe(undefined) }) it('qualifies ref', async () => { diff --git a/action.yml b/action.yml index 5aa90a738..680458fe6 100644 --- a/action.yml +++ b/action.yml @@ -76,6 +76,12 @@ inputs: show-progress: description: 'Whether to show progress status output when fetching.' default: true + reference: + required: false + description: > + Path to a local bare git [reference repository to minimize network usage](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---reference-if-ableltrepositorygt). + + If the directory doesn't exists this option will ignore it and log a message. lfs: description: 'Whether to download Git-LFS files' default: false diff --git a/dist/index.js b/dist/index.js index ddf2b3d89..02aa5f48c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -732,6 +732,13 @@ class GitCommandManager { yield this.execGit(['remote', 'add', remoteName, remoteUrl]); }); } + referenceAdd(alternateObjects) { + return __awaiter(this, void 0, void 0, function* () { + const alternatePath = path.join(this.workingDirectory, '.git/objects/info/alternates'); + core.info(`Adding a git alternate to reference repo at ${alternateObjects}`); + yield fs.promises.writeFile(alternatePath, `${alternateObjects}\n`); + }); + } removeEnvironmentVariable(name) { delete this.gitEnv[name]; } @@ -1211,6 +1218,17 @@ function getSource(settings) { yield git.init(); yield git.remoteAdd('origin', repositoryUrl); core.endGroup(); + if (settings.reference !== undefined) { + const alternateObjects = path.join(settings.reference, '/objects'); + if (fsHelper.directoryExistsSync(alternateObjects, false)) { + core.startGroup('Adding a reference repository'); + yield git.referenceAdd(alternateObjects); + core.endGroup(); + } + else { + core.warning(`Reference repository was specified, but directory ${alternateObjects} does not exists`); + } + } } // Disable automatic garbage collection core.startGroup('Disabling automatic garbage collection'); @@ -1790,6 +1808,8 @@ function getInputs() { // Determine the GitHub URL that the repository is being hosted from result.githubServerUrl = core.getInput('github-server-url'); core.debug(`GitHub Host URL = ${result.githubServerUrl}`); + result.reference = core.getInput('reference'); + core.debug(`Reference repository = ${result.reference}`); return result; }); } diff --git a/src/git-command-manager.ts b/src/git-command-manager.ts index 7752cfa4d..930b9bdf6 100644 --- a/src/git-command-manager.ts +++ b/src/git-command-manager.ts @@ -45,6 +45,7 @@ export interface IGitCommandManager { lfsInstall(): Promise log1(format?: string): Promise remoteAdd(remoteName: string, remoteUrl: string): Promise + referenceAdd(reference: string): Promise removeEnvironmentVariable(name: string): void revParse(ref: string): Promise setEnvironmentVariable(name: string, value: string): void @@ -353,6 +354,15 @@ class GitCommandManager { await this.execGit(['remote', 'add', remoteName, remoteUrl]) } + async referenceAdd(alternateObjects: string): Promise { + const alternatePath = path.join( + this.workingDirectory, + '.git/objects/info/alternates' + ) + core.info(`Adding a git alternate to reference repo at ${alternateObjects}`) + await fs.promises.writeFile(alternatePath, `${alternateObjects}\n`) + } + removeEnvironmentVariable(name: string): void { delete this.gitEnv[name] } diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts index 5c98e9f73..1056a9a17 100644 --- a/src/git-source-provider.ts +++ b/src/git-source-provider.ts @@ -110,6 +110,18 @@ export async function getSource(settings: IGitSourceSettings): Promise { await git.init() await git.remoteAdd('origin', repositoryUrl) core.endGroup() + + if (settings.reference !== undefined) { + const alternateObjects = path.join(settings.reference, '/objects') + + if (fsHelper.directoryExistsSync(alternateObjects, false)) { + core.startGroup('Adding a reference repository') + await git.referenceAdd(alternateObjects) + core.endGroup() + } else { + core.warning(`Reference repository was specified, but directory ${alternateObjects} does not exists`); + } + } } // Disable automatic garbage collection diff --git a/src/git-source-settings.ts b/src/git-source-settings.ts index 629350b2c..7c36be946 100644 --- a/src/git-source-settings.ts +++ b/src/git-source-settings.ts @@ -49,6 +49,11 @@ export interface IGitSourceSettings { */ fetchDepth: number + /** + * The local reference repository + */ + reference: string | undefined + /** * Fetch tags, even if fetchDepth > 0 (default: false) */ @@ -59,6 +64,11 @@ export interface IGitSourceSettings { */ showProgress: boolean + /** + * The local reference repository + */ + reference: string | undefined + /** * Indicates whether to fetch LFS objects */ diff --git a/src/input-helper.ts b/src/input-helper.ts index e546c196d..04b174603 100644 --- a/src/input-helper.ts +++ b/src/input-helper.ts @@ -159,5 +159,8 @@ export async function getInputs(): Promise { result.githubServerUrl = core.getInput('github-server-url') core.debug(`GitHub Host URL = ${result.githubServerUrl}`) + result.reference = core.getInput('reference') + core.debug(`Reference repository = ${result.reference}`) + return result }