diff options
| author | eric sciple <ericsciple@users.noreply.github.com> | 2026-01-09 13:42:23 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-09 13:42:23 -0600 |
| commit | 5921bc8a76f21dbff8ef5088dc2dc3b479ab5309 (patch) | |
| tree | b4c76471127cb4a7e8d0205a8ed8b04f646baaa8 /src/ref-helper.ts | |
| parent | 72bc64336da5b556e438a70b19caa4f80eebee98 (diff) | |
Fix tag handling: preserve annotations and explicit fetch-tags (#2356)v6.0.2
This PR fixes several issues with tag handling in the checkout action:
1. fetch-tags: true now works (fixes #1471)
- Tags refspec is now included in getRefSpec() when fetchTags=true
- Previously tags were only fetched during a separate fetch that was
overwritten by the main fetch
2. Tag checkout preserves annotations (fixes #290)
- Tags are fetched via refspec (+refs/tags/*:refs/tags/*) instead of
--tags flag
- This fetches the actual tag objects, preserving annotations
3. Tag checkout with fetch-tags: true no longer fails (fixes #1467)
- When checking out a tag with fetchTags=true, only the wildcard
refspec is used (specific tag refspec is redundant)
Changes:
- src/ref-helper.ts: getRefSpec() now accepts fetchTags parameter and
prepends tags refspec when true
- src/git-command-manager.ts: fetch() simplified to always use --no-tags,
tags are fetched explicitly via refspec
- src/git-source-provider.ts: passes fetchTags to getRefSpec()
- Added E2E test for fetch-tags option
Related #1471, #1467, #290
Diffstat (limited to 'src/ref-helper.ts')
| -rw-r--r-- | src/ref-helper.ts | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/src/ref-helper.ts b/src/ref-helper.ts index 58f9290..5130f53 100644 --- a/src/ref-helper.ts +++ b/src/ref-helper.ts @@ -76,55 +76,75 @@ export function getRefSpecForAllHistory(ref: string, commit: string): string[] { return result } -export function getRefSpec(ref: string, commit: string): string[] { +export function getRefSpec( + ref: string, + commit: string, + fetchTags?: boolean +): string[] { if (!ref && !commit) { throw new Error('Args ref and commit cannot both be empty') } const upperRef = (ref || '').toUpperCase() + const result: string[] = [] + + // When fetchTags is true, always include the tags refspec + if (fetchTags) { + result.push(tagsRefSpec) + } // SHA if (commit) { // refs/heads if (upperRef.startsWith('REFS/HEADS/')) { const branch = ref.substring('refs/heads/'.length) - return [`+${commit}:refs/remotes/origin/${branch}`] + result.push(`+${commit}:refs/remotes/origin/${branch}`) } // refs/pull/ else if (upperRef.startsWith('REFS/PULL/')) { const branch = ref.substring('refs/pull/'.length) - return [`+${commit}:refs/remotes/pull/${branch}`] + result.push(`+${commit}:refs/remotes/pull/${branch}`) } // refs/tags/ else if (upperRef.startsWith('REFS/TAGS/')) { - return [`+${commit}:${ref}`] + if (!fetchTags) { + result.push(`+${ref}:${ref}`) + } } // Otherwise no destination ref else { - return [commit] + result.push(commit) } } // Unqualified ref, check for a matching branch or tag else if (!upperRef.startsWith('REFS/')) { - return [ - `+refs/heads/${ref}*:refs/remotes/origin/${ref}*`, - `+refs/tags/${ref}*:refs/tags/${ref}*` - ] + result.push(`+refs/heads/${ref}*:refs/remotes/origin/${ref}*`) + if (!fetchTags) { + result.push(`+refs/tags/${ref}*:refs/tags/${ref}*`) + } } // refs/heads/ else if (upperRef.startsWith('REFS/HEADS/')) { const branch = ref.substring('refs/heads/'.length) - return [`+${ref}:refs/remotes/origin/${branch}`] + result.push(`+${ref}:refs/remotes/origin/${branch}`) } // refs/pull/ else if (upperRef.startsWith('REFS/PULL/')) { const branch = ref.substring('refs/pull/'.length) - return [`+${ref}:refs/remotes/pull/${branch}`] + result.push(`+${ref}:refs/remotes/pull/${branch}`) } // refs/tags/ + else if (upperRef.startsWith('REFS/TAGS/')) { + if (!fetchTags) { + result.push(`+${ref}:${ref}`) + } + } + // Other refs else { - return [`+${ref}:${ref}`] + result.push(`+${ref}:${ref}`) } + + return result } /** @@ -170,8 +190,10 @@ export async function testRef( // refs/tags/ else if (upperRef.startsWith('REFS/TAGS/')) { const tagName = ref.substring('refs/tags/'.length) + // Use ^{commit} to dereference annotated tags to their underlying commit return ( - (await git.tagExists(tagName)) && commit === (await git.revParse(ref)) + (await git.tagExists(tagName)) && + commit === (await git.revParse(`${ref}^{commit}`)) ) } // Unexpected |
