summaryrefslogtreecommitdiff
path: root/Git
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2011-12-12 21:12:51 -0400
committerGravatar Joey Hess <joey@kitenet.net>2011-12-12 21:12:51 -0400
commit31a0c07ee91af9e3bf434f416a4d711d841aa223 (patch)
treef45a90aea7a22aa564ef4af9232d81db77108e9b /Git
parent543d0d250104c1f5908e1b7b258d36d95488a029 (diff)
broke out Git/Branch.hs and reorganized
Diffstat (limited to 'Git')
-rw-r--r--Git/Branch.hs60
1 files changed, 60 insertions, 0 deletions
diff --git a/Git/Branch.hs b/Git/Branch.hs
new file mode 100644
index 000000000..e69e96f28
--- /dev/null
+++ b/Git/Branch.hs
@@ -0,0 +1,60 @@
+{- git branch stuff
+ -
+ - Copyright 2011 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Git.Branch where
+
+import qualified Data.ByteString.Lazy.Char8 as L
+
+import Common
+import Git
+
+{- Checks if the second branch has any commits not present on the first
+ - branch. -}
+changed :: Branch -> Branch -> Repo -> IO Bool
+changed origbranch newbranch repo
+ | origbranch == newbranch = return False
+ | otherwise = not . L.null <$> diffs
+ where
+ diffs = Git.pipeRead
+ [ Param "log"
+ , Param (show origbranch ++ ".." ++ show newbranch)
+ , Params "--oneline -n1"
+ ] repo
+
+{- Given a set of refs that are all known to have commits not
+ - on the branch, tries to update the branch by a fast-forward.
+ -
+ - In order for that to be possible, one of the refs must contain
+ - every commit present in all the other refs.
+ -}
+fastForward :: Branch -> [Ref] -> Repo -> IO Bool
+fastForward _ [] _ = return True
+fastForward branch (first:rest) repo = do
+ -- First, check that the branch does not contain any
+ -- new commits that are not in the first ref. If it does,
+ -- cannot fast-forward.
+ diverged <- changed first branch repo
+ if diverged
+ then no_ff
+ else maybe no_ff do_ff =<< findbest first rest
+ where
+ no_ff = return False
+ do_ff to = do
+ Git.run "update-ref"
+ [Param $ show branch, Param $ show to] repo
+ return True
+ findbest c [] = return $ Just c
+ findbest c (r:rs)
+ | c == r = findbest c rs
+ | otherwise = do
+ better <- changed c r repo
+ worse <- changed r c repo
+ case (better, worse) of
+ (True, True) -> return Nothing -- divergent fail
+ (True, False) -> findbest r rs -- better
+ (False, True) -> findbest c rs -- worse
+ (False, False) -> findbest c rs -- same