Skip to content

Commit 565989e

Browse files
committed
Re-add custom rule for GitClone and use git worktree to prepare source
This re-uses the git repository in the _cache/git/<user>/<repo> directory, but uses a temporary directory to get the worktree for a given rev to prepare the per-package directory in _cache/<package>.
1 parent 7c5b5eb commit 565989e

File tree

4 files changed

+70
-16
lines changed

4 files changed

+70
-16
lines changed

app/Foliage/CmdBuild.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import Distribution.Package
2323
import Distribution.Pretty (prettyShow)
2424
import Distribution.Version
2525
import Foliage.FetchURL (addFetchURLRule)
26+
import Foliage.GitClone (addGitCloneRule)
2627
import Foliage.HackageSecurity hiding (ToJSON, toJSON)
2728
import Foliage.Meta
2829
import Foliage.Meta.Aeson ()
@@ -42,6 +43,7 @@ cmdBuild buildOptions = do
4243
shake opts $
4344
do
4445
addFetchURLRule cacheDir
46+
addGitCloneRule cacheDir
4547
addPrepareSourceRule (buildOptsInputDir buildOptions) cacheDir
4648
addPrepareSdistRule outputDirRoot
4749
phony "buildAction" (buildAction buildOptions)

app/Foliage/GitClone.hs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{-# LANGUAGE DeriveAnyClass #-}
2+
{-# LANGUAGE DerivingVia #-}
3+
{-# LANGUAGE OverloadedStrings #-}
4+
{-# LANGUAGE TypeFamilies #-}
5+
6+
-- | Clone a github repository into a cache directory.
7+
module Foliage.GitClone (
8+
gitClone,
9+
addGitCloneRule,
10+
)
11+
where
12+
13+
import Development.Shake
14+
import Development.Shake.Classes
15+
import Development.Shake.FilePath
16+
import Development.Shake.Rule
17+
import Foliage.Meta (GitHubRepo)
18+
import GHC.Generics (Generic)
19+
20+
newtype GitClone = GitClone {repo :: GitHubRepo}
21+
deriving (Eq, Generic)
22+
deriving newtype (NFData)
23+
24+
instance Show GitClone where
25+
show GitClone{repo} = "gitClone " <> show repo
26+
27+
instance Hashable GitClone
28+
29+
instance Binary GitClone
30+
31+
type instance RuleResult GitClone = FilePath
32+
33+
-- | Clone given repo at given revision into the cache directory and return the working copy path.
34+
gitClone :: GitHubRepo -> Action FilePath
35+
gitClone repo = apply1 GitClone{repo}
36+
37+
-- | Set up the 'GitClone' rule with a cache directory.
38+
addGitCloneRule
39+
:: FilePath
40+
-- ^ Cache directory
41+
-> Rules ()
42+
addGitCloneRule cacheDir = addBuiltinRule noLint noIdentity run
43+
where
44+
run :: BuiltinRun GitClone FilePath
45+
run GitClone{repo} _old _mode = do
46+
let path = cacheDir </> "git" </> show repo
47+
48+
alreadyCloned <- doesDirectoryExist path
49+
if alreadyCloned
50+
then command_ [Cwd path] "git" ["fetch"]
51+
else do
52+
let url = "https://github.com/" <> show repo <> ".git"
53+
command_ [] "git" ["clone", "--recursive", url, path]
54+
55+
return $ RunResult{runChanged = ChangedRecomputeDiff, runStore = "", runValue = path}

app/Foliage/PrepareSource.hs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Distribution.Pretty (prettyShow)
1515
import Distribution.Types.PackageId
1616
import Distribution.Types.PackageName (unPackageName)
1717
import Foliage.FetchURL (fetchURL)
18+
import Foliage.GitClone (gitClone)
1819
import Foliage.Meta
1920
import Foliage.UpdateCabalFile (rewritePackageVersion)
2021
import GHC.Generics
@@ -69,9 +70,8 @@ addPrepareSourceRule inputDir cacheDir = addBuiltinRule noLint noIdentity run
6970
tarballPath <- fetchURL uri
7071
extractFromTarball tarballPath mSubdir srcDir
7172
GitHubSource repo rev mSubdir -> do
72-
workingCopy <- gitCheckout cacheDir repo rev
73-
let packageDir = maybe workingCopy (workingCopy </>) mSubdir
74-
copyDirectoryContents packageDir srcDir
73+
repoDir <- gitClone repo
74+
copyGitWorktree repoDir rev mSubdir srcDir
7575

7676
let patchesDir = inputDir </> unPackageName pkgName </> prettyShow pkgVersion </> "patches"
7777
hasPatches <- doesDirectoryExist patchesDir
@@ -119,20 +119,16 @@ addPrepareSourceRule inputDir cacheDir = addBuiltinRule noLint noIdentity run
119119

120120
copyDirectoryContents srcDir outDir
121121

122-
gitCheckout :: FilePath -> GitHubRepo -> GitHubRev -> Action FilePath
123-
gitCheckout cacheDir repo rev = do
124-
alreadyCloned <- doesDirectoryExist path
125-
if alreadyCloned
126-
then command_ [Cwd path] "git" ["fetch"]
127-
else command_ [] "git" ["clone", "--recursive", url, path]
128-
command_ [Cwd path] "git" ["checkout", show rev]
129-
command_ [Cwd path] "git" ["submodule", "update"]
130-
pure path
131-
where
132-
path = cacheDir </> "git" </> show repo
133-
134-
url = "https://github.com/" <> show repo <> ".git"
122+
-- | Copy package source from a git repository using 'git worktree'.
123+
copyGitWorktree :: FilePath -> GitHubRev -> Maybe FilePath -> FilePath -> Action ()
124+
copyGitWorktree repoDir rev mSubdir outDir = do
125+
withTempDir $ \tmpDir -> do
126+
command_ [Cwd repoDir] "git" ["worktree", "add", tmpDir, show rev]
127+
command_ [Cwd tmpDir] "git" ["submodule", "update", "--init"]
128+
let packageDir = maybe tmpDir (tmpDir </>) mSubdir
129+
copyDirectoryContents packageDir outDir
135130

131+
-- | Copy all contents from one directory to another.
136132
copyDirectoryContents :: FilePath -> FilePath -> Action ()
137133
copyDirectoryContents source destination =
138134
cmd_

foliage.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ executable foliage
2727
Foliage.CmdCreateKeys
2828
Foliage.CmdImportIndex
2929
Foliage.FetchURL
30+
Foliage.GitClone
3031
Foliage.HackageSecurity
3132
Foliage.Meta
3233
Foliage.Meta.Aeson

0 commit comments

Comments
 (0)