2011-06-21 20:08:09 +00:00
|
|
|
{- management of the git-annex branch
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
-
|
|
|
|
- Copyright 2011 Joey Hess <joey@kitenet.net>
|
|
|
|
-
|
|
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
|
|
-}
|
|
|
|
|
2011-06-21 20:08:09 +00:00
|
|
|
module Branch (
|
|
|
|
update,
|
2011-06-21 23:11:55 +00:00
|
|
|
get,
|
|
|
|
change,
|
|
|
|
commit
|
2011-06-21 20:08:09 +00:00
|
|
|
) where
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
|
2011-06-21 23:52:40 +00:00
|
|
|
import Control.Monad (unless, liftM)
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
import Control.Monad.State (liftIO)
|
2011-06-21 21:39:45 +00:00
|
|
|
import System.FilePath
|
|
|
|
import System.Directory
|
|
|
|
import Data.String.Utils
|
|
|
|
import System.Cmd.Utils
|
2011-06-21 23:52:40 +00:00
|
|
|
import Data.Maybe
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
|
2011-06-21 21:39:45 +00:00
|
|
|
import qualified GitRepo as Git
|
2011-06-21 23:11:55 +00:00
|
|
|
import qualified GitUnionMerge
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
import qualified Annex
|
|
|
|
import Utility
|
|
|
|
import Types
|
|
|
|
import Messages
|
|
|
|
|
2011-06-21 21:39:45 +00:00
|
|
|
{- Name of the branch that is used to store git-annex's information. -}
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
name :: String
|
|
|
|
name = "git-annex"
|
|
|
|
|
2011-06-21 21:39:45 +00:00
|
|
|
{- Fully qualified name of the branch. -}
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
fullname :: String
|
|
|
|
fullname = "refs/heads/" ++ name
|
|
|
|
|
2011-06-21 21:39:45 +00:00
|
|
|
{- A separate index file for the branch. -}
|
|
|
|
index :: Git.Repo -> FilePath
|
|
|
|
index g = Git.workTree g </> Git.gitDir g </> "index." ++ name
|
|
|
|
|
|
|
|
{- Populates the branch's index file with the current branch contents.
|
|
|
|
-
|
|
|
|
- Usually, this is only done when the index doesn't yet exist, and
|
|
|
|
- the index is used to build up changes to be commited to the branch.
|
|
|
|
-}
|
|
|
|
genIndex :: FilePath -> Git.Repo -> IO ()
|
|
|
|
genIndex f g = do
|
|
|
|
ls <- Git.pipeNullSplit g $
|
|
|
|
map Param ["ls-tree", "-z", "-r", "--full-tree", fullname]
|
|
|
|
forceSuccess =<< Git.pipeWrite g
|
|
|
|
(map Param ["update-index", "-z", "--index-info"])
|
|
|
|
(join "\0" ls)
|
|
|
|
|
|
|
|
{- Runs an action using the branch's index file. -}
|
|
|
|
withIndex :: Annex a -> Annex a
|
|
|
|
withIndex a = do
|
|
|
|
g <- Annex.gitRepo
|
|
|
|
let f = index g
|
|
|
|
liftIO $ Git.useIndex f
|
|
|
|
|
|
|
|
e <- liftIO $ doesFileExist f
|
|
|
|
unless e $ liftIO $ genIndex f g
|
|
|
|
|
|
|
|
r <- a
|
|
|
|
liftIO $ Git.useDefaultIndex
|
|
|
|
return r
|
|
|
|
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
{- Ensures that the branch is up-to-date; should be called before
|
|
|
|
- data is read from it. Runs only once per git-annex run. -}
|
|
|
|
update :: Annex ()
|
|
|
|
update = do
|
|
|
|
updated <- Annex.getState Annex.updated
|
2011-06-21 21:39:45 +00:00
|
|
|
unless updated $ withIndex $ do
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
g <- Annex.gitRepo
|
2011-06-21 23:52:40 +00:00
|
|
|
r <- liftIO $ Git.pipeRead g [Param "show-ref", Param name]
|
|
|
|
let refs = map (last . words) (lines r)
|
|
|
|
updated <- catMaybes `liftM` mapM updateRef refs
|
|
|
|
unless (null updated) $ liftIO $
|
|
|
|
GitUnionMerge.commit g "update" fullname
|
|
|
|
(fullname:updated)
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
Annex.changeState $ \s -> s { Annex.updated = True }
|
|
|
|
|
2011-06-21 23:52:40 +00:00
|
|
|
{- Ensures that a given ref has been merged into the index. -}
|
|
|
|
updateRef :: String -> Annex (Maybe String)
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
updateRef ref
|
2011-06-21 23:52:40 +00:00
|
|
|
| ref == fullname = return Nothing
|
code to update a git-annex branch
There is no suitable git hook to run code when pulling changes that
might need to be merged into the git-annex branch. The post-merge hook
is only run when changes are merged into HEAD, and it's possible,
and indeed likely that many pulls will only have changes in git-annex,
but not in HEAD, and not trigger it.
So, git-annex will have to take care to update the branch before reading
from it, to make sure it has merged in current info from remotes. Happily,
this can be done quite inexpensively, just a git-show-ref to list
branches, and a minimalized git-log to see if there are unmerged changes
on the branches. To further speed up, it will be done only once per
git-annex run, max.
2011-06-21 18:29:09 +00:00
|
|
|
| otherwise = do
|
|
|
|
g <- Annex.gitRepo
|
|
|
|
diffs <- liftIO $ Git.pipeRead g [
|
|
|
|
Param "log",
|
|
|
|
Param (name++".."++ref),
|
|
|
|
Params "--oneline -n1"
|
|
|
|
]
|
2011-06-21 23:52:40 +00:00
|
|
|
if (null diffs)
|
|
|
|
then return Nothing
|
|
|
|
else do
|
|
|
|
showSideAction $ "merging " ++ ref ++ " into " ++ name ++ "..."
|
|
|
|
-- By passing only one ref, it is actually
|
|
|
|
-- merged into the index, preserving any
|
|
|
|
-- changes that may already be staged.
|
|
|
|
liftIO $ GitUnionMerge.merge g [ref]
|
|
|
|
return $ Just ref
|
2011-06-21 20:08:09 +00:00
|
|
|
|
2011-06-21 21:39:45 +00:00
|
|
|
{- Stages the content of a file into the branch's index. -}
|
2011-06-21 20:08:09 +00:00
|
|
|
change :: FilePath -> String -> Annex ()
|
2011-06-21 23:11:55 +00:00
|
|
|
change file content = do
|
2011-06-21 21:39:45 +00:00
|
|
|
g <- Annex.gitRepo
|
|
|
|
sha <- liftIO $ Git.hashObject g content
|
|
|
|
withIndex $ liftIO $ Git.run g "update-index"
|
|
|
|
[ Params "--add --cacheinfo 100644 ",
|
|
|
|
Param sha, File file]
|
2011-06-21 20:08:09 +00:00
|
|
|
|
|
|
|
{- Commits staged changes to the branch. -}
|
2011-06-21 21:39:45 +00:00
|
|
|
commit :: String -> Annex ()
|
|
|
|
commit message = withIndex $ do
|
|
|
|
g <- Annex.gitRepo
|
2011-06-21 23:52:40 +00:00
|
|
|
liftIO $ GitUnionMerge.commit g message fullname []
|
2011-06-21 21:39:45 +00:00
|
|
|
|
|
|
|
{- Gets the content of a file on the branch, or content staged in the index
|
|
|
|
- if it's newer. Returns an empty string if the file didn't exist yet. -}
|
|
|
|
get :: FilePath -> Annex String
|
2011-06-21 23:11:55 +00:00
|
|
|
get file = update >> do
|
|
|
|
withIndex $ do
|
|
|
|
g <- Annex.gitRepo
|
|
|
|
liftIO $ catch (cat g) (const $ return "")
|
2011-06-21 21:39:45 +00:00
|
|
|
where
|
|
|
|
-- To avoid stderr from cat-file when file does not exist,
|
|
|
|
-- first run it with -e to check that it exists.
|
|
|
|
cat g = do
|
|
|
|
Git.run g "cat-file" [Param "-e", catfile]
|
|
|
|
Git.pipeRead g [Param "cat-file", Param "blob", catfile]
|
|
|
|
catfile = Param $ ':':file
|