working toward adjusted commit propigation
This commit is contained in:
		
					parent
					
						
							
								7811556a5b
							
						
					
				
			
			
				commit
				
					
						cf24e9b892
					
				
			
		
					 4 changed files with 112 additions and 32 deletions
				
			
		| 
						 | 
					@ -9,6 +9,7 @@ module Annex.AdjustedBranch (
 | 
				
			||||||
	Adjustment(..),
 | 
						Adjustment(..),
 | 
				
			||||||
	OrigBranch,
 | 
						OrigBranch,
 | 
				
			||||||
	AdjBranch,
 | 
						AdjBranch,
 | 
				
			||||||
 | 
						originalToAdjusted,
 | 
				
			||||||
	adjustedToOriginal,
 | 
						adjustedToOriginal,
 | 
				
			||||||
	fromAdjustedBranch,
 | 
						fromAdjustedBranch,
 | 
				
			||||||
	enterAdjustedBranch,
 | 
						enterAdjustedBranch,
 | 
				
			||||||
| 
						 | 
					@ -18,13 +19,16 @@ module Annex.AdjustedBranch (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Annex.Common
 | 
					import Annex.Common
 | 
				
			||||||
import qualified Annex
 | 
					import qualified Annex
 | 
				
			||||||
 | 
					import Git
 | 
				
			||||||
import Git.Types
 | 
					import Git.Types
 | 
				
			||||||
import qualified Git.Branch
 | 
					import qualified Git.Branch
 | 
				
			||||||
import qualified Git.Ref
 | 
					import qualified Git.Ref
 | 
				
			||||||
import qualified Git.Command
 | 
					import qualified Git.Command
 | 
				
			||||||
import Git.Tree
 | 
					import qualified Git.Tree
 | 
				
			||||||
 | 
					import Git.Tree (TreeItem(..))
 | 
				
			||||||
import Git.Env
 | 
					import Git.Env
 | 
				
			||||||
import Git.Index
 | 
					import Git.Index
 | 
				
			||||||
 | 
					import Git.FilePath
 | 
				
			||||||
import qualified Git.LockFile
 | 
					import qualified Git.LockFile
 | 
				
			||||||
import Annex.CatFile
 | 
					import Annex.CatFile
 | 
				
			||||||
import Annex.Link
 | 
					import Annex.Link
 | 
				
			||||||
| 
						 | 
					@ -35,8 +39,10 @@ import qualified Database.Keys
 | 
				
			||||||
data Adjustment = UnlockAdjustment
 | 
					data Adjustment = UnlockAdjustment
 | 
				
			||||||
	deriving (Show)
 | 
						deriving (Show)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
adjustTreeItem :: Adjustment -> HashObjectHandle -> TreeItem -> Annex (Maybe TreeItem)
 | 
					data Direction = Forward | Reverse
 | 
				
			||||||
adjustTreeItem UnlockAdjustment h ti@(TreeItem f m s)
 | 
					
 | 
				
			||||||
 | 
					adjustTreeItem :: Adjustment -> Direction -> HashObjectHandle -> TreeItem -> Annex (Maybe TreeItem)
 | 
				
			||||||
 | 
					adjustTreeItem UnlockAdjustment Forward h ti@(TreeItem f m s)
 | 
				
			||||||
	| toBlobType m == Just SymlinkBlob = do
 | 
						| toBlobType m == Just SymlinkBlob = do
 | 
				
			||||||
		mk <- catKey s
 | 
							mk <- catKey s
 | 
				
			||||||
		case mk of
 | 
							case mk of
 | 
				
			||||||
| 
						 | 
					@ -46,6 +52,20 @@ adjustTreeItem UnlockAdjustment h ti@(TreeItem f m s)
 | 
				
			||||||
					<$> hashPointerFile' h k
 | 
										<$> hashPointerFile' h k
 | 
				
			||||||
			Nothing -> return (Just ti)
 | 
								Nothing -> return (Just ti)
 | 
				
			||||||
	| otherwise = return (Just ti)
 | 
						| otherwise = return (Just ti)
 | 
				
			||||||
 | 
					adjustTreeItem UnlockAdjustment Reverse h ti@(TreeItem f m s)
 | 
				
			||||||
 | 
						-- XXX does not remember when files were originally unlocked; locks
 | 
				
			||||||
 | 
						-- everything
 | 
				
			||||||
 | 
						| toBlobType m /= Just SymlinkBlob = do
 | 
				
			||||||
 | 
							mk <- catKey s
 | 
				
			||||||
 | 
							case mk of
 | 
				
			||||||
 | 
								Just k -> do
 | 
				
			||||||
 | 
									absf <- inRepo $ \r -> absPath $
 | 
				
			||||||
 | 
										repoPath r <> fromTopFilePath f r
 | 
				
			||||||
 | 
									linktarget <- calcRepo $ gitAnnexLink absf k
 | 
				
			||||||
 | 
									Just . TreeItem f (fromBlobType SymlinkBlob)
 | 
				
			||||||
 | 
										<$> hashSymlink' h linktarget
 | 
				
			||||||
 | 
								Nothing -> return (Just ti)
 | 
				
			||||||
 | 
						| otherwise = return (Just ti)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type OrigBranch = Branch
 | 
					type OrigBranch = Branch
 | 
				
			||||||
type AdjBranch = Branch
 | 
					type AdjBranch = Branch
 | 
				
			||||||
| 
						 | 
					@ -92,28 +112,34 @@ enterAdjustedBranch :: Adjustment -> Annex ()
 | 
				
			||||||
enterAdjustedBranch adj = go =<< originalBranch
 | 
					enterAdjustedBranch adj = go =<< originalBranch
 | 
				
			||||||
  where
 | 
					  where
 | 
				
			||||||
	go (Just origbranch) = do
 | 
						go (Just origbranch) = do
 | 
				
			||||||
		adjbranch <- preventCommits $ adjustBranch adj origbranch
 | 
							adjbranch <- preventCommits $ adjustBranch adj Forward origbranch
 | 
				
			||||||
		inRepo $ Git.Command.run
 | 
							inRepo $ Git.Command.run
 | 
				
			||||||
			[ Param "checkout"
 | 
								[ Param "checkout"
 | 
				
			||||||
			, Param $ fromRef $ Git.Ref.base $ adjbranch
 | 
								, Param $ fromRef $ Git.Ref.base $ adjbranch
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
	go Nothing = error "not on any branch!"
 | 
						go Nothing = error "not on any branch!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
adjustBranch :: Adjustment -> OrigBranch -> Annex AdjBranch
 | 
					adjustBranch :: Adjustment -> Direction -> OrigBranch -> Annex AdjBranch
 | 
				
			||||||
adjustBranch adj origbranch = do
 | 
					adjustBranch adj direction origbranch = do
 | 
				
			||||||
	sha <- adjust adj origbranch
 | 
						sha <- adjust adj direction origbranch
 | 
				
			||||||
	inRepo $ Git.Branch.update adjbranch sha
 | 
						inRepo $ Git.Branch.update adjbranch sha
 | 
				
			||||||
	return adjbranch
 | 
						return adjbranch
 | 
				
			||||||
  where
 | 
					  where
 | 
				
			||||||
	adjbranch = originalToAdjusted origbranch adj
 | 
						adjbranch = originalToAdjusted origbranch adj
 | 
				
			||||||
 | 
					
 | 
				
			||||||
adjust :: Adjustment -> Ref -> Annex Sha
 | 
					adjust :: Adjustment -> Direction -> Ref -> Annex Sha
 | 
				
			||||||
adjust adj orig = do
 | 
					adjust adj direction orig = do
 | 
				
			||||||
	h <- inRepo hashObjectStart
 | 
						treesha <- adjustTree adj direction orig
 | 
				
			||||||
	treesha <- adjustTree (adjustTreeItem adj h) orig =<< Annex.gitRepo
 | 
					 | 
				
			||||||
	liftIO $ hashObjectStop h
 | 
					 | 
				
			||||||
	commitAdjustedTree treesha orig
 | 
						commitAdjustedTree treesha orig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					adjustTree :: Adjustment -> Direction -> Ref -> Annex Sha
 | 
				
			||||||
 | 
					adjustTree adj direction orig = do
 | 
				
			||||||
 | 
						h <- inRepo hashObjectStart
 | 
				
			||||||
 | 
						treesha <- Git.Tree.adjustTree (adjustTreeItem adj direction h) orig
 | 
				
			||||||
 | 
							=<< Annex.gitRepo
 | 
				
			||||||
 | 
						liftIO $ hashObjectStop h
 | 
				
			||||||
 | 
						return treesha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{- Locks git's index file, preventing git from making a commit, merge, 
 | 
					{- Locks git's index file, preventing git from making a commit, merge, 
 | 
				
			||||||
 - or otherwise changing the HEAD ref while the action is run.
 | 
					 - or otherwise changing the HEAD ref while the action is run.
 | 
				
			||||||
 -
 | 
					 -
 | 
				
			||||||
| 
						 | 
					@ -141,8 +167,11 @@ commitAdjustedTree treesha parent = go =<< catCommit parent
 | 
				
			||||||
		(commitAuthorMetaData parentcommit)
 | 
							(commitAuthorMetaData parentcommit)
 | 
				
			||||||
		(commitCommitterMetaData parentcommit)
 | 
							(commitCommitterMetaData parentcommit)
 | 
				
			||||||
		mkcommit
 | 
							mkcommit
 | 
				
			||||||
	mkcommit = Git.Branch.commitTree
 | 
						mkcommit = Git.Branch.commitTree Git.Branch.AutomaticCommit
 | 
				
			||||||
		Git.Branch.AutomaticCommit "adjusted branch" [parent] treesha
 | 
							adjustedBranchCommitMessage [parent] treesha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					adjustedBranchCommitMessage :: String
 | 
				
			||||||
 | 
					adjustedBranchCommitMessage = "git-annex adjusted branch"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{- Update the currently checked out adjusted branch, merging the provided
 | 
					{- Update the currently checked out adjusted branch, merging the provided
 | 
				
			||||||
 - branch into it. -}
 | 
					 - branch into it. -}
 | 
				
			||||||
| 
						 | 
					@ -154,8 +183,8 @@ updateAdjustedBranch tomerge (origbranch, adj) commitmode =
 | 
				
			||||||
  where
 | 
					  where
 | 
				
			||||||
	go (Just mergesha, Just currbranch) = ifM (inRepo $ Git.Branch.changed currbranch mergesha)
 | 
						go (Just mergesha, Just currbranch) = ifM (inRepo $ Git.Branch.changed currbranch mergesha)
 | 
				
			||||||
		( do
 | 
							( do
 | 
				
			||||||
			propigateAdjustedCommits origbranch adj
 | 
								propigateAdjustedCommits origbranch (adj, currbranch)
 | 
				
			||||||
			adjustedtomerge <- adjust adj mergesha
 | 
								adjustedtomerge <- adjust adj Forward mergesha
 | 
				
			||||||
			ifM (inRepo $ Git.Branch.changed currbranch adjustedtomerge)
 | 
								ifM (inRepo $ Git.Branch.changed currbranch adjustedtomerge)
 | 
				
			||||||
				( ifM (autoMergeFrom adjustedtomerge (Just currbranch) commitmode)
 | 
									( ifM (autoMergeFrom adjustedtomerge (Just currbranch) commitmode)
 | 
				
			||||||
					( recommit currbranch mergesha =<< catCommit currbranch
 | 
										( recommit currbranch mergesha =<< catCommit currbranch
 | 
				
			||||||
| 
						 | 
					@ -176,11 +205,51 @@ updateAdjustedBranch tomerge (origbranch, adj) commitmode =
 | 
				
			||||||
	recommit currbranch parent (Just commit) = do
 | 
						recommit currbranch parent (Just commit) = do
 | 
				
			||||||
		commitsha <- commitAdjustedTree (commitTree commit) parent
 | 
							commitsha <- commitAdjustedTree (commitTree commit) parent
 | 
				
			||||||
		inRepo $ Git.Branch.update currbranch commitsha
 | 
							inRepo $ Git.Branch.update currbranch commitsha
 | 
				
			||||||
		propigateAdjustedCommits origbranch adj
 | 
							propigateAdjustedCommits origbranch (adj, currbranch)
 | 
				
			||||||
		return True
 | 
							return True
 | 
				
			||||||
	recommit _ _ Nothing = return False
 | 
						recommit _ _ Nothing = return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{- Check for any commits present on the adjusted branch that have not yet
 | 
					{- Check for any commits present on the adjusted branch that have not yet
 | 
				
			||||||
 - been propigated to the orig branch, and propigate them. -}
 | 
					 - been propigated to the orig branch, and propigate them.
 | 
				
			||||||
propigateAdjustedCommits :: OrigBranch -> Adjustment -> Annex ()
 | 
					 -
 | 
				
			||||||
propigateAdjustedCommits originbranch adj = return () -- TODO
 | 
					 - After propigating the commits back to the orig banch,
 | 
				
			||||||
 | 
					 - rebase the adjusted branch on top of the updated orig branch.
 | 
				
			||||||
 | 
					 -}
 | 
				
			||||||
 | 
					propigateAdjustedCommits :: OrigBranch -> (Adjustment, AdjBranch) -> Annex ()
 | 
				
			||||||
 | 
					propigateAdjustedCommits origbranch (adj, currbranch) = do
 | 
				
			||||||
 | 
						v <- inRepo $ Git.Ref.sha (Git.Ref.under "refs/heads/" origbranch)
 | 
				
			||||||
 | 
						case v of
 | 
				
			||||||
 | 
							Just origsha -> go origsha False =<< newcommits
 | 
				
			||||||
 | 
							Nothing -> return ()
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
						newcommits = inRepo $ Git.Branch.changedCommits origbranch currbranch
 | 
				
			||||||
 | 
							-- Get commits oldest first, so they can be processed
 | 
				
			||||||
 | 
							-- in order made.
 | 
				
			||||||
 | 
							[Param "--reverse"]
 | 
				
			||||||
 | 
						go newhead _ [] = do
 | 
				
			||||||
 | 
							inRepo $ Git.Branch.update origbranch newhead
 | 
				
			||||||
 | 
							-- TODO rebase adjusted branch
 | 
				
			||||||
 | 
						go parent pastadjcommit (sha:l) = do
 | 
				
			||||||
 | 
							mc <- catCommit sha
 | 
				
			||||||
 | 
							case mc of
 | 
				
			||||||
 | 
								Just c
 | 
				
			||||||
 | 
									| commitMessage c == adjustedBranchCommitMessage ->
 | 
				
			||||||
 | 
										go parent True l
 | 
				
			||||||
 | 
									| pastadjcommit -> do
 | 
				
			||||||
 | 
										commit <- reverseAdjustedCommit parent adj c
 | 
				
			||||||
 | 
										go commit pastadjcommit l
 | 
				
			||||||
 | 
								_ -> go parent pastadjcommit l
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{- Reverses an adjusted commit, yielding a commit sha.
 | 
				
			||||||
 | 
					 -
 | 
				
			||||||
 | 
					 - Note that the commit message, and the author and committer metadata are
 | 
				
			||||||
 | 
					 - copied over. However, any gpg signature will be lost, and any other
 | 
				
			||||||
 | 
					 - headers are not copied either. -}
 | 
				
			||||||
 | 
					reverseAdjustedCommit :: Sha -> Adjustment -> Commit -> Annex Sha
 | 
				
			||||||
 | 
					reverseAdjustedCommit parent adj c = do
 | 
				
			||||||
 | 
						treesha <- adjustTree adj Reverse (commitTree c)
 | 
				
			||||||
 | 
						inRepo $ commitWithMetaData
 | 
				
			||||||
 | 
							(commitAuthorMetaData c)
 | 
				
			||||||
 | 
							(commitCommitterMetaData c) $
 | 
				
			||||||
 | 
							Git.Branch.commitTree Git.Branch.AutomaticCommit
 | 
				
			||||||
 | 
								(commitMessage c) [parent] treesha
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -267,21 +267,20 @@ pushLocal b = do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
updateSyncBranch :: CurrBranch -> Annex ()
 | 
					updateSyncBranch :: CurrBranch -> Annex ()
 | 
				
			||||||
updateSyncBranch (Nothing, _) = noop
 | 
					updateSyncBranch (Nothing, _) = noop
 | 
				
			||||||
updateSyncBranch (Just branch, _) = do
 | 
					updateSyncBranch (Just branch, madj) = do
 | 
				
			||||||
	-- When in an adjusted branch, propigate any changes to it back to
 | 
						-- When in an adjusted branch, propigate any changes to it back to
 | 
				
			||||||
	-- the original branch.
 | 
						-- the original branch.
 | 
				
			||||||
	branch' <- case adjustedToOriginal branch of
 | 
						case madj of
 | 
				
			||||||
		Just (adj, origbranch) -> do
 | 
							Just adj -> propigateAdjustedCommits branch
 | 
				
			||||||
			propigateAdjustedCommits origbranch adj
 | 
								(adj, originalToAdjusted branch adj)
 | 
				
			||||||
			return origbranch
 | 
							Nothing -> return ()
 | 
				
			||||||
		Nothing -> return branch
 | 
					 | 
				
			||||||
	-- Update the sync branch to match the new state of the branch
 | 
						-- Update the sync branch to match the new state of the branch
 | 
				
			||||||
	inRepo $ updateBranch (syncBranch branch') branch'
 | 
						inRepo $ updateBranch (syncBranch branch) branch
 | 
				
			||||||
	-- In direct mode, we're operating on some special direct mode
 | 
						-- In direct mode, we're operating on some special direct mode
 | 
				
			||||||
	-- branch, rather than the intended branch, so update the intended
 | 
						-- branch, rather than the intended branch, so update the intended
 | 
				
			||||||
	-- branch.
 | 
						-- branch.
 | 
				
			||||||
	whenM isDirect $
 | 
						whenM isDirect $
 | 
				
			||||||
		inRepo $ updateBranch (fromDirectBranch branch') branch'
 | 
							inRepo $ updateBranch (fromDirectBranch branch) branch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
updateBranch :: Git.Branch -> Git.Branch -> Git.Repo -> IO ()
 | 
					updateBranch :: Git.Branch -> Git.Branch -> Git.Repo -> IO ()
 | 
				
			||||||
updateBranch syncbranch updateto g = 
 | 
					updateBranch syncbranch updateto g = 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,15 +48,25 @@ currentUnsafe r = parse . firstLine
 | 
				
			||||||
changed :: Branch -> Branch -> Repo -> IO Bool
 | 
					changed :: Branch -> Branch -> Repo -> IO Bool
 | 
				
			||||||
changed origbranch newbranch repo
 | 
					changed origbranch newbranch repo
 | 
				
			||||||
	| origbranch == newbranch = return False
 | 
						| origbranch == newbranch = return False
 | 
				
			||||||
	| otherwise = not . null <$> diffs
 | 
						| otherwise = not . null
 | 
				
			||||||
 | 
							<$> changed' origbranch newbranch [Param "-n1"] repo
 | 
				
			||||||
  where
 | 
					  where
 | 
				
			||||||
	diffs = pipeReadStrict
 | 
					
 | 
				
			||||||
 | 
					changed' :: Branch -> Branch -> [CommandParam] -> Repo -> IO String
 | 
				
			||||||
 | 
					changed' origbranch newbranch extraps repo = pipeReadStrict ps repo
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
						ps =
 | 
				
			||||||
		[ Param "log"
 | 
							[ Param "log"
 | 
				
			||||||
		, Param (fromRef origbranch ++ ".." ++ fromRef newbranch)
 | 
							, Param (fromRef origbranch ++ ".." ++ fromRef newbranch)
 | 
				
			||||||
		, Param "-n1"
 | 
					 | 
				
			||||||
		, Param "--pretty=%H"
 | 
							, Param "--pretty=%H"
 | 
				
			||||||
		] repo
 | 
							] ++ extraps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{- Lists commits that are in the second branch and not in the first branch. -}
 | 
				
			||||||
 | 
					changedCommits :: Branch -> Branch -> [CommandParam] -> Repo -> IO [Sha]
 | 
				
			||||||
 | 
					changedCommits origbranch newbranch extraps repo = 
 | 
				
			||||||
 | 
						catMaybes . map extractSha . lines
 | 
				
			||||||
 | 
							<$> changed' origbranch newbranch extraps repo
 | 
				
			||||||
 | 
						
 | 
				
			||||||
{- Check if it's possible to fast-forward from the old
 | 
					{- Check if it's possible to fast-forward from the old
 | 
				
			||||||
 - ref to the new ref.
 | 
					 - ref to the new ref.
 | 
				
			||||||
 -
 | 
					 -
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -351,3 +351,5 @@ like this, at its most simple:
 | 
				
			||||||
* Entering an adjusted branch can race with commits to the current branch,
 | 
					* Entering an adjusted branch can race with commits to the current branch,
 | 
				
			||||||
  and so the assistant should not be running, or at least should have
 | 
					  and so the assistant should not be running, or at least should have
 | 
				
			||||||
  commits disabled when entering it.
 | 
					  commits disabled when entering it.
 | 
				
			||||||
 | 
					* When the adjusted branch unlocks files, behave as if annex.addunlocked is
 | 
				
			||||||
 | 
					  set, so git annex add will add files unlocked.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue