Skip to content

Commit b6fb59a

Browse files
committed
Add a GitClone rule which fetches sources using git
Working copies are kept in the _cache/git/ directory.
1 parent c98bf02 commit b6fb59a

File tree

6 files changed

+86
-19
lines changed

6 files changed

+86
-19
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: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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 Control.Monad (unless)
14+
import Development.Shake
15+
import Development.Shake.Classes
16+
import Development.Shake.FilePath
17+
import Development.Shake.Rule
18+
import Foliage.Meta (GitHubRepo, GitHubRev)
19+
import GHC.Generics (Generic)
20+
21+
data GitClone = GitClone {repo :: GitHubRepo, rev :: GitHubRev}
22+
deriving (Eq, Generic, NFData)
23+
24+
instance Show GitClone where
25+
show GitClone{repo, rev} = "gitClone " <> show repo <> " " <> show rev
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 -> GitHubRev -> Action FilePath
35+
gitClone repo rev = apply1 GitClone{repo, rev}
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, rev} _old _mode = do
46+
let path = cacheDir </> "git" </> show repo
47+
48+
alreadyCloned <- doesDirectoryExist path
49+
unless alreadyCloned $ do
50+
let url = "https://github.com/" <> show repo <> ".git"
51+
command_ [] "git" ["clone", "--recursive", url, path]
52+
53+
command_ [Cwd path] "git" ["checkout", show rev]
54+
command_ [Cwd path] "git" ["submodule", "update"]
55+
56+
return $ RunResult{runChanged = ChangedRecomputeDiff, runStore = "", runValue = path}

app/Foliage/Meta.hs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,16 @@ import Toml (TomlCodec, (.=))
5151
import Toml qualified
5252

5353
newtype GitHubRepo = GitHubRepo {unGitHubRepo :: Text}
54-
deriving (Show, Eq, Binary, Hashable, NFData) via Text
54+
deriving (Eq, Binary, Hashable, NFData) via Text
55+
56+
instance Show GitHubRepo where
57+
show = T.unpack . unGitHubRepo
5558

5659
newtype GitHubRev = GitHubRev {unGitHubRev :: Text}
57-
deriving (Show, Eq, Binary, Hashable, NFData) via Text
60+
deriving (Eq, Binary, Hashable, NFData) via Text
61+
62+
instance Show GitHubRev where
63+
show = T.unpack . unGitHubRev
5864

5965
data PackageVersionSource
6066
= URISource

app/Foliage/PrepareSource.hs

Lines changed: 19 additions & 15 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 Foliage.Utils.GitHub (githubRepoTarballUrl)
@@ -70,8 +71,9 @@ addPrepareSourceRule inputDir cacheDir = addBuiltinRule noLint noIdentity run
7071
tarballPath <- fetchURL uri
7172
extractFromTarball tarballPath mSubdir srcDir
7273
GitHubSource repo rev mSubdir -> do
73-
tarballPath <- fetchURL (githubRepoTarballUrl repo rev)
74-
extractFromTarball tarballPath mSubdir srcDir
74+
workDir <- gitClone repo rev
75+
let packageDir = maybe workDir (workDir </>) mSubdir
76+
copyDirectoryContents packageDir srcDir
7577

7678
let patchesDir = inputDir </> unPackageName pkgName </> prettyShow pkgVersion </> "patches"
7779
hasPatches <- doesDirectoryExist patchesDir
@@ -117,16 +119,18 @@ addPrepareSourceRule inputDir cacheDir = addBuiltinRule noLint noIdentity run
117119
applyMSubdir = case mSubdir of Just s -> (</> s); _ -> id
118120
srcDir = applyMSubdir $ byPassSingleTopLevelDir tmpDir
119121

120-
cmd_
121-
[ "cp"
122-
, -- copy directories recursively
123-
"--recursive"
124-
, -- treat DEST as a normal file
125-
"--no-target-directory"
126-
, -- always follow symbolic links in SOURCE
127-
"--dereference"
128-
, -- SOURCE
129-
srcDir
130-
, -- DEST
131-
outDir
132-
]
122+
copyDirectoryContents srcDir outDir
123+
124+
copyDirectoryContents :: FilePath -> FilePath -> Action ()
125+
copyDirectoryContents source destination =
126+
cmd_
127+
[ "cp"
128+
, -- copy directories recursively
129+
"--recursive"
130+
, -- treat DEST as a normal file
131+
"--no-target-directory"
132+
, -- always follow symbolic links in SOURCE
133+
"--dereference"
134+
, source
135+
, destination
136+
]

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

tests/Tests.hs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ main = do
3838
, testCaseSteps "git submodules" $ \step ->
3939
inTemporaryDirectoryWithFixture "tests/fixtures/git-submodule" $ do
4040
step "Building repository"
41-
-- TODO: build fails because of cabal-install not finding the
42-
-- referenced files from the submodule
4341
callCommand "foliage build"
4442
, ---
4543
testCaseSteps "accepts --no-signatures" $ \step ->

0 commit comments

Comments
 (0)