Skip to content

Commit 79649a5

Browse files
authored
Merge pull request #6684 from phadej/issue-6610
6610 Add pijul to known repository type
2 parents 4d1dcd2 + e7e60f1 commit 79649a5

File tree

5 files changed

+227
-21
lines changed

5 files changed

+227
-21
lines changed

Cabal/Distribution/PackageDescription/Check.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,6 +1922,7 @@ repoTypeDirname Mercurial = [".hg"]
19221922
repoTypeDirname GnuArch = [".arch-params"]
19231923
repoTypeDirname Bazaar = [".bzr"]
19241924
repoTypeDirname Monotone = ["_MTN"]
1925+
repoTypeDirname Pijul = [".pijul"]
19251926

19261927
-- ------------------------------------------------------------
19271928
-- * Checks involving files in the package

Cabal/Distribution/Types/SourceRepo.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ instance NFData RepoKind where rnf = genericRnf
126126
-- obtain and track the repo depend on the repo type.
127127
--
128128
data KnownRepoType = Darcs | Git | SVN | CVS
129-
| Mercurial | GnuArch | Bazaar | Monotone
129+
| Mercurial | GnuArch | Bazaar | Monotone | Pijul
130130
deriving (Eq, Generic, Ord, Read, Show, Typeable, Data, Enum, Bounded)
131131

132132
instance Binary KnownRepoType

Cabal/tests/UnitTests/Distribution/Utils/Structured.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ tests = testGroup "Distribution.Utils.Structured"
2323
, testCase "SPDX.License" $ structureHash (Proxy :: Proxy License) @?= Fingerprint 0xd3d4a09f517f9f75 0xbc3d16370d5a853a
2424
-- The difference is in encoding of newtypes
2525
#if MIN_VERSION_base(4,7,0)
26-
, testCase "LocalBuildInfo" $ structureHash (Proxy :: Proxy LocalBuildInfo) @?= Fingerprint 0xe426ef7c5c6e25e8 0x79b156f0f3c58f79
26+
, testCase "LocalBuildInfo" $ structureHash (Proxy :: Proxy LocalBuildInfo) @?= Fingerprint 0x27de6f0a3d133e71 0x81c8d35b9e4b8bf0
2727
#endif
2828
]

cabal-install/Distribution/Client/VCS.hs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ module Distribution.Client.VCS (
2828
vcsGit,
2929
vcsHg,
3030
vcsSvn,
31+
vcsPijul,
3132
) where
3233

3334
import Prelude ()
@@ -498,3 +499,147 @@ svnProgram = (simpleProgram "svn") {
498499
_ -> ""
499500
}
500501

502+
503+
-- | VCS driver for Pijul.
504+
-- Documentation for Pijul can be found at <https://pijul.org/manual/introduction.html>
505+
--
506+
-- 2020-04-09 Oleg:
507+
--
508+
-- As far as I understand pijul, there are branches and "tags" in pijul,
509+
-- but there aren't a "commit hash" identifying an arbitrary state.
510+
--
511+
-- One can create `a pijul tag`, which will make a patch hash,
512+
-- which depends on everything currently in the repository.
513+
-- I guess if you try to apply that patch, you'll be forced to apply
514+
-- all the dependencies too. In other words, there are no named tags.
515+
--
516+
-- It's not clear to me whether there is an option to
517+
-- "apply this patch *and* all of its dependencies".
518+
-- And relatedly, whether how to make sure that there are no other
519+
-- patches applied.
520+
--
521+
-- With branches it's easier, as you can `pull` and `checkout` them,
522+
-- and they seem to be similar enough. Yet, pijul documentations says
523+
--
524+
-- > Note that the purpose of branches in Pijul is quite different from Git,
525+
-- since Git's "feature branches" can usually be implemented by just
526+
-- patches.
527+
--
528+
-- I guess it means that indeed instead of creating a branch and making PR
529+
-- in "GitHub" workflow, you'd just create a patch and offer it.
530+
-- You can do that with `git` too. Push (a branch with) commit to remote
531+
-- and ask other to cherry-pick that commit. Yet, in git identity of commit
532+
-- changes when it applied to other trees, where patches in pijul have
533+
-- will continue to have the same hash.
534+
--
535+
-- Unfortunately pijul doesn't talk about conflict resolution.
536+
-- It seems that you get something like:
537+
--
538+
-- % pijul status
539+
-- On branch merge
540+
--
541+
-- Unresolved conflicts:
542+
-- (fix conflicts and record the resolution with "pijul record ...")
543+
--
544+
-- foo
545+
--
546+
-- % cat foo
547+
-- first line
548+
-- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
549+
-- branch BBB
550+
-- ================================
551+
-- branch AAA
552+
-- <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
553+
-- last line
554+
--
555+
-- And then the `pijul dependencies` would draw you a graph like
556+
--
557+
--
558+
-- -----> foo on branch B ----->
559+
-- resolve confict Initial patch
560+
-- -----> foo on branch A ----->
561+
--
562+
-- Which is seems reasonable.
563+
--
564+
-- So currently, pijul support is very experimental, and most likely
565+
-- won't work, even the basics are in place. Tests are also written
566+
-- but disabled, as the branching model differs from `git` one,
567+
-- for which tests are written.
568+
--
569+
vcsPijul :: VCS Program
570+
vcsPijul =
571+
VCS {
572+
vcsRepoType = KnownRepoType Pijul,
573+
vcsProgram = pijulProgram,
574+
vcsCloneRepo,
575+
vcsSyncRepos
576+
}
577+
where
578+
vcsCloneRepo :: Verbosity -- ^ it seems that pijul does not have verbose flag
579+
-> ConfiguredProgram
580+
-> SourceRepositoryPackage f
581+
-> FilePath
582+
-> FilePath
583+
-> [ProgramInvocation]
584+
vcsCloneRepo _verbosity prog repo srcuri destdir =
585+
[ programInvocation prog cloneArgs ]
586+
-- And if there's a tag, we have to do that in a second step:
587+
++ [ (programInvocation prog (checkoutArgs tag)) {
588+
progInvokeCwd = Just destdir
589+
}
590+
| tag <- maybeToList (srpTag repo) ]
591+
where
592+
cloneArgs = ["clone", srcuri, destdir]
593+
++ branchArgs
594+
branchArgs = case srpBranch repo of
595+
Just b -> ["--from-branch", b]
596+
Nothing -> []
597+
checkoutArgs tag = "checkout" : [tag] -- TODO: this probably doesn't work either
598+
599+
vcsSyncRepos :: Verbosity
600+
-> ConfiguredProgram
601+
-> [(SourceRepositoryPackage f, FilePath)]
602+
-> IO [MonitorFilePath]
603+
vcsSyncRepos _ _ [] = return []
604+
vcsSyncRepos verbosity pijulProg
605+
((primaryRepo, primaryLocalDir) : secondaryRepos) = do
606+
607+
vcsSyncRepo verbosity pijulProg primaryRepo primaryLocalDir Nothing
608+
sequence_
609+
[ vcsSyncRepo verbosity pijulProg repo localDir (Just primaryLocalDir)
610+
| (repo, localDir) <- secondaryRepos ]
611+
return [ monitorDirectoryExistence dir
612+
| dir <- (primaryLocalDir : map snd secondaryRepos) ]
613+
614+
vcsSyncRepo verbosity pijulProg SourceRepositoryPackage{..} localDir peer = do
615+
exists <- doesDirectoryExist localDir
616+
if exists
617+
then pijul localDir ["pull"] -- TODO: this probably doesn't work.
618+
else pijul (takeDirectory localDir) cloneArgs
619+
pijul localDir checkoutArgs
620+
where
621+
pijul :: FilePath -> [String] -> IO ()
622+
pijul cwd args = runProgramInvocation verbosity $
623+
(programInvocation pijulProg args) {
624+
progInvokeCwd = Just cwd
625+
}
626+
627+
cloneArgs = ["clone", loc, localDir]
628+
++ case peer of
629+
Nothing -> []
630+
Just peerLocalDir -> [peerLocalDir]
631+
where loc = srpLocation
632+
checkoutArgs = "checkout" : ["--force", checkoutTarget, "--" ]
633+
checkoutTarget = fromMaybe "HEAD" (srpBranch `mplus` srpTag) -- TODO: this is definitely wrong.
634+
635+
pijulProgram :: Program
636+
pijulProgram = (simpleProgram "pijul") {
637+
programFindVersion = findProgramVersion "--version" $ \str ->
638+
case words str of
639+
-- "pijul 0.12.2
640+
(_:ver:_) | all isTypical ver -> ver
641+
_ -> ""
642+
}
643+
where
644+
isNum c = c >= '0' && c <= '9'
645+
isTypical c = isNum c || c == '.'

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

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,26 @@ import UnitTests.TempTestDir (withTestDir, removeDirectoryRecursiveHack)
4747
--
4848
tests :: MTimeChange -> [TestTree]
4949
tests mtimeChange =
50-
[ testGroup "check VCS test framework" $
51-
[ testProperty "git" prop_framework_git
52-
] ++
53-
[ testProperty "darcs" (prop_framework_darcs mtimeChange)
54-
| enableDarcsTests
50+
[ testGroup "git"
51+
[ testProperty "check VCS test framework" prop_framework_git
52+
, testProperty "cloneSourceRepo" prop_cloneRepo_git
53+
, testProperty "syncSourceRepos" prop_syncRepos_git
5554
]
56-
, testGroup "cloneSourceRepo" $
57-
[ testProperty "git" prop_cloneRepo_git
58-
] ++
59-
[ testProperty "darcs" (prop_cloneRepo_darcs mtimeChange)
60-
| enableDarcsTests
55+
56+
-- for the moment they're not yet working
57+
, testGroup "darcs" $ const []
58+
[ testProperty "check VCS test framework" $ prop_framework_darcs mtimeChange
59+
, testProperty "cloneSourceRepo" $ prop_cloneRepo_darcs mtimeChange
60+
, testProperty "syncSourceRepos" $ prop_syncRepos_darcs mtimeChange
6161
]
62-
, testGroup "syncSourceRepos" $
63-
[ testProperty "git" prop_syncRepos_git
64-
] ++
65-
[ testProperty "darcs" (prop_syncRepos_darcs mtimeChange)
66-
| enableDarcsTests
62+
63+
, testGroup "pijul" $ const []
64+
[ testProperty "check VCS test framework" prop_framework_pijul
65+
, testProperty "cloneSourceRepo" prop_cloneRepo_pijul
66+
, testProperty "syncSourceRepos" prop_syncRepos_pijul
6767
]
68-
]
69-
where
70-
-- for the moment they're not yet working
71-
enableDarcsTests = False
7268

69+
]
7370

7471
prop_framework_git :: BranchingRepoRecipe -> Property
7572
prop_framework_git =
@@ -83,6 +80,12 @@ prop_framework_darcs mtimeChange =
8380
. prop_framework vcsDarcs (vcsTestDriverDarcs mtimeChange)
8481
. WithoutBranchingSupport
8582

83+
prop_framework_pijul :: BranchingRepoRecipe -> Property
84+
prop_framework_pijul =
85+
ioProperty
86+
. prop_framework vcsPijul vcsTestDriverPijul
87+
. WithBranchingSupport
88+
8689
prop_cloneRepo_git :: BranchingRepoRecipe -> Property
8790
prop_cloneRepo_git =
8891
ioProperty
@@ -96,6 +99,12 @@ prop_cloneRepo_darcs mtimeChange =
9699
. prop_cloneRepo vcsDarcs (vcsTestDriverDarcs mtimeChange)
97100
. WithoutBranchingSupport
98101

102+
prop_cloneRepo_pijul :: BranchingRepoRecipe -> Property
103+
prop_cloneRepo_pijul =
104+
ioProperty
105+
. prop_cloneRepo vcsPijul vcsTestDriverPijul
106+
. WithBranchingSupport
107+
99108
prop_syncRepos_git :: RepoDirSet -> SyncTargetIterations -> PrngSeed
100109
-> BranchingRepoRecipe -> Property
101110
prop_syncRepos_git destRepoDirs syncTargetSetIterations seed =
@@ -113,6 +122,13 @@ prop_syncRepos_darcs mtimeChange destRepoDirs syncTargetSetIterations seed =
113122
destRepoDirs syncTargetSetIterations seed
114123
. WithoutBranchingSupport
115124

125+
prop_syncRepos_pijul :: RepoDirSet -> SyncTargetIterations -> PrngSeed
126+
-> BranchingRepoRecipe -> Property
127+
prop_syncRepos_pijul destRepoDirs syncTargetSetIterations seed =
128+
ioProperty
129+
. prop_syncRepos vcsPijul vcsTestDriverPijul
130+
destRepoDirs syncTargetSetIterations seed
131+
. WithBranchingSupport
116132

117133
-- ------------------------------------------------------------
118134
-- * General test setup
@@ -693,3 +709,47 @@ vcsTestDriverDarcs mtimeChange verbosity vcs repoRoot =
693709
}
694710
darcs = runProgramInvocation verbosity . darcsInvocation
695711

712+
713+
vcsTestDriverPijul :: Verbosity -> VCS ConfiguredProgram
714+
-> FilePath -> VCSTestDriver
715+
vcsTestDriverPijul verbosity vcs repoRoot =
716+
VCSTestDriver {
717+
vcsVCS = vcs
718+
719+
, vcsRepoRoot = repoRoot
720+
721+
, vcsIgnoreFiles = Set.empty
722+
723+
, vcsInit =
724+
pijul $ ["init"]
725+
726+
, vcsAddFile = \_ filename ->
727+
pijul ["add", filename]
728+
729+
, vcsCommitChanges = \_state -> do
730+
pijul $ ["record", "-a", "-m 'a patch'"
731+
, "-A 'A <[email protected]>'"
732+
]
733+
commit <- pijul' ["log"]
734+
let commit' = takeWhile (not . isSpace) commit
735+
return (Just commit')
736+
737+
-- tags work differently in pijul...
738+
-- so this is wrong
739+
, vcsTagState = \_ tagname ->
740+
pijul ["tag", tagname]
741+
742+
, vcsSwitchBranch = \_ branchname -> do
743+
-- unless (branchname `Map.member` allBranches) $
744+
-- pijul ["from-branch", branchname]
745+
pijul $ ["checkout", branchname]
746+
747+
, vcsCheckoutTag = Left $ \tagname ->
748+
pijul $ ["checkout", tagname]
749+
}
750+
where
751+
gitInvocation args = (programInvocation (vcsProgram vcs) args) {
752+
progInvokeCwd = Just repoRoot
753+
}
754+
pijul = runProgramInvocation verbosity . gitInvocation
755+
pijul' = getProgramInvocationOutput verbosity . gitInvocation

0 commit comments

Comments
 (0)