From e60e2497774ee58cb8a4afaecb7d42934f3dd034 Mon Sep 17 00:00:00 2001 From: Diego Dompe Date: Fri, 30 Jun 2023 15:14:41 -0600 Subject: [PATCH] Add support for reference repository parameter --- 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 | 5 +++++ src/input-helper.ts | 3 +++ 10 files changed, 66 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5427a50..de28269 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,11 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl # Default: 1 fetch-depth: '' + # 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 fec6573..bba2a87 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) => { @@ -818,7 +819,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 362133f..8e25354 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 069fda4..a8aeb81 100644 --- a/__test__/input-helper.test.ts +++ b/__test__/input-helper.test.ts @@ -88,6 +88,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 e562b56..d8b2674 100644 --- a/action.yml +++ b/action.yml @@ -65,6 +65,12 @@ inputs: fetch-depth: description: 'Number of commits to fetch. 0 indicates all history for all branches and tags.' default: 1 + 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 4556295..6c063e0 100644 --- a/dist/index.js +++ b/dist/index.js @@ -729,6 +729,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]; } @@ -1208,6 +1215,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'); @@ -1768,6 +1786,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 e684dba..eb3eda6 100644 --- a/src/git-command-manager.ts +++ b/src/git-command-manager.ts @@ -43,6 +43,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 @@ -343,6 +344,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 8f9d63f..be10659 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 3272e63..30e0cd1 100644 --- a/src/git-source-settings.ts +++ b/src/git-source-settings.ts @@ -44,6 +44,11 @@ export interface IGitSourceSettings { */ fetchDepth: number + /** + * 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 410e480..7c458b7 100644 --- a/src/input-helper.ts +++ b/src/input-helper.ts @@ -141,5 +141,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 }