From 31a38f8468b1842d204af663e6dff03bbd436eff Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 20 Nov 2024 15:00:17 -0400 Subject: [PATCH] git-remote-annex: Require git version 2.31 or newer Since old ones had a buggy git bundle command. In particular, git 2.30.2 has a git bundle that supports --stdin, but does not read from it, and so fails to create a bundle. While not using --stdin would perhaps work, it limits the number of revs that get included in the bundle to the command line length limit. But the real kicker is that at the same time --stdin got fixed, a bug also got fixed that made git bundle skip including refs when they had the same sha as other refs it included. Which would lead to data loss. So best to avoid that buggy thing. --- CHANGELOG | 2 ++ CmdLine/GitRemoteAnnex.hs | 2 ++ Git/Bundle.hs | 6 ++++++ Test.hs | 32 +++++++++++++++++--------------- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 249ed77549..a4a43e6fd6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -21,6 +21,8 @@ git-annex (10.20241032) UNRELEASED; urgency=medium uses the same hostname as remote.name.url, which is itself a http(s) url, they are assumed to share a username and password. This avoids unnecessary duplicate password prompts. + * git-remote-annex: Require git version 2.31 or newer, since old + ones had a buggy git bundle command. -- Joey Hess Mon, 11 Nov 2024 12:26:00 -0400 diff --git a/CmdLine/GitRemoteAnnex.hs b/CmdLine/GitRemoteAnnex.hs index 89ded7191c..0b5505c52c 100644 --- a/CmdLine/GitRemoteAnnex.hs +++ b/CmdLine/GitRemoteAnnex.hs @@ -70,6 +70,8 @@ import qualified Data.Set as S run :: [String] -> IO () run (remotename:url:[]) = do + unlessM Git.Bundle.versionSupported $ + giveup "git-remote-annex needs a newer version of git" repo <- getRepo state <- Annex.new repo Annex.eval state $ diff --git a/Git/Bundle.hs b/Git/Bundle.hs index caa4d12ec9..651484d3f5 100644 --- a/Git/Bundle.hs +++ b/Git/Bundle.hs @@ -12,10 +12,16 @@ module Git.Bundle where import Common import Git import Git.Command +import qualified Git.Version import Data.Char (ord) import qualified Data.ByteString.Char8 as S8 +-- Older versions of git had a git bundle command that sometimes omitted +-- refs, and that did not properly support --stdin. +versionSupported :: IO Bool +versionSupported = not <$> Git.Version.older "2.31" + listHeads :: FilePath -> Repo -> IO [(Sha, Ref)] listHeads bundle repo = map gen . S8.lines <$> pipeReadStrict [Param "bundle", Param "list-heads", File bundle] repo diff --git a/Test.hs b/Test.hs index 722558b70f..9796608365 100644 --- a/Test.hs +++ b/Test.hs @@ -37,6 +37,7 @@ import qualified Git.Types import qualified Git.Ref import qualified Git.LsTree import qualified Git.FilePath +import qualified Git.Bundle import qualified Annex.Locations #ifndef mingw32_HOST_OS import qualified Types.GitConfig @@ -427,29 +428,30 @@ test_git_remote_annex :: Bool -> Assertion test_git_remote_annex exporttree #ifndef mingw32_HOST_OS | exporttree = - testspecialremote ["importtree=yes", "exporttree=yes"] $ + runtest ["importtree=yes", "exporttree=yes"] $ git_annex "export" ["master", "--to=foo"] "export" | otherwise = - testspecialremote [] $ + runtest [] $ git_annex "copy" ["--to=foo"] "copy" #else -- git-remote-annex is not currently installed on Windows return () #endif where - testspecialremote cfg populate = intmpclonerepo $ do - let cfg' = ["type=directory", "encryption=none", "directory=dir"] ++ cfg - createDirectory "dir" - git_annex "initremote" ("foo":("uuid=" ++ diruuid):cfg') "initremote" - git_annex "get" [] "get failed" - () <- populate - git "config" ["remote.foo.url", "annex::"] "git config" - git "push" ["foo", "master"] "git push" - git "push" ["foo", "git-annex"] "git push" - git "clone" ["annex::"++diruuid++"?"++intercalate "&" cfg', "clonedir"] - "git clone from special remote" - inpath "clonedir" $ - git_annex "get" [annexedfile] "get from origin special remote" + runtest cfg populate = whenM Git.Bundle.versionSupported $ + intmpclonerepo $ do + let cfg' = ["type=directory", "encryption=none", "directory=dir"] ++ cfg + createDirectory "dir" + git_annex "initremote" ("foo":("uuid=" ++ diruuid):cfg') "initremote" + git_annex "get" [] "get failed" + () <- populate + git "config" ["remote.foo.url", "annex::"] "git config" + git "push" ["foo", "master"] "git push" + git "push" ["foo", "git-annex"] "git push" + git "clone" ["annex::"++diruuid++"?"++intercalate "&" cfg', "clonedir"] + "git clone from special remote" + inpath "clonedir" $ + git_annex "get" [annexedfile] "get from origin special remote" diruuid="89ddefa4-a04c-11ef-87b5-e880882a4f98" test_add_moved :: Assertion