summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Annex/Branch.hs2
-rw-r--r--Command/DropUnused.hs4
-rw-r--r--Command/Sync.hs70
-rw-r--r--Config.hs7
-rw-r--r--Git.hs20
-rw-r--r--GitAnnex.hs4
-rw-r--r--Utility/BadPrelude.hs28
-rw-r--r--Utility/Misc.hs13
-rw-r--r--debian/changelog2
-rw-r--r--doc/git-annex.mdwn11
10 files changed, 141 insertions, 20 deletions
diff --git a/Annex/Branch.hs b/Annex/Branch.hs
index 8f0a09fd6..37237ec66 100644
--- a/Annex/Branch.hs
+++ b/Annex/Branch.hs
@@ -141,7 +141,7 @@ update = onceonly $ do
let merge_desc = if null branches
then "update"
else "merging " ++
- unwords (map (show . Git.refDescribe) branches) ++
+ unwords (map Git.refDescribe branches) ++
" into " ++ show name
unless (null branches) $ do
showSideAction merge_desc
diff --git a/Command/DropUnused.hs b/Command/DropUnused.hs
index 3df9ab6c2..244f378d9 100644
--- a/Command/DropUnused.hs
+++ b/Command/DropUnused.hs
@@ -73,6 +73,6 @@ readUnusedLog prefix = do
then M.fromList . map parse . lines <$> liftIO (readFile f)
else return M.empty
where
- parse line = (num, fromJust $ readKey $ tail rest)
+ parse line = (num, fromJust $ readKey rest)
where
- (num, rest) = break (== ' ') line
+ (num, rest) = separate (== ' ') line
diff --git a/Command/Sync.hs b/Command/Sync.hs
new file mode 100644
index 000000000..7dc5f4d24
--- /dev/null
+++ b/Command/Sync.hs
@@ -0,0 +1,70 @@
+{- git-annex command
+ -
+ - Copyright 2011 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Command.Sync where
+
+import Common.Annex
+import Command
+import qualified Annex.Branch
+import qualified Git
+
+import qualified Data.ByteString.Lazy.Char8 as L
+
+def :: [Command]
+def = [command "sync" paramPaths seek "synchronize local repository with remote"]
+
+-- syncing involves several operations, any of which can independantly fail
+seek :: [CommandSeek]
+seek = map withNothing [commit, pull, push]
+
+commit :: CommandStart
+commit = do
+ showStart "commit" ""
+ next $ next $ do
+ showOutput
+ -- Commit will fail when the tree is clean, so ignore failure.
+ _ <- inRepo $ Git.runBool "commit" [Param "-a", Param "-m", Param "sync"]
+ return True
+
+pull :: CommandStart
+pull = do
+ remote <- defaultRemote
+ showStart "pull" remote
+ next $ next $ do
+ showOutput
+ checkRemote remote
+ inRepo $ Git.runBool "pull" [Param remote]
+
+push :: CommandStart
+push = do
+ remote <- defaultRemote
+ showStart "push" remote
+ next $ next $ do
+ Annex.Branch.update
+ showOutput
+ inRepo $ Git.runBool "push" [Param remote, matchingbranches]
+ where
+ -- git push may be configured to not push matching
+ -- branches; this should ensure it always does.
+ matchingbranches = Param ":"
+
+-- the remote defaults to origin when not configured
+defaultRemote :: Annex String
+defaultRemote = do
+ branch <- currentBranch
+ fromRepo $ Git.configGet ("branch." ++ branch ++ ".remote") "origin"
+
+currentBranch :: Annex String
+currentBranch = last . split "/" . L.unpack . head . L.lines <$>
+ inRepo (Git.pipeRead [Param "symbolic-ref", Param "HEAD"])
+
+checkRemote :: String -> Annex ()
+checkRemote remote = do
+ remoteurl <- fromRepo $
+ Git.configGet ("remote." ++ remote ++ ".url") ""
+ when (null remoteurl) $ do
+ error $ "No url is configured for the remote: " ++ remote
diff --git a/Config.hs b/Config.hs
index cc0c92953..c6107fc8e 100644
--- a/Config.hs
+++ b/Config.hs
@@ -79,9 +79,10 @@ repoNotIgnored r = not . Git.configTrue <$> getConfig r "ignore" "false"
{- If a value is specified, it is used; otherwise the default is looked up
- in git config. forcenumcopies overrides everything. -}
getNumCopies :: Maybe Int -> Annex Int
-getNumCopies v =
- Annex.getState Annex.forcenumcopies >>= maybe (use v) (return . id)
+getNumCopies v = perhaps (use v) =<< Annex.getState Annex.forcenumcopies
where
use (Just n) = return n
- use Nothing = read <$> fromRepo (Git.configGet config "1")
+ use Nothing = perhaps (return 1) =<<
+ readMaybe <$> fromRepo (Git.configGet config "1")
+ perhaps fallback = maybe fallback (return . id)
config = "annex.numcopies"
diff --git a/Git.hs b/Git.hs
index 5bdd4afd4..8bc32b7cc 100644
--- a/Git.hs
+++ b/Git.hs
@@ -345,7 +345,7 @@ urlPort :: Repo -> Maybe Integer
urlPort r =
case urlAuthPart uriPort r of
":" -> Nothing
- (':':p) -> Just (read p)
+ (':':p) -> readMaybe p
_ -> Nothing
{- Hostname of an URL repo, including any username (ie, "user@host") -}
@@ -507,11 +507,7 @@ configStore s repo = do
configParse :: String -> M.Map String String
configParse s = M.fromList $ map pair $ lines s
where
- pair l = (key l, val l)
- key l = head $ keyval l
- val l = join sep $ drop 1 $ keyval l
- keyval l = split sep l :: [String]
- sep = "="
+ pair = separate (== '=')
{- Calculates a list of a repo's configured remotes, by parsing its config. -}
configRemotes :: Repo -> IO [Repo]
@@ -550,13 +546,11 @@ genRemote s repo = gen $ calcloc s
scpstyle v = ":" `isInfixOf` v && not ("//" `isInfixOf` v)
scptourl v = "ssh://" ++ host ++ slash dir
where
- bits = split ":" v
- host = head bits
- dir = join ":" $ drop 1 bits
- slash d | d == "" = "/~/" ++ dir
- | head d == '/' = dir
- | head d == '~' = '/':dir
- | otherwise = "/~/" ++ dir
+ (host, dir) = separate (== ':') v
+ slash d | d == "" = "/~/" ++ d
+ | "/" `isPrefixOf` d = d
+ | "~" `isPrefixOf` d = '/':d
+ | otherwise = "/~/" ++ d
{- Checks if a string from git config is a true value. -}
configTrue :: String -> Bool
diff --git a/GitAnnex.hs b/GitAnnex.hs
index d768499dd..7871638e4 100644
--- a/GitAnnex.hs
+++ b/GitAnnex.hs
@@ -47,6 +47,7 @@ import qualified Command.Trust
import qualified Command.Untrust
import qualified Command.Semitrust
import qualified Command.Dead
+import qualified Command.Sync
import qualified Command.AddUrl
import qualified Command.Map
import qualified Command.Upgrade
@@ -61,6 +62,8 @@ cmds = concat
, Command.Copy.def
, Command.Unlock.def
, Command.Lock.def
+ , Command.Sync.def
+ , Command.AddUrl.def
, Command.Init.def
, Command.Describe.def
, Command.InitRemote.def
@@ -72,7 +75,6 @@ cmds = concat
, Command.Untrust.def
, Command.Semitrust.def
, Command.Dead.def
- , Command.AddUrl.def
, Command.FromKey.def
, Command.DropKey.def
, Command.Fix.def
diff --git a/Utility/BadPrelude.hs b/Utility/BadPrelude.hs
new file mode 100644
index 000000000..7921a7e9b
--- /dev/null
+++ b/Utility/BadPrelude.hs
@@ -0,0 +1,28 @@
+{- Some stuff from Prelude should not be used, as it tends to be a source
+ - of bugs.
+ -
+ - This exports functions that conflict with the prelude, which avoids
+ - them being accidentially used.
+ -}
+
+module Utility.BadPrelude where
+
+{- head is a partial function; head [] is an error -}
+head :: [a] -> a
+head = Prelude.head
+
+{- tail is also partial -}
+tail :: [a] -> a
+tail = Prelude.tail
+
+{- init too -}
+init :: [a] -> a
+init = Prelude.init
+
+{- last too -}
+last :: [a] -> a
+last = Prelude.last
+
+{- read should be avoided, as it throws an error -}
+read :: Read a => String -> a
+read = Prelude.read
diff --git a/Utility/Misc.hs b/Utility/Misc.hs
index 728598723..541e150b7 100644
--- a/Utility/Misc.hs
+++ b/Utility/Misc.hs
@@ -27,6 +27,19 @@ readMaybe s = case reads s of
((x,_):_) -> Just x
_ -> Nothing
+{- Like break, but the character matching the condition is not included
+ - in the second result list.
+ -
+ - separate (== ':') "foo:bar" = ("foo", "bar")
+ - separate (== ':') "foobar" = ("foo, "")
+ -}
+separate :: (a -> Bool) -> [a] -> ([a], [a])
+separate c l = unbreak $ break c l
+ where
+ unbreak r@(a, b)
+ | null b = r
+ | otherwise = (a, tail b)
+
{- Catches IO errors and returns a Bool -}
catchBoolIO :: IO Bool -> IO Bool
catchBoolIO a = catchDefaultIO a False
diff --git a/debian/changelog b/debian/changelog
index 1c27ad566..b481d9999 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,8 @@ git-annex (3.20111204) UNRELEASED; urgency=low
multiple different encrypted special remotes.
* unannex: Can be run on files that have been added to the annex, but not
yet committed.
+ * sync: New command that synchronises the local repository and default
+ remote, by running git commit, pull, and push for you.
-- Joey Hess <joeyh@debian.org> Sun, 04 Dec 2011 12:22:37 -0400
diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn
index 08def0d62..d7a51663f 100644
--- a/doc/git-annex.mdwn
+++ b/doc/git-annex.mdwn
@@ -120,6 +120,17 @@ subdirectories).
Use this to undo an unlock command if you don't want to modify
the files, or have made modifications you want to discard.
+* sync
+
+ Use this command when you want to synchronize the local repository
+ with its default remote (typically "origin"). The sync process involves
+ first committing all local changes, then pulling and merging any changes
+ from the remote, and finally pushing the repository's state to the remote.
+ You can use standard git commands to do each of those steps by hand,
+ or if you don't want to worry about the details, you can use sync.
+
+ Note that sync does not transfer any file contents from or to the remote.
+
* addurl [url ...]
Downloads each url to a file, which is added to the annex.