diff options
| author | eric sciple <ericsciple@users.noreply.github.com> | 2020-05-27 09:54:28 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-27 09:54:28 -0400 |
| commit | 1af3b46e902378dcbdf104a32ddae1644c64c366 (patch) | |
| tree | eb40b22d94abbd6860bb2ec1eac5b1ca62ea542a /dist/index.js | |
| parent | 31d9f35c90667154e76ccca096898caab3e5bba7 (diff) | |
Fetch all history for all tags and branches when fetch-depth=0 (#258)
Diffstat (limited to 'dist/index.js')
| -rw-r--r-- | dist/index.js | 135 |
1 files changed, 116 insertions, 19 deletions
diff --git a/dist/index.js b/dist/index.js index 86601d1..0c78d25 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3383,6 +3383,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const url_1 = __webpack_require__(835); const core = __importStar(__webpack_require__(470)); const github = __importStar(__webpack_require__(469)); +exports.tagsRefSpec = '+refs/tags/*:refs/tags/*'; function getCheckoutInfo(git, ref, commit) { return __awaiter(this, void 0, void 0, function* () { if (!git) { @@ -3429,6 +3430,15 @@ function getCheckoutInfo(git, ref, commit) { }); } exports.getCheckoutInfo = getCheckoutInfo; +function getRefSpecForAllHistory(ref, commit) { + const result = ['+refs/heads/*:refs/remotes/origin/*', exports.tagsRefSpec]; + if (ref && ref.toUpperCase().startsWith('REFS/PULL/')) { + const branch = ref.substring('refs/pull/'.length); + result.push(`+${commit || ref}:refs/remotes/pull/${branch}`); + } + return result; +} +exports.getRefSpecForAllHistory = getRefSpecForAllHistory; function getRefSpec(ref, commit) { if (!ref && !commit) { throw new Error('Args ref and commit cannot both be empty'); @@ -3478,6 +3488,50 @@ function getRefSpec(ref, commit) { } } exports.getRefSpec = getRefSpec; +/** + * Tests whether the initial fetch created the ref at the expected commit + */ +function testRef(git, ref, commit) { + return __awaiter(this, void 0, void 0, function* () { + if (!git) { + throw new Error('Arg git cannot be empty'); + } + if (!ref && !commit) { + throw new Error('Args ref and commit cannot both be empty'); + } + // No SHA? Nothing to test + if (!commit) { + return true; + } + // SHA only? + else if (!ref) { + return yield git.shaExists(commit); + } + const upperRef = ref.toUpperCase(); + // refs/heads/ + if (upperRef.startsWith('REFS/HEADS/')) { + const branch = ref.substring('refs/heads/'.length); + return ((yield git.branchExists(true, `origin/${branch}`)) && + commit === (yield git.revParse(`refs/remotes/origin/${branch}`))); + } + // refs/pull/ + else if (upperRef.startsWith('REFS/PULL/')) { + // Assume matches because fetched using the commit + return true; + } + // refs/tags/ + else if (upperRef.startsWith('REFS/TAGS/')) { + const tagName = ref.substring('refs/tags/'.length); + return ((yield git.tagExists(tagName)) && commit === (yield git.revParse(ref))); + } + // Unexpected + else { + core.debug(`Unexpected ref format '${ref}' when testing ref info`); + return true; + } + }); +} +exports.testRef = testRef; function checkCommitInfo(token, commitInfo, repositoryOwner, repositoryName, ref, commit) { return __awaiter(this, void 0, void 0, function* () { try { @@ -5634,6 +5688,7 @@ const exec = __importStar(__webpack_require__(986)); const fshelper = __importStar(__webpack_require__(618)); const io = __importStar(__webpack_require__(1)); const path = __importStar(__webpack_require__(622)); +const refHelper = __importStar(__webpack_require__(227)); const regexpHelper = __importStar(__webpack_require__(528)); const retryHelper = __importStar(__webpack_require__(587)); const git_version_1 = __webpack_require__(559); @@ -5749,18 +5804,14 @@ class GitCommandManager { return output.exitCode === 0; }); } - fetch(fetchDepth, refSpec) { + fetch(refSpec, fetchDepth) { return __awaiter(this, void 0, void 0, function* () { - const args = [ - '-c', - 'protocol.version=2', - 'fetch', - '--no-tags', - '--prune', - '--progress', - '--no-recurse-submodules' - ]; - if (fetchDepth > 0) { + const args = ['-c', 'protocol.version=2', 'fetch']; + if (!refSpec.some(x => x === refHelper.tagsRefSpec)) { + args.push('--no-tags'); + } + args.push('--prune', '--progress', '--no-recurse-submodules'); + if (fetchDepth && fetchDepth > 0) { args.push(`--depth=${fetchDepth}`); } else if (fshelper.fileExistsSync(path.join(this.workingDirectory, '.git', 'shallow'))) { @@ -5819,9 +5870,28 @@ class GitCommandManager { removeEnvironmentVariable(name) { delete this.gitEnv[name]; } + /** + * Resolves a ref to a SHA. For a branch or lightweight tag, the commit SHA is returned. + * For an annotated tag, the tag SHA is returned. + * @param {string} ref For example: 'refs/heads/master' or '/refs/tags/v1' + * @returns {Promise<string>} + */ + revParse(ref) { + return __awaiter(this, void 0, void 0, function* () { + const output = yield this.execGit(['rev-parse', ref]); + return output.stdout.trim(); + }); + } setEnvironmentVariable(name, value) { this.gitEnv[name] = value; } + shaExists(sha) { + return __awaiter(this, void 0, void 0, function* () { + const args = ['rev-parse', '--verify', '--quiet', `${sha}^{object}`]; + const output = yield this.execGit(args, true); + return output.exitCode === 0; + }); + } submoduleForeach(command, recursive) { return __awaiter(this, void 0, void 0, function* () { const args = ['submodule', 'foreach']; @@ -6060,7 +6130,7 @@ function getSource(settings) { core.endGroup(); // Prepare existing directory, otherwise recreate if (isExisting) { - yield gitDirectoryHelper.prepareExistingDirectory(git, settings.repositoryPath, repositoryUrl, settings.clean); + yield gitDirectoryHelper.prepareExistingDirectory(git, settings.repositoryPath, repositoryUrl, settings.clean, settings.ref); } if (!git) { // Downloading using REST API @@ -6102,8 +6172,21 @@ function getSource(settings) { } // Fetch core.startGroup('Fetching the repository'); - const refSpec = refHelper.getRefSpec(settings.ref, settings.commit); - yield git.fetch(settings.fetchDepth, refSpec); + if (settings.fetchDepth <= 0) { + // Fetch all branches and tags + let refSpec = refHelper.getRefSpecForAllHistory(settings.ref, settings.commit); + yield git.fetch(refSpec); + // When all history is fetched, the ref we're interested in may have moved to a different + // commit (push or force push). If so, fetch again with a targeted refspec. + if (!(yield refHelper.testRef(git, settings.ref, settings.commit))) { + refSpec = refHelper.getRefSpec(settings.ref, settings.commit); + yield git.fetch(refSpec); + } + } + else { + const refSpec = refHelper.getRefSpec(settings.ref, settings.commit); + yield git.fetch(refSpec, settings.fetchDepth); + } core.endGroup(); // Checkout info core.startGroup('Determining the checkout info'); @@ -7454,7 +7537,7 @@ const fs = __importStar(__webpack_require__(747)); const fsHelper = __importStar(__webpack_require__(618)); const io = __importStar(__webpack_require__(1)); const path = __importStar(__webpack_require__(622)); -function prepareExistingDirectory(git, repositoryPath, repositoryUrl, clean) { +function prepareExistingDirectory(git, repositoryPath, repositoryUrl, clean, ref) { return __awaiter(this, void 0, void 0, function* () { assert.ok(repositoryPath, 'Expected repositoryPath to be defined'); assert.ok(repositoryUrl, 'Expected repositoryUrl to be defined'); @@ -7494,10 +7577,24 @@ function prepareExistingDirectory(git, repositoryPath, repositoryUrl, clean) { for (const branch of branches) { yield git.branchDelete(false, branch); } - // Remove all refs/remotes/origin/* to avoid conflicts - branches = yield git.branchList(true); - for (const branch of branches) { - yield git.branchDelete(true, branch); + // Remove any conflicting refs/remotes/origin/* + // Example 1: Consider ref is refs/heads/foo and previously fetched refs/remotes/origin/foo/bar + // Example 2: Consider ref is refs/heads/foo/bar and previously fetched refs/remotes/origin/foo + if (ref) { + ref = ref.startsWith('refs/') ? ref : `refs/heads/${ref}`; + if (ref.startsWith('refs/heads/')) { + const upperName1 = ref.toUpperCase().substr('REFS/HEADS/'.length); + const upperName1Slash = `${upperName1}/`; + branches = yield git.branchList(true); + for (const branch of branches) { + const upperName2 = branch.substr('origin/'.length).toUpperCase(); + const upperName2Slash = `${upperName2}/`; + if (upperName1.startsWith(upperName2Slash) || + upperName2.startsWith(upperName1Slash)) { + yield git.branchDelete(true, branch); + } + } + } } core.endGroup(); // Clean |
