Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VCS: Fix weird tag creation #10586

Merged
merged 3 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 50 additions & 13 deletions cabal-install/src/Distribution/Client/VCS.hs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,8 @@ vcsGit =
| dir <- (primaryLocalDir : map snd secondaryRepos)
]

-- NOTE: Repositories are cloned once, but can be synchronized multiple times.
-- Therefore, this code has to work with both `git clone` and `git fetch`.
vcsSyncRepo verbosity gitProg SourceRepositoryPackage{..} localDir peer = do
exists <- doesDirectoryExist localDir
if exists
Expand All @@ -532,10 +534,53 @@ vcsGit =
(removePathForcibly gitModulesDir)
(\e -> if isPermissionError e then removePathForcibly gitModulesDir else throw e)
else removeDirectoryRecursive gitModulesDir
when (resetTarget /= "HEAD") $ do
git localDir fetchArgs -- first fetch the tag if needed
git localDir setTagArgs
git localDir resetArgs -- only then reset to the commit

-- If we want a particular branch or tag, fetch it.
ref <- case srpBranch `mplus` srpTag of
Nothing -> pure "HEAD"
Just ref -> do
-- /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\
-- /!\ MULTIPLE HOURS HAVE BEEN LOST HERE!! /!\
-- /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\
--
-- If you run `git fetch origin MY_TAG`, then the tag _will_ be
-- fetched, but no local ref (e.g. `refs/tags/MY_TAG`) will be
-- created.
--
-- This means that doing `git fetch origin MY_TAG && git reset --hard
-- MY_TAG` will fail with a message like `unknown revision MY_TAG`.
--
-- There are two ways around this:
--
-- 1. Provide a refmap explicitly:
--
-- git fetch --refmap="+refs/tags/*:refs/tags/*" origin MYTAG
--
-- This tells Git to create local tags matching remote tags. It's
-- not in the default refmap so you need to set it explicitly.
-- (You can also set it with `git config set --local
-- remote.origin.fetch ...`.)
--
-- 2. Use `FETCH_HEAD` directly: Git writes a `FETCH_HEAD` ref
-- containing the commit that was just fetched. This feels a bit
-- nasty but seems to work reliably, even if nothing was fetched.
-- (That is, deleting `FETCH_HEAD` and re-running a `git fetch`
-- command will succesfully recreate the `FETCH_HEAD` ref.)
--
-- Option 2 is what Cabal has done historically, and we're keeping it
-- for now. Option 1 is possible but seems to have little benefit.
git localDir ("fetch" : verboseArg ++ ["origin", ref])
pure "FETCH_HEAD"

-- Then, reset to the appropriate ref.
git localDir $
"reset"
: verboseArg
++ [ "--hard"
, ref
, "--"
]

git localDir $ ["submodule", "sync", "--recursive"] ++ verboseArg
git localDir $ ["submodule", "update", "--force", "--init", "--recursive"] ++ verboseArg
git localDir $ ["submodule", "foreach", "--recursive"] ++ verboseArg ++ ["git clean -ffxdq"]
Expand All @@ -556,15 +601,7 @@ vcsGit =
++ verboseArg
where
loc = srpLocation
-- To checkout/reset to a particular commit, we must first fetch it
-- (since the base clone is shallow).
fetchArgs = "fetch" : verboseArg ++ ["origin", resetTarget]
-- And then create the Tag from the FETCH_HEAD (which we should have just fetched)
9999years marked this conversation as resolved.
Show resolved Hide resolved
setTagArgs = ["tag", "-f", resetTarget, "FETCH_HEAD"]
-- Then resetting to that tag will work (if we don't create the tag
-- locally from FETCH_HEAD, it won't exist).
resetArgs = "reset" : verboseArg ++ ["--hard", resetTarget, "--"]
resetTarget = fromMaybe "HEAD" (srpBranch `mplus` srpTag)

verboseArg = ["--quiet" | verbosity < Verbosity.normal]

gitProgram :: Program
Expand Down
9 changes: 9 additions & 0 deletions cabal-testsuite/PackageTests/postCheckoutCommand/cabal.out
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
# cabal v2-build
Configuration is affected by the following files:
- cabal.positive.project
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
- example-1.0 (lib) (first run)
Configuring library for example-1.0...
Preprocessing library for example-1.0...
Building library for example-1.0...
# cabal v2-build
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ import Test.Cabal.Prelude

main = cabalTest $ do
withProjectFile "cabal.positive.project" $ do
cabal "v2-build" ["-v0"]
cabal "v2-build" []
withProjectFile "cabal.negative.project" $ do
fails $ cabal "v2-build" ["-v0"]
fails $ cabal "v2-build" []
Loading