Skip to content

Commit e6a20a3

Browse files
authored
Merge pull request #10590 from 9999years/vcs-submodules
VCS: Don't run submodule commands unless necessary
2 parents 8cc49d9 + 1e26d3e commit e6a20a3

File tree

4 files changed

+60
-25
lines changed
  • Cabal/src/Distribution/Simple/Program
  • cabal-install
    • src/Distribution/Client
    • tests/UnitTests/Distribution/Client
  • changelog.d

4 files changed

+60
-25
lines changed

Cabal/src/Distribution/Simple/Program/Run.hs

+2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ data ProgramInvocation = ProgramInvocation
6161
, progInvokeInputEncoding :: IOEncoding
6262
-- ^ TODO: remove this, make user decide when constructing 'progInvokeInput'.
6363
, progInvokeOutputEncoding :: IOEncoding
64+
, progInvokeWhen :: IO Bool
6465
}
6566

6667
data IOEncoding
@@ -82,6 +83,7 @@ emptyProgramInvocation =
8283
, progInvokeInput = Nothing
8384
, progInvokeInputEncoding = IOEncodingText
8485
, progInvokeOutputEncoding = IOEncodingText
86+
, progInvokeWhen = pure True
8587
}
8688

8789
simpleProgramInvocation

cabal-install/src/Distribution/Client/VCS.hs

+28-13
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ import qualified Data.List as List
9696
import qualified Data.Map as Map
9797
import System.Directory
9898
( doesDirectoryExist
99+
, doesFileExist
99100
, removeDirectoryRecursive
100101
, removePathForcibly
101102
)
@@ -468,11 +469,18 @@ vcsGit =
468469
[programInvocation prog cloneArgs]
469470
-- And if there's a tag, we have to do that in a second step:
470471
++ [git (resetArgs tag) | tag <- maybeToList (srpTag repo)]
471-
++ [ git (["submodule", "sync", "--recursive"] ++ verboseArg)
472-
, git (["submodule", "update", "--init", "--force", "--recursive"] ++ verboseArg)
472+
++ [ whenGitModulesExists $ git $ ["submodule", "sync", "--recursive"] ++ verboseArg
473+
, whenGitModulesExists $ git $ ["submodule", "update", "--init", "--force", "--recursive"] ++ verboseArg
473474
]
474475
where
475476
git args = (programInvocation prog args){progInvokeCwd = Just destdir}
477+
478+
gitModulesPath = destdir </> ".gitmodules"
479+
whenGitModulesExists invocation =
480+
invocation
481+
{ progInvokeWhen = doesFileExist gitModulesPath
482+
}
483+
476484
cloneArgs =
477485
["clone", srcuri, destdir]
478486
++ branchArgs
@@ -518,22 +526,25 @@ vcsGit =
518526
-- is needed because sometimes `git submodule sync` does not actually
519527
-- update the submodule source URL. Detailed description here:
520528
-- https://git.coop/-/snippets/85
521-
git localDir $ ["submodule", "deinit", "--force", "--all"] ++ verboseArg
522-
let gitModulesDir = localDir </> ".git" </> "modules"
523-
gitModulesExists <- doesDirectoryExist gitModulesDir
524-
when gitModulesExists $
529+
let dotGitModulesPath = localDir </> ".git" </> "modules"
530+
gitModulesPath = localDir </> ".gitmodules"
531+
532+
-- Remove any `.git/modules` if they exist.
533+
dotGitModulesExists <- doesDirectoryExist dotGitModulesPath
534+
when dotGitModulesExists $ do
535+
git localDir $ ["submodule", "deinit", "--force", "--all"] ++ verboseArg
525536
if buildOS == Windows
526537
then do
527538
-- Windows can't delete some git files #10182
528539
void $
529540
Process.createProcess_ "attrib" $
530541
Process.shell $
531-
"attrib -s -h -r " <> gitModulesDir <> "\\*.* /s /d"
542+
"attrib -s -h -r " <> dotGitModulesPath <> "\\*.* /s /d"
532543

533544
catch
534-
(removePathForcibly gitModulesDir)
535-
(\e -> if isPermissionError e then removePathForcibly gitModulesDir else throw e)
536-
else removeDirectoryRecursive gitModulesDir
545+
(removePathForcibly dotGitModulesPath)
546+
(\e -> if isPermissionError e then removePathForcibly dotGitModulesPath else throw e)
547+
else removeDirectoryRecursive dotGitModulesPath
537548

538549
-- If we want a particular branch or tag, fetch it.
539550
ref <- case srpBranch `mplus` srpTag of
@@ -581,9 +592,13 @@ vcsGit =
581592
, "--"
582593
]
583594

584-
git localDir $ ["submodule", "sync", "--recursive"] ++ verboseArg
585-
git localDir $ ["submodule", "update", "--force", "--init", "--recursive"] ++ verboseArg
586-
git localDir $ ["submodule", "foreach", "--recursive"] ++ verboseArg ++ ["git clean -ffxdq"]
595+
-- We need to check if `.gitmodules` exists _after_ the `git reset` call.
596+
gitModulesExists <- doesFileExist gitModulesPath
597+
when gitModulesExists $ do
598+
git localDir $ ["submodule", "sync", "--recursive"] ++ verboseArg
599+
git localDir $ ["submodule", "update", "--force", "--init", "--recursive"] ++ verboseArg
600+
git localDir $ ["submodule", "foreach", "--recursive"] ++ verboseArg ++ ["git clean -ffxdq"]
601+
587602
git localDir $ ["clean", "-ffxdq"]
588603
where
589604
git :: FilePath -> [String] -> IO ()

cabal-install/tests/UnitTests/Distribution/Client/VCS.hs

+16-12
Original file line numberDiff line numberDiff line change
@@ -923,10 +923,7 @@ vcsTestDriverGit
923923
, mkVcsTmpDir = tmpDir
924924
}
925925
, vcsAddSubmodule = \_ source dest -> do
926-
destExists <-
927-
(||)
928-
<$> doesFileExist (repoRoot </> dest)
929-
<*> doesDirectoryExist (repoRoot </> dest)
926+
destExists <- doesPathExist $ repoRoot </> dest
930927
when destExists $ gitQuiet ["rm", "--force", dest]
931928
-- If there is an old submodule git dir with the same name, remove it.
932929
-- It most likely has a different URL and `git submodule add` will fai.
@@ -995,16 +992,23 @@ vcsTestDriverGit
995992
verboseArg = ["--quiet" | verbosity < Verbosity.normal]
996993

997994
submoduleGitDir path = repoRoot </> ".git" </> "modules" </> path
995+
996+
dotGitModulesPath = repoRoot </> ".git" </> "modules"
997+
gitModulesPath = repoRoot </> ".gitmodules"
998+
998999
deinitAndRemoveCachedSubmodules = do
999-
gitQuiet ["submodule", "deinit", "--force", "--all"]
1000-
let gitModulesDir = repoRoot </> ".git" </> "modules"
1001-
gitModulesExists <- doesDirectoryExist gitModulesDir
1002-
when gitModulesExists $ removeDirectoryRecursive gitModulesDir
1000+
dotGitModulesExists <- doesDirectoryExist dotGitModulesPath
1001+
when dotGitModulesExists $ do
1002+
git $ ["submodule", "deinit", "--force", "--all"] ++ verboseArg
1003+
removeDirectoryRecursive dotGitModulesPath
1004+
10031005
updateSubmodulesAndCleanup = do
1004-
gitQuiet ["submodule", "sync", "--recursive"]
1005-
gitQuiet ["submodule", "update", "--init", "--recursive", "--force"]
1006-
-- Note: We need to manually add `verboseArg` here so that the embedded `git clean` command includes it as well.
1007-
gitQuiet $ ["submodule", "foreach", "--recursive", "git clean -ffxdq"] ++ verboseArg
1006+
gitModulesExists <- doesFileExist gitModulesPath
1007+
when gitModulesExists $ do
1008+
gitQuiet ["submodule", "sync", "--recursive"]
1009+
gitQuiet ["submodule", "update", "--init", "--recursive", "--force"]
1010+
-- Note: We need to manually add `verboseArg` here so that the embedded `git clean` command includes it as well.
1011+
gitQuiet $ ["submodule", "foreach", "--recursive", "git clean -ffxdq"] ++ verboseArg
10081012
gitQuiet ["clean", "-ffxdq"]
10091013

10101014
type MTimeChange = Int

changelog.d/pr-10590

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
synopsis: "Don't run submodule commands unless necessary"
3+
packages: [cabal-install]
4+
prs: 10590
5+
---
6+
7+
When `cabal` clones a Git repo for a `source-repository-package` listed in a
8+
`cabal.project`, it will run various commands to check out the correct
9+
revision, initialize submodules if they're present, and so on.
10+
11+
Now, `cabal` will avoid running `git submodule` commands unless the cloned
12+
repository contains a `.gitmodules` file. This will declutter `cabal`'s debug
13+
output by running fewer commands.
14+

0 commit comments

Comments
 (0)