git-annex 5.20131120 → 5.20131127
raw patch · 130 files changed
+2541/−398 lines, 130 filesbinary-added
Files
- Annex.hs +9/−23
- Annex/Content.hs +1/−0
- Annex/Direct/Fixup.hs +31/−0
- Annex/Exception.hs +2/−0
- Annex/Path.hs +34/−0
- Assistant.hs +4/−0
- Assistant/Alert.hs +60/−15
- Assistant/Alert/Utility.hs +1/−1
- Assistant/NamedThread.hs +1/−1
- Assistant/Repair.hs +1/−1
- Assistant/Restart.hs +86/−0
- Assistant/Threads/NetWatcher.hs +4/−1
- Assistant/Threads/TransferWatcher.hs +6/−0
- Assistant/Threads/UpgradeWatcher.hs +109/−0
- Assistant/Threads/Upgrader.hs +101/−0
- Assistant/Threads/WebApp.hs +1/−0
- Assistant/Types/Alert.hs +4/−2
- Assistant/Types/DaemonStatus.hs +16/−4
- Assistant/Upgrade.hs +316/−0
- Assistant/WebApp/Configurators/Local.hs +1/−1
- Assistant/WebApp/Configurators/Pairing.hs +1/−0
- Assistant/WebApp/Configurators/Preferences.hs +17/−0
- Assistant/WebApp/Configurators/Upgrade.hs +48/−0
- Assistant/WebApp/Configurators/XMPP.hs +1/−0
- Assistant/WebApp/Control.hs +30/−26
- Assistant/WebApp/Notifications.hs +12/−1
- Assistant/WebApp/OtherRepos.hs +2/−38
- Assistant/WebApp/Page.hs +6/−1
- Assistant/WebApp/SideBar.hs +14/−8
- Assistant/WebApp/Types.hs +9/−0
- Assistant/WebApp/routes +8/−1
- Build/BundledPrograms.hs +5/−0
- Build/Configure.hs +9/−2
- Build/DistributionUpdate.hs +64/−0
- CHANGELOG +27/−0
- Command/ImportFeed.hs +1/−1
- Command/Reinject.hs +1/−1
- Command/Upgrade.hs +0/−4
- Git/Config.hs +7/−2
- Git/Fsck.hs +12/−20
- Git/Objects.hs +8/−2
- Git/Repair.hs +143/−136
- Makefile +12/−7
- Seek.hs +5/−3
- Test.hs +1/−1
- Types/Distribution.hs +38/−0
- Types/GitConfig.hs +3/−0
- Upgrade.hs +10/−2
- Utility/FileMode.hs +4/−0
- Utility/Misc.hs +10/−0
- Utility/Quvi.hs +61/−9
- Utility/Tmp.hs +1/−1
- Utility/Url.hs +2/−1
- debian/changelog +27/−0
- doc/assistant/downloadupgrade.png binary
- doc/assistant/upgradecomplete.png binary
- doc/bugs/Assistant_has_created_155_semitrusted_repositories.mdwn +191/−0
- doc/bugs/Finding_an_Unused_file.mdwn +1/−1
- doc/bugs/Git_annex_add_fails_on_read-only_files.mdwn +37/−0
- doc/bugs/Lost_S3_Remote/comment_1_6e80e6db6671581d471fc9a54181c04c._comment +1/−1
- doc/bugs/Too_many_open_files.mdwn +55/−0
- doc/bugs/direct_mode_sync_should_avoid_git_commit.mdwn +5/−0
- doc/bugs/git-annex_does_not_install_on_windows_without_admin_rights.mdwn +19/−0
- doc/bugs/git_annex_indirect_can_fail_catastrophically.mdwn +1/−1
- doc/bugs/repair_fails_when_home_on_seperate_partition.mdwn +60/−0
- doc/bugs/test_failures_on_window_for_5.20131118.mdwn +20/−0
- doc/bugs/utf8/comment_13_7044d2c5bb1c91ee37eb9868963a1ff2._comment +1/−1
- doc/builds.mdwn +2/−2
- doc/design/assistant/blog/day_140__release_monday.mdwn +1/−1
- doc/design/assistant/blog/day_83__3-way.mdwn +1/−1
- doc/design/assistant/gpgkeys.mdwn +1/−1
- doc/design/assistant/polls/Android_default_directory.mdwn +1/−1
- doc/design/assistant/upgrading.mdwn +52/−0
- doc/design/roadmap.mdwn +1/−1
- doc/devblog/day_-4__forgetting.mdwn +1/−1
- doc/devblog/day_48__direct_mode_guard_design.mdwn +1/−1
- doc/devblog/day_61__damage_driven_development__II.mdwn +15/−0
- doc/devblog/day_62__upgrade_alerts.mdwn +22/−0
- doc/devblog/day_63__leverage.mdwn +24/−0
- doc/devblog/day_64__overkill.mdwn +31/−0
- doc/devblog/day_65__wrapping_up_upgrades.mdwn +5/−0
- doc/devblog/day_66__upgrade_testing.mdwn +17/−0
- doc/devblog/day_67_thanksgiving_rush.mdwn +19/−0
- doc/devblog/day_9__Friday_the_13th.mdwn +1/−1
- doc/forum/New_special_remote_suggeston_-_clean_directory.mdwn +15/−0
- doc/forum/Some_mounted_devices_not_detected.mdwn +3/−0
- doc/forum/could_not_read_from_remote_repository.mdwn +36/−0
- doc/forum/dropping_files_not_working_when_using_git_annex_assistant.txt +18/−0
- doc/forum/s3_vs_ssh_Performance_Problems.mdwn +8/−0
- doc/forum/unsynced_folder.mdwn +3/−0
- doc/git-annex.mdwn +16/−1
- doc/ikiwiki/pagespec.mdwn +86/−0
- doc/install/OSX.mdwn +1/−1
- doc/install/OSX/comment_32_a46d8e3e7795b9afb1e1c2be943d12af._comment +1/−1
- doc/install/cabal/comment_29_ac082dca67f4a29b06070c0283130f52._comment +39/−0
- doc/install/cabal/comment_30_ad639c07cb79e89406e95c1dafce3a01._comment +35/−0
- doc/install/cabal/comment_31_4763b24a29627d55f465b9ea260ea7ec._comment +22/−0
- doc/install/cabal/comment_32_1d34c294486c85b1149675fa5861ae35._comment +10/−0
- doc/internals.mdwn +1/−1
- doc/news/2013_git-annex_user_survey.mdwn +5/−0
- doc/news/version_4.20131024.mdwn +0/−43
- doc/news/version_5.20131127.mdwn +24/−0
- doc/special_remotes/comment_20_6b7242721f2f2c77b634568cb737e3e3._comment +13/−0
- doc/special_remotes/comment_21_5c11e69c28b9ed4cbe238a36c0839a47._comment +15/−0
- doc/special_remotes/xmpp.mdwn +1/−1
- doc/special_remotes/xmpp/comment_9_eda76b826491c96b1ce072aacf9d3adf._comment +23/−0
- doc/sync/comment_6_012e9d4468d0b88ee3c5dad3911c3606._comment +10/−0
- doc/sync/comment_7_6276e100d1341f1a0be368f54de0ae7b._comment +8/−0
- doc/tips/Crude_Windows_Sync.mdwn +35/−0
- doc/todo/Check_if_an_upgrade_is_available_in_the_webapp.mdwn +2/−0
- doc/todo/Not_working_on_Android-x86.mdwn +19/−0
- doc/todo/checksum_verification_on_transfer.mdwn +1/−1
- doc/todo/dumb_plaindir_remote___40__e.g._for_NAS_mounts__41__.mdwn +5/−0
- doc/todo/quvi_0.9_support.mdwn +8/−0
- doc/todo/special_remote_for_amazon_glacier.mdwn +1/−1
- doc/todo/wishlist:_make_git_annex_reinject_work_in_direct_mode.mdwn +3/−0
- git-annex.1 +15/−1
- git-annex.cabal +9/−3
- standalone/android/Makefile +7/−1
- standalone/windows/build.sh +2/−0
- static/longpolling.js +18/−4
- templates/configurators/ssh/add.hamlet +1/−1
- templates/configurators/upgrade/android.hamlet +9/−0
- templates/control/notrunning.hamlet +10/−0
- templates/control/notrunning.julius +3/−0
- templates/control/restarting.hamlet +0/−2
- templates/control/shutdownconfirmed.hamlet +0/−2
- templates/notifications/longpolling.julius +1/−1
- templates/page.julius +22/−0
- templates/sidebar/alert.hamlet +4/−3
Annex.hs view
@@ -5,7 +5,7 @@ - Licensed under the GNU GPL version 3 or higher. -} -{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE GeneralizedNewtypeDeriving, PackageImports #-} module Annex ( Annex,@@ -40,12 +40,11 @@ import Common import qualified Git import qualified Git.Config-import Git.Types hiding (remotes)+import Annex.Direct.Fixup import Git.CatFile import Git.CheckAttr import Git.CheckIgnore import Git.SharedRepository-import Git.Config import qualified Git.Queue import Types.Backend import Types.GitConfig@@ -112,9 +111,9 @@ , useragent :: Maybe String } -newState :: Git.Repo -> AnnexState-newState r = AnnexState- { repo = if annexDirect c then fixupDirect r else r+newState :: GitConfig -> Git.Repo -> AnnexState+newState c r = AnnexState+ { repo = r , gitconfig = c , backends = [] , remotes = []@@ -145,13 +144,14 @@ , inodeschanged = Nothing , useragent = Nothing }- where- c = extractGitConfig r {- Makes an Annex state object for the specified git repo. - Ensures the config is read, if it was not already. -} new :: Git.Repo -> IO AnnexState-new = newState <$$> Git.Config.read+new r = do+ r' <- Git.Config.read r+ let c = extractGitConfig r'+ newState c <$> if annexDirect c then fixupDirect r' else return r' {- Performs an action in the Annex monad from a starting state, - returning a new state. -}@@ -250,17 +250,3 @@ withCurrentState a = do s <- getState id return $ eval s a--{- Direct mode repos have core.bare=true, but are not really bare.- - Fix up the Repo to be a non-bare repo, and arrange for git commands- - run by git-annex to be passed parameters that override this setting. -}-fixupDirect :: Git.Repo -> Git.Repo-fixupDirect r@(Repo { location = Local { gitdir = d, worktree = Nothing } }) =- r- { location = Local { gitdir = d </> ".git", worktree = Just d }- , gitGlobalOpts = gitGlobalOpts r ++- [ Param "-c"- , Param $ coreBare ++ "=" ++ boolConfig False- ]- }-fixupDirect r = r
Annex/Content.hs view
@@ -30,6 +30,7 @@ freezeContent, thawContent, dirKeys,+ withObjectLoc, ) where import System.IO.Unsafe (unsafeInterleaveIO)
+ Annex/Direct/Fixup.hs view
@@ -0,0 +1,31 @@+{- git-annex direct mode guard fixup+ -+ - Copyright 2013 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Annex.Direct.Fixup where++import Git.Types+import Git.Config+import qualified Git.Construct as Construct+import Utility.Path+import Utility.SafeCommand++{- Direct mode repos have core.bare=true, but are not really bare.+ - Fix up the Repo to be a non-bare repo, and arrange for git commands+ - run by git-annex to be passed parameters that override this setting. -}+fixupDirect :: Repo -> IO Repo+fixupDirect r@(Repo { location = l@(Local { gitdir = d, worktree = Nothing }) }) = do+ let r' = r+ { location = l { worktree = Just (parentDir d) }+ , gitGlobalOpts = gitGlobalOpts r +++ [ Param "-c"+ , Param $ coreBare ++ "=" ++ boolConfig False+ ]+ }+ -- Recalc now that the worktree is correct.+ rs' <- Construct.fromRemotes r'+ return $ r' { remotes = rs' }+fixupDirect r = return r
Annex/Exception.hs view
@@ -10,6 +10,8 @@ - Licensed under the GNU GPL version 3 or higher. -} +{-# LANGUAGE PackageImports #-}+ module Annex.Exception ( bracketIO, tryAnnex,
+ Annex/Path.hs view
@@ -0,0 +1,34 @@+{- git-annex program path+ -+ - Copyright 2013 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++{-# LANGUAGE CPP #-}++module Annex.Path where++import Common+import Config.Files+import System.Environment++{- A fully qualified path to the currently running git-annex program.+ - + - getExecutablePath is available since ghc 7.4.2. On OSs it supports+ - well, it returns the complete path to the program. But, on other OSs,+ - it might return just the basename.+ -}+programPath :: IO (Maybe FilePath)+programPath = do+#if MIN_VERSION_base(4,6,0)+ exe <- getExecutablePath+ p <- if isAbsolute exe+ then return exe+ else readProgramFile+#else+ p <- readProgramFile+#endif+ -- In case readProgramFile returned just the command name,+ -- fall back to finding it in PATH.+ searchPath p
Assistant.hs view
@@ -28,6 +28,8 @@ import Assistant.Threads.MountWatcher #endif import Assistant.Threads.NetWatcher+import Assistant.Threads.Upgrader+import Assistant.Threads.UpgradeWatcher import Assistant.Threads.TransferScanner import Assistant.Threads.TransferPoller import Assistant.Threads.ConfigMonitor@@ -150,6 +152,8 @@ , assist $ mountWatcherThread urlrenderer #endif , assist $ netWatcherThread+ , assist $ upgraderThread urlrenderer+ , assist $ upgradeWatcherThread urlrenderer , assist $ netWatcherFallbackThread , assist $ transferScannerThread urlrenderer , assist $ cronnerThread urlrenderer
Assistant/Alert.hs view
@@ -15,6 +15,7 @@ import qualified Remote import Utility.Tense import Logs.Transfer+import Types.Distribution import Data.String import qualified Data.Text as T@@ -42,6 +43,7 @@ { buttonLabel = label , buttonUrl = url , buttonAction = if autoclose then Just close else Nothing+ , buttonPrimary = True } #endif @@ -61,7 +63,7 @@ , alertIcon = Just ActivityIcon , alertCombiner = Nothing , alertName = Nothing- , alertButton = Nothing+ , alertButtons = [] } warningAlert :: String -> String -> Alert@@ -77,11 +79,11 @@ , alertIcon = Just ErrorIcon , alertCombiner = Just $ dataCombiner $ \_old new -> new , alertName = Just $ WarningAlert name- , alertButton = Nothing+ , alertButtons = [] } -errorAlert :: String -> AlertButton -> Alert-errorAlert msg button = Alert+errorAlert :: String -> [AlertButton] -> Alert+errorAlert msg buttons = Alert { alertClass = Error , alertHeader = Nothing , alertMessageRender = renderData@@ -93,7 +95,7 @@ , alertIcon = Just ErrorIcon , alertCombiner = Nothing , alertName = Nothing- , alertButton = Just button+ , alertButtons = buttons } activityAlert :: Maybe TenseText -> [TenseChunk] -> Alert@@ -160,7 +162,7 @@ , alertIcon = Just ErrorIcon , alertName = Just SanityCheckFixAlert , alertCombiner = Just $ dataCombiner (++)- , alertButton = Nothing+ , alertButtons = [] } where render alert = tenseWords $ alerthead : alertData alert ++ [alertfoot]@@ -172,7 +174,7 @@ { alertData = case mr of Nothing -> [ UnTensed $ T.pack $ "Consistency check in progress" ] Just r -> [ UnTensed $ T.pack $ "Consistency check of " ++ Remote.name r ++ " in progress"]- , alertButton = Just button+ , alertButtons = [button] } showFscking :: UrlRenderer -> Maybe Remote -> IO (Either E.SomeException a) -> Assistant a@@ -204,7 +206,7 @@ ] , alertIcon = Just InfoIcon , alertPriority = High- , alertButton = Just button+ , alertButtons = [button] , alertClosable = True , alertClass = Message , alertMessageRender = renderData@@ -215,7 +217,50 @@ , alertData = [] } -brokenRepositoryAlert :: AlertButton -> Alert+baseUpgradeAlert :: [AlertButton] -> TenseText -> Alert+baseUpgradeAlert buttons message = Alert+ { alertHeader = Just message+ , alertIcon = Just UpgradeIcon+ , alertPriority = High+ , alertButtons = buttons+ , alertClosable = True+ , alertClass = Message+ , alertMessageRender = renderData+ , alertCounter = 0+ , alertBlockDisplay = True+ , alertName = Just UpgradeAlert+ , alertCombiner = Just $ fullCombiner $ \new _old -> new+ , alertData = []+ }++canUpgradeAlert :: AlertPriority -> GitAnnexVersion -> AlertButton -> Alert+canUpgradeAlert priority version button = + (baseUpgradeAlert [button] $ fromString msg)+ { alertPriority = priority+ , alertData = [fromString $ " (version " ++ version ++ ")"]+ }+ where+ msg = if priority >= High+ then "An important upgrade of git-annex is available!"+ else "An upgrade of git-annex is available."++upgradeReadyAlert :: AlertButton -> Alert+upgradeReadyAlert button = baseUpgradeAlert [button] $+ fromString "A new version of git-annex has been installed."++upgradingAlert :: Alert+upgradingAlert = activityAlert Nothing [ fromString "Upgrading git-annex" ]++upgradeFinishedAlert :: Maybe AlertButton -> GitAnnexVersion -> Alert+upgradeFinishedAlert button version =+ baseUpgradeAlert (maybe [] (:[]) button) $ fromString $ + "Finished upgrading git-annex to version " ++ version++upgradeFailedAlert :: String -> Alert+upgradeFailedAlert msg = (errorAlert msg [])+ { alertHeader = Just $ fromString "Upgrade failed." }++brokenRepositoryAlert :: [AlertButton] -> Alert brokenRepositoryAlert = errorAlert "Serious problems have been detected with your repository. This needs your immediate attention!" repairingAlert :: String -> Alert@@ -228,7 +273,7 @@ pairingAlert button = baseActivityAlert { alertData = [ UnTensed "Pairing in progress" ] , alertPriority = High- , alertButton = Just button+ , alertButtons = [button] } pairRequestReceivedAlert :: String -> AlertButton -> Alert@@ -244,7 +289,7 @@ , alertIcon = Just InfoIcon , alertName = Just $ PairAlert who , alertCombiner = Just $ dataCombiner $ \_old new -> new- , alertButton = Just button+ , alertButtons = [button] } pairRequestAcknowledgedAlert :: String -> Maybe AlertButton -> Alert@@ -253,7 +298,7 @@ , alertPriority = High , alertName = Just $ PairAlert who , alertCombiner = Just $ dataCombiner $ \_old new -> new- , alertButton = button+ , alertButtons = maybe [] (:[]) button } xmppNeededAlert :: AlertButton -> Alert@@ -261,7 +306,7 @@ { alertHeader = Just "Share with friends, and keep your devices in sync across the cloud." , alertIcon = Just TheCloud , alertPriority = High- , alertButton = Just button+ , alertButtons = [button] , alertClosable = True , alertClass = Message , alertMessageRender = renderData@@ -280,7 +325,7 @@ ] , alertIcon = Just ErrorIcon , alertPriority = High- , alertButton = Just button+ , alertButtons = [button] , alertClosable = True , alertClass = Message , alertMessageRender = renderData@@ -298,7 +343,7 @@ "\" has been emptied, and can now be removed." , alertIcon = Just InfoIcon , alertPriority = High- , alertButton = Just button+ , alertButtons = [button] , alertClosable = True , alertClass = Message , alertMessageRender = renderData
Assistant/Alert/Utility.hs view
@@ -87,7 +87,7 @@ { alertClass = if c == Activity then c' else c , alertPriority = Filler , alertClosable = True- , alertButton = Nothing+ , alertButtons = [] , alertIcon = Just $ if success then SuccessIcon else ErrorIcon } where
Assistant/NamedThread.hs view
@@ -82,7 +82,7 @@ (RestartThreadR name) runAssistant d $ void $ addAlert $ (warningAlert (fromThreadName name) msg)- { alertButton = Just button }+ { alertButtons = [button] } #endif namedThreadId :: NamedThread -> Assistant (Maybe ThreadId)
Assistant/Repair.hs view
@@ -46,7 +46,7 @@ unless ok $ do button <- mkAlertButton True (T.pack "Click Here") urlrenderer $ RepairRepositoryR u- void $ addAlert $ brokenRepositoryAlert button+ void $ addAlert $ brokenRepositoryAlert [button] #endif return ok | otherwise = return False
+ Assistant/Restart.hs view
@@ -0,0 +1,86 @@+{- git-annex assistant restarting+ -+ - Copyright 2013 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU AGPL version 3 or higher.+ -}++module Assistant.Restart where++import Assistant.Common+import Assistant.Threads.Watcher+import Assistant.DaemonStatus+import Assistant.NamedThread+import Utility.ThreadScheduler+import Utility.NotificationBroadcaster+import Utility.Url+import qualified Git.Construct+import qualified Git.Config+import Config.Files+import qualified Annex+import qualified Git++import Control.Concurrent+import System.Posix (getProcessID, signalProcess, sigTERM)+import System.Process (cwd)++{- Before the assistant can be restarted, have to remove our + - gitAnnexUrlFile and our gitAnnexPidFile. Pausing the watcher is also+ - a good idea, to avoid fighting when two assistants are running in the+ - same repo.+ -}+prepRestart :: Assistant ()+prepRestart = do+ liftIO . maybe noop (`throwTo` PauseWatcher) =<< namedThreadId watchThread+ liftIO . nukeFile =<< liftAnnex (fromRepo gitAnnexUrlFile)+ liftIO . nukeFile =<< liftAnnex (fromRepo gitAnnexPidFile)++{- To finish a restart, send a global redirect to the new url+ - to any web browsers that are displaying the webapp.+ -+ - Wait for browser to update before terminating this process. -}+postRestart :: URLString -> Assistant ()+postRestart url = do+ modifyDaemonStatus_ $ \status -> status { globalRedirUrl = Just url }+ liftIO . sendNotification . globalRedirNotifier =<< getDaemonStatus+ void $ liftIO $ forkIO $ do+ threadDelaySeconds (Seconds 120)+ signalProcess sigTERM =<< getProcessID++runRestart :: Assistant URLString+runRestart = liftIO . newAssistantUrl+ =<< liftAnnex (Git.repoLocation <$> Annex.gitRepo)++{- Starts up the assistant in the repository, and waits for it to create+ - a gitAnnexUrlFile. Waits for the assistant to be up and listening for+ - connections by testing the url. -}+newAssistantUrl :: FilePath -> IO URLString+newAssistantUrl repo = do+ startAssistant repo+ geturl+ where+ geturl = do+ r <- Git.Config.read =<< Git.Construct.fromPath repo+ waiturl $ gitAnnexUrlFile r+ waiturl urlfile = do+ v <- tryIO $ readFile urlfile+ case v of+ Left _ -> delayed $ waiturl urlfile+ Right url -> ifM (listening url)+ ( return url+ , delayed $ waiturl urlfile+ )+ listening url = catchBoolIO $ fst <$> exists url [] Nothing+ delayed a = do+ threadDelay 100000 -- 1/10th of a second+ a++{- Returns once the assistant has daemonized, but possibly before it's+ - listening for web connections. -}+startAssistant :: FilePath -> IO ()+startAssistant repo = do+ program <- readProgramFile+ (_, _, _, pid) <- + createProcess $+ (proc program ["assistant"]) { cwd = Just repo }+ void $ checkSuccessProcess pid
Assistant/Threads/NetWatcher.hs view
@@ -15,6 +15,7 @@ import Utility.ThreadScheduler import qualified Types.Remote as Remote import Assistant.DaemonStatus+import Utility.NotificationBroadcaster #if WITH_DBUS import Utility.DBus@@ -127,7 +128,9 @@ #endif handleConnection :: Assistant ()-handleConnection = reconnectRemotes True =<< networkRemotes+handleConnection = do+ liftIO . sendNotification . networkConnectedNotifier =<< getDaemonStatus+ reconnectRemotes True =<< networkRemotes {- Network remotes to sync with. -} networkRemotes :: Assistant [Remote]
Assistant/Threads/TransferWatcher.hs view
@@ -16,6 +16,7 @@ import qualified Remote import Control.Concurrent+import qualified Data.Map as M {- This thread watches for changes to the gitAnnexTransferDir, - and updates the DaemonStatus's map of ongoing transfers. -}@@ -88,6 +89,11 @@ Just t -> do debug [ "transfer finishing:", show t] minfo <- removeTransfer t++ -- Run transfer hook.+ m <- transferHook <$> getDaemonStatus+ maybe noop (\hook -> void $ liftIO $ forkIO $ hook t)+ (M.lookup (transferKey t) m) finished <- asIO2 finishedTransfer void $ liftIO $ forkIO $ do
+ Assistant/Threads/UpgradeWatcher.hs view
@@ -0,0 +1,109 @@+{- git-annex assistant thread to detect when git-annex is upgraded+ -+ - Copyright 2013 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++{-# LANGUAGE CPP #-}++module Assistant.Threads.UpgradeWatcher (+ upgradeWatcherThread+) where++import Assistant.Common+import Assistant.Upgrade+import Utility.DirWatcher+import Utility.DirWatcher.Types+import Utility.ThreadScheduler+import Assistant.Types.UrlRenderer+import Assistant.Alert+import Assistant.DaemonStatus+#ifdef WITH_WEBAPP+import Assistant.WebApp.Types+import qualified Build.SysConfig+#endif++import Control.Concurrent.MVar+import qualified Data.Text as T++data WatcherState = InStartupScan | Started | Upgrading+ deriving (Eq)++upgradeWatcherThread :: UrlRenderer -> NamedThread+upgradeWatcherThread urlrenderer = namedThread "UpgradeWatcher" $ do+ whenM (liftIO checkSuccessfulUpgrade) $+ showSuccessfulUpgrade urlrenderer+ go =<< liftIO upgradeFlagFile+ where+ go Nothing = debug [ "cannot determine program path" ]+ go (Just flagfile) = do+ mvar <- liftIO $ newMVar InStartupScan+ changed <- Just <$> asIO2 (changedFile urlrenderer mvar flagfile)+ let hooks = mkWatchHooks+ { addHook = changed+ , delHook = changed+ , addSymlinkHook = changed+ , modifyHook = changed+ , delDirHook = changed+ }+ let dir = parentDir flagfile+ let depth = length (splitPath dir) + 1+ let nosubdirs f = length (splitPath f) == depth+ void $ liftIO $ watchDir dir nosubdirs hooks (startup mvar)+ -- Ignore bogus events generated during the startup scan.+ startup mvar scanner = do+ r <- scanner+ void $ swapMVar mvar Started+ return r++changedFile :: UrlRenderer -> MVar WatcherState -> FilePath -> FilePath -> Maybe FileStatus -> Assistant ()+changedFile urlrenderer mvar flagfile file _status+ | flagfile /= file = noop+ | otherwise = do+ state <- liftIO $ readMVar mvar+ when (state == Started) $ do+ setstate Upgrading+ ifM (liftIO upgradeSanityCheck)+ ( handleUpgrade urlrenderer+ , do+ debug ["new version failed sanity check; not using"]+ setstate Started+ )+ where+ setstate = void . liftIO . swapMVar mvar++handleUpgrade :: UrlRenderer -> Assistant ()+handleUpgrade urlrenderer = do+ -- Wait 2 minutes for any final upgrade changes to settle.+ -- (For example, other associated files may be being put into+ -- place.) Not needed when using a distribution bundle, because+ -- in that case git-annex handles the upgrade in a non-racy way.+ liftIO $ unlessM usingDistribution $+ threadDelaySeconds (Seconds 120)+ ifM autoUpgradeEnabled+ ( do+ debug ["starting automatic upgrade"]+ unattendedUpgrade+#ifdef WITH_WEBAPP+ , do+ button <- mkAlertButton True (T.pack "Finish Upgrade") urlrenderer ConfigFinishUpgradeR+ void $ addAlert $ upgradeReadyAlert button+#else+ , noop+#endif+ )++showSuccessfulUpgrade :: UrlRenderer -> Assistant ()+showSuccessfulUpgrade urlrenderer = do+#ifdef WITH_WEBAPP+ button <- ifM autoUpgradeEnabled + ( pure Nothing+ , Just <$> mkAlertButton True+ (T.pack "Enable Automatic Upgrades")+ urlrenderer ConfigEnableAutomaticUpgradeR+ )+ void $ addAlert $ upgradeFinishedAlert button Build.SysConfig.packageversion+#else+ noop+#endif
+ Assistant/Threads/Upgrader.hs view
@@ -0,0 +1,101 @@+{- git-annex assistant thread to detect when upgrade is available+ -+ - Copyright 2013 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++{-# LANGUAGE CPP #-}++module Assistant.Threads.Upgrader (+ upgraderThread+) where++import Assistant.Common+import Assistant.Upgrade++import Assistant.Types.UrlRenderer+import Assistant.DaemonStatus+import Assistant.Alert+import Utility.NotificationBroadcaster+import Utility.Tmp+import qualified Annex+import qualified Build.SysConfig+import qualified Utility.Url as Url+import qualified Annex.Url as Url+import qualified Git.Version+import Types.Distribution+#ifdef WITH_WEBAPP+import Assistant.WebApp.Types+#endif++import Data.Time.Clock+import qualified Data.Text as T++upgraderThread :: UrlRenderer -> NamedThread+upgraderThread urlrenderer = namedThread "Upgrader" $+ when (isJust Build.SysConfig.upgradelocation) $ do+ {- Check for upgrade on startup, unless it was just+ - upgraded. -}+ unlessM (liftIO checkSuccessfulUpgrade) $+ checkUpgrade urlrenderer+ h <- liftIO . newNotificationHandle False . networkConnectedNotifier =<< getDaemonStatus+ go h =<< liftIO getCurrentTime+ where+ {- Wait for a network connection event. Then see if it's been+ - half a day since the last upgrade check. If so, proceed with+ - check. -}+ go h lastchecked = do+ liftIO $ waitNotification h+ autoupgrade <- liftAnnex $ annexAutoUpgrade <$> Annex.getGitConfig+ if autoupgrade == NoAutoUpgrade+ then go h lastchecked+ else do+ now <- liftIO getCurrentTime+ if diffUTCTime now lastchecked > halfday+ then do+ checkUpgrade urlrenderer+ go h =<< liftIO getCurrentTime+ else go h lastchecked+ halfday = 12 * 60 * 60++checkUpgrade :: UrlRenderer -> Assistant ()+checkUpgrade urlrenderer = do+ debug [ "Checking if an upgrade is available." ]+ go =<< getDistributionInfo+ where+ go Nothing = debug [ "Failed to check if upgrade is available." ]+ go (Just d) = do+ let installed = Git.Version.normalize Build.SysConfig.packageversion+ let avail = Git.Version.normalize $ distributionVersion d+ let old = Git.Version.normalize <$> distributionUrgentUpgrade d+ if Just installed <= old+ then canUpgrade High urlrenderer d+ else if installed < avail+ then canUpgrade Low urlrenderer d+ else debug [ "No new version found." ]++canUpgrade :: AlertPriority -> UrlRenderer -> GitAnnexDistribution -> Assistant ()+canUpgrade urgency urlrenderer d = ifM autoUpgradeEnabled+ ( startDistributionDownload d+ , do+#ifdef WITH_WEBAPP+ button <- mkAlertButton True (T.pack "Upgrade") urlrenderer (ConfigStartUpgradeR d)+ void $ addAlert (canUpgradeAlert urgency (distributionVersion d) button)+#else+ noop+#endif+ )++getDistributionInfo :: Assistant (Maybe GitAnnexDistribution)+getDistributionInfo = do+ ua <- liftAnnex Url.getUserAgent+ liftIO $ withTmpFile "git-annex.tmp" $ \tmpfile h -> do+ hClose h+ ifM (Url.downloadQuiet distributionInfoUrl [] [] tmpfile ua)+ ( readish <$> readFileStrict tmpfile+ , return Nothing+ )++distributionInfoUrl :: String+distributionInfoUrl = fromJust Build.SysConfig.upgradelocation ++ ".info"
Assistant/Threads/WebApp.hs view
@@ -30,6 +30,7 @@ import Assistant.WebApp.Configurators.Edit import Assistant.WebApp.Configurators.Delete import Assistant.WebApp.Configurators.Fsck+import Assistant.WebApp.Configurators.Upgrade import Assistant.WebApp.Documentation import Assistant.WebApp.Control import Assistant.WebApp.OtherRepos
Assistant/Types/Alert.hs view
@@ -31,6 +31,7 @@ | CloudRepoNeededAlert | SyncAlert | NotFsckedAlert+ | UpgradeAlert deriving (Eq) {- The first alert is the new alert, the second is an old alert.@@ -49,10 +50,10 @@ , alertIcon :: Maybe AlertIcon , alertCombiner :: Maybe AlertCombiner , alertName :: Maybe AlertName- , alertButton :: Maybe AlertButton+ , alertButtons :: [AlertButton] } -data AlertIcon = ActivityIcon | SyncIcon | SuccessIcon | ErrorIcon | InfoIcon | TheCloud+data AlertIcon = ActivityIcon | SyncIcon | SuccessIcon | ErrorIcon | InfoIcon | UpgradeIcon | TheCloud type AlertMap = M.Map AlertId Alert @@ -73,4 +74,5 @@ { buttonLabel :: Text , buttonUrl :: Text , buttonAction :: Maybe (AlertId -> IO ())+ , buttonPrimary :: Bool }
Assistant/Types/DaemonStatus.hs view
@@ -14,6 +14,7 @@ import Assistant.Types.ThreadName import Assistant.Types.NetMessager import Assistant.Types.Alert+import Utility.Url import Control.Concurrent.STM import Control.Concurrent.MVar@@ -55,18 +56,25 @@ , desynced :: S.Set UUID -- Pairing request that is in progress. , pairingInProgress :: Maybe PairingInProgress- -- Broadcasts notifications about all changes to the DaemonStatus+ -- Broadcasts notifications about all changes to the DaemonStatus. , changeNotifier :: NotificationBroadcaster -- Broadcasts notifications when queued or current transfers change. , transferNotifier :: NotificationBroadcaster- -- Broadcasts notifications when there's a change to the alerts+ -- Broadcasts notifications when there's a change to the alerts. , alertNotifier :: NotificationBroadcaster- -- Broadcasts notifications when the syncRemotes change+ -- Broadcasts notifications when the syncRemotes change. , syncRemotesNotifier :: NotificationBroadcaster- -- Broadcasts notifications when the scheduleLog changes+ -- Broadcasts notifications when the scheduleLog changes. , scheduleLogNotifier :: NotificationBroadcaster -- Broadcasts a notification once the startup sanity check has run. , startupSanityCheckNotifier :: NotificationBroadcaster+ -- Broadcasts notifications when the network is connected.+ , networkConnectedNotifier :: NotificationBroadcaster+ -- Broadcasts notifications when a global redirect is needed.+ , globalRedirNotifier :: NotificationBroadcaster+ , globalRedirUrl :: Maybe URLString+ -- Actions to run after a Key is transferred.+ , transferHook :: M.Map Key (Transfer -> IO ()) -- When the XMPP client is connected, this will contain the XMPP -- address. , xmppClientID :: Maybe ClientID@@ -103,5 +111,9 @@ <*> newNotificationBroadcaster <*> newNotificationBroadcaster <*> newNotificationBroadcaster+ <*> newNotificationBroadcaster+ <*> newNotificationBroadcaster+ <*> pure Nothing+ <*> pure M.empty <*> pure Nothing <*> pure M.empty
+ Assistant/Upgrade.hs view
@@ -0,0 +1,316 @@+{- git-annex assistant upgrading+ -+ - Copyright 2013 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU AGPL version 3 or higher.+ -}++{-# LANGUAGE CPP #-}++module Assistant.Upgrade where++import Assistant.Common+import Assistant.Restart+import qualified Annex+import Assistant.Alert+import Assistant.DaemonStatus+import Utility.Env+import Types.Distribution+import Logs.Transfer+import Logs.Web+import Logs.Presence+import Logs.Location+import Annex.Content+import qualified Backend+import qualified Types.Backend+import qualified Types.Key+import Assistant.TransferQueue+import Assistant.TransferSlots+import Remote (remoteFromUUID)+import Annex.Path+import Config.Files+import Utility.ThreadScheduler+import Utility.Tmp+import Utility.UserInfo+import qualified Utility.Lsof as Lsof++import qualified Data.Map as M+import Data.Tuple.Utils++{- Upgrade without interaction in the webapp. -}+unattendedUpgrade :: Assistant ()+unattendedUpgrade = do+ prepUpgrade+ url <- runRestart+ postUpgrade url++prepUpgrade :: Assistant ()+prepUpgrade = do+ void $ addAlert upgradingAlert+ void $ liftIO $ setEnv upgradedEnv "1" True+ prepRestart++postUpgrade :: URLString -> Assistant ()+postUpgrade = postRestart++autoUpgradeEnabled :: Assistant Bool+autoUpgradeEnabled = liftAnnex $ (==) AutoUpgrade . annexAutoUpgrade <$> Annex.getGitConfig++checkSuccessfulUpgrade :: IO Bool+checkSuccessfulUpgrade = isJust <$> getEnv upgradedEnv++upgradedEnv :: String+upgradedEnv = "GIT_ANNEX_UPGRADED"++{- Start downloading the distribution key from the web.+ - Install a hook that will be run once the download is complete,+ - and finishes the upgrade.+ -+ - Creates the destination directory where the upgrade will be installed+ - early, in order to check if another upgrade has happened (or is+ - happending). On failure, the directory is removed.+ -}+startDistributionDownload :: GitAnnexDistribution -> Assistant ()+startDistributionDownload d = go =<< liftIO . newVersionLocation d =<< liftIO oldVersionLocation+ where+ go Nothing = debug ["Skipping redundant upgrade"]+ go (Just dest) = do+ liftAnnex $ setUrlPresent k u+ hook <- asIO1 $ distributionDownloadComplete d dest cleanup+ modifyDaemonStatus_ $ \s -> s+ { transferHook = M.insert k hook (transferHook s) }+ maybe noop (queueTransfer "upgrade" Next (Just f) t)+ =<< liftAnnex (remoteFromUUID webUUID)+ startTransfer t+ k = distributionKey d+ u = distributionUrl d+ f = takeFileName u ++ " (for upgrade)"+ t = Transfer+ { transferDirection = Download+ , transferUUID = webUUID+ , transferKey = k+ }+ cleanup = liftAnnex $ do+ removeAnnex k+ setUrlMissing k u+ logStatus k InfoMissing++{- Called once the download is done.+ - Passed an action that can be used to clean up the downloaded file.+ -+ - Fsck the key to verify the download.+ -}+distributionDownloadComplete :: GitAnnexDistribution -> FilePath -> Assistant () -> Transfer -> Assistant ()+distributionDownloadComplete d dest cleanup t + | transferDirection t == Download = do+ debug ["finished downloading git-annex distribution"]+ maybe (failedupgrade "bad download") go+ =<< liftAnnex (withObjectLoc k fsckit (getM fsckit))+ | otherwise = cleanup+ where+ k = distributionKey d+ fsckit f = case Backend.maybeLookupBackendName (Types.Key.keyBackendName k) of+ Nothing -> return $ Just f+ Just b -> case Types.Backend.fsckKey b of+ Nothing -> return $ Just f+ Just a -> ifM (a k f)+ ( return $ Just f+ , return Nothing+ )+ go f = do+ ua <- asIO $ upgradeToDistribution dest cleanup f+ fa <- asIO1 failedupgrade+ liftIO $ ua `catchNonAsync` (fa . show)+ failedupgrade msg = do+ void $ addAlert $ upgradeFailedAlert msg+ cleanup+ liftIO $ void $ tryIO $ removeDirectoryRecursive dest++{- The upgrade method varies by OS.+ -+ - In general, find where the distribution was installed before,+ - and unpack the new distribution next to it (in a versioned directory).+ - Then update the programFile to point to the new version.+ -}+upgradeToDistribution :: FilePath -> Assistant () -> FilePath -> Assistant ()+upgradeToDistribution newdir cleanup distributionfile = do+ liftIO $ createDirectoryIfMissing True newdir+ (program, deleteold) <- unpack+ changeprogram program+ cleanup+ prepUpgrade+ url <- runRestart+ {- At this point, the new assistant is fully running, so+ - it's safe to delete the old version. -}+ liftIO $ void $ tryIO deleteold+ postUpgrade url+ where+ changeprogram program = liftIO $ do+ unlessM (boolSystem program [Param "version"]) $+ error "New git-annex program failed to run! Not using."+ pf <- programFile+ liftIO $ writeFile pf program+ +#ifdef darwin_HOST_OS+ {- OS X uses a dmg, so mount it, and copy the contents into place. -}+ unpack = liftIO $ do+ olddir <- oldVersionLocation+ withTmpDirIn (parentDir newdir) "git-annex.upgrade" $ \tmpdir -> do+ void $ boolSystem "hdiutil"+ [ Param "attach", File distributionfile+ , Param "-mountpoint", File tmpdir+ ]+ void $ boolSystem "cp"+ [ Param "-R"+ , File $ tmpdir </> installBase </> "Contents"+ , File $ newdir+ ]+ void $ boolSystem "hdiutil"+ [ Param "eject"+ , File tmpdir+ ]+ sanitycheck newdir+ let deleteold = do+ deleteFromManifest $ olddir </> "Contents" </> "MacOS"+ makeorigsymlink olddir+ return (newdir </> "Contents" </> "MacOS" </> "git-annex", deleteold)+#else+ {- Linux uses a tarball (so could other POSIX systems), so+ - untar it (into a temp directory) and move the directory+ - into place. -}+ unpack = liftIO $ do+ olddir <- oldVersionLocation+ withTmpDirIn (parentDir newdir) "git-annex.upgrade" $ \tmpdir -> do+ let tarball = tmpdir </> "tar"+ -- Cannot rely on filename extension, and this also+ -- avoids problems if tar doesn't support transparent+ -- decompression.+ void $ boolSystem "sh"+ [ Param "-c"+ , Param $ "zcat < " ++ shellEscape distributionfile +++ " > " ++ shellEscape tarball+ ]+ tarok <- boolSystem "tar"+ [ Param "xf"+ , Param tarball+ , Param "--directory", File tmpdir+ ]+ unless tarok $+ error $ "failed to untar " ++ distributionfile+ sanitycheck $ tmpdir </> installBase+ installby rename newdir (tmpdir </> installBase)+ let deleteold = do+ deleteFromManifest olddir+ makeorigsymlink olddir+ return (newdir </> "git-annex", deleteold)+ installby a dstdir srcdir =+ mapM_ (\x -> a x (dstdir </> takeFileName x))+ =<< dirContents srcdir+#endif+ sanitycheck dir = + unlessM (doesDirectoryExist dir) $+ error $ "did not find " ++ dir ++ " in " ++ distributionfile+ makeorigsymlink olddir = do+ let origdir = parentDir olddir </> installBase+ nukeFile origdir+ createSymbolicLink newdir origdir++{- Finds where the old version was installed. -}+oldVersionLocation :: IO FilePath+oldVersionLocation = do+#ifdef darwin_HOST_OS+ pdir <- parentDir <$> readProgramFile+ let dirs = splitDirectories pdir+ {- It will probably be deep inside a git-annex.app directory. -}+ let olddir = case findIndex ("git-annex.app" `isPrefixOf`) dirs of+ Nothing -> pdir+ Just i -> joinPath (take (i + 1) dirs)+#else+ olddir <- parentDir <$> readProgramFile+#endif+ when (null olddir) $+ error $ "Cannot find old distribution bundle; not upgrading."+ return olddir++{- Finds a place to install the new version.+ - Generally, put it in the parent directory of where the old version was+ - installed, and use a version number in the directory name.+ - If unable to write to there, instead put it in the home directory.+ -+ - The directory is created. If it already exists, returns Nothing.+ -}+newVersionLocation :: GitAnnexDistribution -> FilePath -> IO (Maybe FilePath)+newVersionLocation d olddir = + trymkdir newloc $ do+ home <- myHomeDir+ trymkdir (home </> s) $+ return Nothing+ where+ s = installBase ++ "." ++ distributionVersion d+ topdir = parentDir olddir+ newloc = topdir </> s+ trymkdir dir fallback =+ (createDirectory dir >> return (Just dir))+ `catchIO` const fallback++installBase :: String+installBase = "git-annex." +++#ifdef linux_HOST_OS+ "linux"+#else+#ifdef darwin_HOST_OS+ "app"+#else+ "dir"+#endif+#endif++deleteFromManifest :: FilePath -> IO ()+deleteFromManifest dir = do+ fs <- map (dir </>) . lines <$> catchDefaultIO "" (readFile manifest)+ mapM_ nukeFile fs+ nukeFile manifest+ removeEmptyRecursive dir+ where+ manifest = dir </> "git-annex.MANIFEST"++removeEmptyRecursive :: FilePath -> IO ()+removeEmptyRecursive dir = do+ print ("remove", dir)+ mapM_ removeEmptyRecursive =<< dirContents dir+ void $ tryIO $ removeDirectory dir++{- This is a file that the UpgradeWatcher can watch for modifications to+ - detect when git-annex has been upgraded.+ -}+upgradeFlagFile :: IO (Maybe FilePath)+upgradeFlagFile = ifM usingDistribution+ ( Just <$> programFile+ , programPath+ )++{- Sanity check to see if an upgrade is complete and the program is ready+ - to be run. -}+upgradeSanityCheck :: IO Bool+upgradeSanityCheck = ifM usingDistribution+ ( doesFileExist =<< programFile+ , do+ -- Ensure that the program is present, and has no writers,+ -- and can be run. This should handle distribution+ -- upgrades, manual upgrades, etc.+ v <- programPath+ case v of+ Nothing -> return False+ Just program -> do+ untilM (doesFileExist program <&&> nowriter program) $+ threadDelaySeconds (Seconds 60)+ boolSystem program [Param "version"]+ )+ where+ nowriter f = null+ . filter (`elem` [Lsof.OpenReadWrite, Lsof.OpenWriteOnly])+ . map snd3+ <$> Lsof.query [f]++usingDistribution :: IO Bool+usingDistribution = isJust <$> getEnv "GIT_ANNEX_STANDLONE_ENV"
Assistant/WebApp/Configurators/Local.hs view
@@ -10,10 +10,10 @@ module Assistant.WebApp.Configurators.Local where import Assistant.WebApp.Common-import Assistant.WebApp.OtherRepos import Assistant.WebApp.Gpg import Assistant.WebApp.MakeRemote import Assistant.Sync+import Assistant.Restart import Init import qualified Git import qualified Git.Construct
Assistant/WebApp/Configurators/Pairing.hs view
@@ -249,6 +249,7 @@ tid <- liftIO myThreadId let selfdestruct = AlertButton { buttonLabel = "Cancel"+ , buttonPrimary = True , buttonUrl = urlrender DashboardR , buttonAction = Just $ const $ do oncancel
Assistant/WebApp/Configurators/Preferences.hs view
@@ -19,6 +19,8 @@ import Config.Files import Utility.DataUnits import Git.Config+import Types.Distribution+import qualified Build.SysConfig import qualified Data.Text as T @@ -26,6 +28,7 @@ { diskReserve :: Text , numCopies :: Int , autoStart :: Bool+ , autoUpgrade :: AutoUpgrade , debugEnabled :: Bool } @@ -37,6 +40,8 @@ "Number of copies" (Just $ numCopies def) <*> areq (checkBoxField `withNote` autostartnote) "Auto start" (Just $ autoStart def)+ <*> areq (selectFieldList autoUpgradeChoices)+ autoUpgradeLabel (Just $ autoUpgrade def) <*> areq (checkBoxField `withNote` debugnote) "Enable debug logging" (Just $ debugEnabled def) where@@ -45,6 +50,16 @@ debugnote = [whamlet|<a href="@{LogR}">View Log</a>|] autostartnote = [whamlet|Start the git-annex assistant at boot or on login.|] + autoUpgradeChoices :: [(Text, AutoUpgrade)]+ autoUpgradeChoices =+ [ ("ask me", AskUpgrade)+ , ("enabled", AutoUpgrade)+ , ("disabled", NoAutoUpgrade)+ ]+ autoUpgradeLabel+ | isJust Build.SysConfig.upgradelocation = "Auto upgrade"+ | otherwise = "Auto restart on upgrade"+ positiveIntField = check isPositive intField where isPositive i@@ -68,12 +83,14 @@ <$> (T.pack . roughSize storageUnits False . annexDiskReserve <$> Annex.getGitConfig) <*> (annexNumCopies <$> Annex.getGitConfig) <*> inAutoStartFile+ <*> (annexAutoUpgrade <$> Annex.getGitConfig) <*> (annexDebug <$> Annex.getGitConfig) storePrefs :: PrefsForm -> Annex () storePrefs p = do setConfig (annexConfig "diskreserve") (T.unpack $ diskReserve p) setConfig (annexConfig "numcopies") (show $ numCopies p)+ setConfig (annexConfig "autoupgrade") (fromAutoUpgrade $ autoUpgrade p) unlessM ((==) <$> pure (autoStart p) <*> inAutoStartFile) $ do here <- fromRepo Git.repoPath liftIO $ if autoStart p
+ Assistant/WebApp/Configurators/Upgrade.hs view
@@ -0,0 +1,48 @@+{- git-annex assistant webapp upgrade UI+ -+ - Copyright 2013 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU AGPL version 3 or higher.+ -}++{-# LANGUAGE CPP, QuasiQuotes, TemplateHaskell, OverloadedStrings #-}++module Assistant.WebApp.Configurators.Upgrade where++import Assistant.WebApp.Common+import Types.Distribution+import Assistant.Upgrade+import Assistant.Restart+import Config++{- On Android, just point the user at the apk file to download.+ - Installation will be handled by selecting the downloaded file.+ -+ - Otherwise, start the upgrade process, which will run fully+ - noninteractively.+ - -}+getConfigStartUpgradeR :: GitAnnexDistribution -> Handler Html+getConfigStartUpgradeR d = do+#ifdef ANDROID_SPLICES+ let url = distributionUrl d+ page "Upgrade" (Just Configuration) $+ $(widgetFile "configurators/upgrade/android")+#else+ liftAssistant $ startDistributionDownload d+ redirect DashboardR+#endif++{- Finish upgrade by starting the new assistant in the same repository this+ - one is running in, and redirecting to it. -}+getConfigFinishUpgradeR :: Handler Html+getConfigFinishUpgradeR = do+ liftAssistant prepUpgrade+ url <- liftAssistant runRestart+ liftAssistant $ postUpgrade url+ redirect url++getConfigEnableAutomaticUpgradeR :: Handler Html+getConfigEnableAutomaticUpgradeR = do+ liftAnnex $ setConfig (annexConfig "autoupgrade")+ (fromAutoUpgrade AutoUpgrade)+ redirect DashboardR
Assistant/WebApp/Configurators/XMPP.hs view
@@ -43,6 +43,7 @@ { buttonLabel = "Configure a Jabber account" , buttonUrl = urlrender XMPPConfigR , buttonAction = Just close+ , buttonPrimary = True } #else xmppNeeded = return ()
Assistant/WebApp/Control.hs view
@@ -1,6 +1,6 @@ {- git-annex assistant webapp control -- - Copyright 2012 Joey Hess <joey@kitenet.net>+ - Copyright 2012, 2013 Joey Hess <joey@kitenet.net> - - Licensed under the GNU AGPL version 3 or higher. -}@@ -10,15 +10,17 @@ module Assistant.WebApp.Control where import Assistant.WebApp.Common-import Config.Files-import Utility.LogFile import Assistant.DaemonStatus import Assistant.Alert import Assistant.TransferSlots+import Assistant.Restart+import Utility.LogFile+import Utility.NotificationBroadcaster import Control.Concurrent import System.Posix (getProcessID, signalProcess, sigTERM) import qualified Data.Map as M+import qualified Data.Text as T getShutdownR :: Handler Html getShutdownR = page "Shutdown" Nothing $@@ -36,27 +38,33 @@ - the transfer processes). -} ts <- M.keys . currentTransfers <$> getDaemonStatus mapM_ pauseTransfer ts- page "Shutdown" Nothing $ do- {- Wait 2 seconds before shutting down, to give the web- - page time to load in the browser. -}- void $ liftIO $ forkIO $ do- threadDelay 2000000- signalProcess sigTERM =<< getProcessID- $(widgetFile "control/shutdownconfirmed")--{- Quite a hack, and doesn't redirect the browser window. -}-getRestartR :: Handler Html-getRestartR = page "Restarting" Nothing $ do+ webapp <- getYesod+ let url = T.unpack $ yesodRender webapp (T.pack "") NotRunningR []+ {- Signal any other web browsers. -}+ liftAssistant $ do+ modifyDaemonStatus_ $ \status -> status { globalRedirUrl = Just url }+ liftIO . sendNotification . globalRedirNotifier =<< getDaemonStatus+ {- Wait 2 seconds before shutting down, to give the web+ - page time to load in the browser. -} void $ liftIO $ forkIO $ do threadDelay 2000000- program <- readProgramFile- unlessM (boolSystem "sh" [Param "-c", Param $ restartcommand program]) $- error "restart failed"- $(widgetFile "control/restarting")- where- restartcommand program = program ++ " assistant --stop; exec " ++- program ++ " webapp"+ signalProcess sigTERM =<< getProcessID+ redirect NotRunningR +{- Use a custom page to avoid putting long polling elements on it that will + - fail and cause the web browser to show an error once the webapp is+ - truely stopped. -}+getNotRunningR :: Handler Html+getNotRunningR = customPage' False Nothing $+ $(widgetFile "control/notrunning")++getRestartR :: Handler Html+getRestartR = do+ liftAssistant prepRestart+ url <- liftAssistant runRestart+ liftAssistant $ postRestart url+ redirect url+ getRestartThreadR :: ThreadName -> Handler () getRestartThreadR name = do m <- liftAssistant $ startedThreads <$> getDaemonStatus@@ -67,9 +75,5 @@ getLogR = page "Logs" Nothing $ do logfile <- liftAnnex $ fromRepo gitAnnexLogFile logs <- liftIO $ listLogs logfile- logcontent <- liftIO $ concat <$> mapM readlog logs+ logcontent <- liftIO $ concat <$> mapM readFileStrictAnyEncoding logs $(widgetFile "control/log")- where- readlog f = withFile f ReadMode $ \h -> do- fileEncoding h -- log may contain invalid utf-8- hClose h `after` hGetContentsStrict h
Assistant/WebApp/Notifications.hs view
@@ -50,7 +50,6 @@ let startdelay = Aeson.String (T.pack (show ms_startdelay)) let ident = Aeson.String tident #endif- addScript $ StaticR longpolling_js $(widgetFile "notifications/longpolling") {- Notifier urls are requested by the javascript, to avoid allocation@@ -82,6 +81,9 @@ where route nid = RepoListR nid reposelector +getNotifierGlobalRedirR :: Handler RepPlain+getNotifierGlobalRedirR = notifierUrl GlobalRedirR getGlobalRedirBroadcaster+ getTransferBroadcaster :: Assistant NotificationBroadcaster getTransferBroadcaster = transferNotifier <$> getDaemonStatus @@ -93,3 +95,12 @@ getRepoListBroadcaster :: Assistant NotificationBroadcaster getRepoListBroadcaster = syncRemotesNotifier <$> getDaemonStatus++getGlobalRedirBroadcaster :: Assistant NotificationBroadcaster+getGlobalRedirBroadcaster = globalRedirNotifier <$> getDaemonStatus++getGlobalRedirR :: NotificationId -> Handler RepPlain+getGlobalRedirR nid = do+ waitNotifier getGlobalRedirBroadcaster nid+ maybe (getGlobalRedirR nid) (return . RepPlain . toContent . T.pack)+ =<< globalRedirUrl <$> liftAssistant getDaemonStatus
Assistant/WebApp/OtherRepos.hs view
@@ -12,14 +12,9 @@ import Assistant.Common import Assistant.WebApp.Types import Assistant.WebApp.Page-import qualified Git.Construct-import qualified Git.Config import Config.Files-import qualified Utility.Url as Url import Utility.Yesod--import Control.Concurrent-import System.Process (cwd)+import Assistant.Restart getRepositorySwitcherR :: Handler Html getRepositorySwitcherR = page "Switch repository" Nothing $ do@@ -35,38 +30,7 @@ names <- mapM relHome gooddirs return $ sort $ zip names gooddirs -{- Starts up the assistant in the repository, and waits for it to create- - a gitAnnexUrlFile. Waits for the assistant to be up and listening for- - connections by testing the url. Once it's running, redirect to it.- -} getSwitchToRepositoryR :: FilePath -> Handler Html getSwitchToRepositoryR repo = do- liftIO $ startAssistant repo liftIO $ addAutoStartFile repo -- make this the new default repo- redirect =<< liftIO geturl- where- geturl = do- r <- Git.Config.read =<< Git.Construct.fromPath repo- waiturl $ gitAnnexUrlFile r- waiturl urlfile = do- v <- tryIO $ readFile urlfile- case v of- Left _ -> delayed $ waiturl urlfile- Right url -> ifM (listening url)- ( return url- , delayed $ waiturl urlfile- )- listening url = catchBoolIO $ fst <$> Url.exists url [] Nothing- delayed a = do- threadDelay 100000 -- 1/10th of a second- a--{- Returns once the assistant has daemonized, but possibly before it's- - listening for web connections. -}-startAssistant :: FilePath -> IO ()-startAssistant repo = do- program <- readProgramFile- (_, _, _, pid) <- - createProcess $- (proc program ["assistant"]) { cwd = Just repo }- void $ checkSuccessProcess pid+ redirect =<< liftIO (newAssistantUrl repo)
Assistant/WebApp/Page.hs view
@@ -50,7 +50,10 @@ {- A custom page, with no title or sidebar set. -} customPage :: Maybe NavBarItem -> Widget -> Handler Html-customPage navbaritem content = do+customPage = customPage' True++customPage' :: Bool -> Maybe NavBarItem -> Widget -> Handler Html+customPage' with_longpolling navbaritem content = do webapp <- getYesod case cannotRun webapp of Nothing -> do@@ -62,6 +65,8 @@ addScript $ StaticR js_bootstrap_dropdown_js addScript $ StaticR js_bootstrap_modal_js addScript $ StaticR js_bootstrap_collapse_js+ when with_longpolling $+ addScript $ StaticR longpolling_js $(widgetFile "page") giveUrlRenderer $(Hamlet.hamletFile $ hamletTemplate "bootstrap") Just msg -> error msg
Assistant/WebApp/SideBar.hs view
@@ -50,6 +50,7 @@ let message = renderAlertMessage alert let messagelines = T.lines message let multiline = length messagelines > 1+ let buttons = zip (alertButtons alert) [1..] $(widgetFile "sidebar/alert") {- Called by client to get a sidebar display.@@ -79,16 +80,20 @@ getCloseAlert = liftAssistant . removeAlert {- When an alert with a button is clicked on, the button takes us here. -}-getClickAlert :: AlertId -> Handler ()-getClickAlert i = do+getClickAlert :: AlertId -> Int -> Handler ()+getClickAlert i bnum = do m <- alertMap <$> liftAssistant getDaemonStatus case M.lookup i m of- Just (Alert { alertButton = Just b }) -> do- {- Spawn a thread to run the action while redirecting. -}- case buttonAction b of- Nothing -> noop- Just a -> liftIO $ void $ forkIO $ a i- redirect $ buttonUrl b+ Just (Alert { alertButtons = bs })+ | length bs >= bnum -> do+ let b = bs !! (bnum - 1)+ {- Spawn a thread to run the action+ - while redirecting. -}+ case buttonAction b of+ Nothing -> noop+ Just a -> liftIO $ void $ forkIO $ a i+ redirect $ buttonUrl b+ | otherwise -> redirectBack _ -> redirectBack htmlIcon :: AlertIcon -> Widget@@ -97,6 +102,7 @@ htmlIcon InfoIcon = bootstrapIcon "info-sign" htmlIcon SuccessIcon = bootstrapIcon "ok" htmlIcon ErrorIcon = bootstrapIcon "exclamation-sign"+htmlIcon UpgradeIcon = bootstrapIcon "arrow-up" -- utf-8 umbrella (utf-8 cloud looks too stormy) htmlIcon TheCloud = [whamlet|☂|]
Assistant/WebApp/Types.hs view
@@ -25,6 +25,7 @@ import Build.SysConfig (packageversion) import Types.ScheduledActivity import Assistant.WebApp.RepoId+import Types.Distribution import Yesod.Static import Text.Hamlet@@ -163,6 +164,10 @@ data RepoKey = RepoKey KeyId | NoRepoKey deriving (Read, Show, Eq, Ord) +instance PathPiece Bool where+ toPathPiece = pack . show+ fromPathPiece = readish . unpack+ instance PathPiece RemovableDrive where toPathPiece = pack . show fromPathPiece = readish . unpack@@ -220,5 +225,9 @@ fromPathPiece = readish . unpack instance PathPiece RepoId where+ toPathPiece = pack . show+ fromPathPiece = readish . unpack++instance PathPiece GitAnnexDistribution where toPathPiece = pack . show fromPathPiece = readish . unpack
Assistant/WebApp/routes view
@@ -9,6 +9,7 @@ /shutdown ShutdownR GET /shutdown/confirm ShutdownConfirmedR GET+/shutdown/complete NotRunningR GET /restart RestartR GET /restart/thread/#ThreadName RestartThreadR GET /log LogR GET@@ -21,6 +22,9 @@ /config/xmpp/needcloudrepo/#UUID NeedCloudRepoR GET /config/fsck ConfigFsckR GET POST /config/fsck/preferences ConfigFsckPreferencesR POST+/config/upgrade/start/#GitAnnexDistribution ConfigStartUpgradeR GET+/config/upgrade/finish ConfigFinishUpgradeR GET+/config/upgrade/automatically ConfigEnableAutomaticUpgradeR GET /config/addrepository AddRepositoryR GET /config/repository/new NewRepositoryR GET POST@@ -100,8 +104,11 @@ /repolist/#NotificationId/#RepoSelector RepoListR GET /notifier/repolist/#RepoSelector NotifierRepoListR GET +/globalredir/#NotificationId GlobalRedirR GET+/notifier/globalredir NotifierGlobalRedirR GET+ /alert/close/#AlertId CloseAlert GET-/alert/click/#AlertId ClickAlert GET+/alert/click/#AlertId/#Int ClickAlert GET /filebrowser FileBrowserR GET POST /transfer/pause/#Transfer PauseTransferR GET POST
Build/BundledPrograms.hs view
@@ -45,6 +45,11 @@ , SysConfig.sha512 , SysConfig.sha224 , SysConfig.sha384+#ifdef linux_HOST_OS+ -- used to unpack the tarball when upgrading+ , Just "gunzip"+ , Just "tar"+#endif -- nice and ionice are not included in the bundle; we rely on the -- system's own version, which may better match its kernel ]
Build/Configure.hs view
@@ -7,7 +7,7 @@ import System.Process import Control.Applicative import System.FilePath-import System.Environment+import System.Environment (getArgs) import Data.Maybe import Control.Monad.IfElse import Data.Char@@ -17,11 +17,13 @@ import Utility.SafeCommand import Utility.Monad import Utility.ExternalSHA+import Utility.Env import qualified Git.Version tests :: [TestCase] tests = [ TestCase "version" getVersion+ , TestCase "UPGRADE_LOCATION" getUpgradeLocation , TestCase "git" $ requireCmd "git" "git --version >/dev/null" , TestCase "git version" getGitVersion , testCp "cp_a" "-a"@@ -33,6 +35,7 @@ , TestCase "wget" $ testCmd "wget" "wget --version >/dev/null" , TestCase "bup" $ testCmd "bup" "bup --version >/dev/null" , TestCase "quvi" $ testCmd "quvi" "quvi --version >/dev/null"+ , TestCase "newquvi" $ testCmd "newquvi" "quvi info >/dev/null" , TestCase "nice" $ testCmd "nice" "nice true >/dev/null" , TestCase "ionice" $ testCmd "ionice" "ionice -c3 true >/dev/null" , TestCase "gpg" $ maybeSelectCmd "gpg"@@ -90,6 +93,11 @@ cmd = "cp " ++ option cmdline = cmd ++ " " ++ testFile ++ " " ++ testFile ++ ".new" +getUpgradeLocation :: Test+getUpgradeLocation = do+ e <- getEnv "UPGRADE_LOCATION"+ return $ Config "upgradelocation" $ MaybeStringConfig e+ getGitVersion :: Test getGitVersion = Config "gitversion" . StringConfig . show <$> Git.Version.installed@@ -130,4 +138,3 @@ ] overridden (Config k _) = k `elem` overridekeys overridekeys = map (\(Config k _) -> k) overrides-
+ Build/DistributionUpdate.hs view
@@ -0,0 +1,64 @@+{- Builds distributon info files for each git-annex release in a directory+ - tree, which must itself be part of a git-annex repository. Only files+ - that are present have their info file created. -}++import Common.Annex+import Types.Distribution+import Build.Version+import Utility.UserInfo+import Utility.Path+import qualified Git.Construct+import qualified Annex+import Annex.Content+import Backend+import Git.Command++import Data.Time.Clock++main = do+ state <- Annex.new =<< Git.Construct.fromPath =<< getRepoDir+ Annex.eval state makeinfos++makeinfos :: Annex ()+makeinfos = do+ basedir <- liftIO getRepoDir+ version <- liftIO getChangelogVersion+ now <- liftIO getCurrentTime+ liftIO $ putStrLn $ "building info files for version " ++ version ++ " in " ++ basedir+ fs <- liftIO $ dirContentsRecursiveSkipping (== "info") (basedir </> "git-annex")+ forM_ fs $ \f -> do+ v <- lookupFile f+ case v of+ Nothing -> noop+ Just (k, _b) -> whenM (inAnnex k) $ do+ liftIO $ putStrLn f+ let infofile = f ++ ".info"+ liftIO $ writeFile infofile $ show $ GitAnnexDistribution+ { distributionUrl = mkUrl basedir f+ , distributionKey = k+ , distributionVersion = version+ , distributionReleasedate = now+ , distributionUrgentUpgrade = Nothing+ }+ void $ inRepo $ runBool [Param "add", Param infofile]+ void $ inRepo $ runBool + [ Param "commit"+ , Param "-m"+ , Param $ "publishing git-annex " ++ version+ ]+ void $ inRepo $ runBool+ [ Param "annex"+ , Params "move --to website"+ ]+ void $ inRepo $ runBool+ [ Param "annex"+ , Params "sync"+ ]++getRepoDir :: IO FilePath+getRepoDir = do+ home <- liftIO myHomeDir+ return $ home </> "lib" </> "downloads"++mkUrl :: FilePath -> FilePath -> String+mkUrl basedir f = "https://downloads.kitenet.net/" ++ relPathDirToFile basedir f
CHANGELOG view
@@ -1,3 +1,30 @@+git-annex (5.20131127) unstable; urgency=low++ * webapp: Detect when upgrades are available, and upgrade if the user+ desires.+ (Only when git-annex is installed using the prebuilt binaries+ from git-annex upstream, not from eg Debian.)+ * assistant: Detect when the git-annex binary is modified or replaced,+ and either prompt the user to restart the program, or automatically+ restart it.+ * annex.autoupgrade configures both the above upgrade behaviors.+ * Added support for quvi 0.9. Slightly suboptimal due to limitations in its+ interface compared with the old version.+ * Bug fix: annex.version did not get set on automatic upgrade to v5 direct+ mode repo, so the upgrade was performed repeatedly, slowing commands down.+ * webapp: Fix bug that broke switching between local repositories+ that use the new guarded direct mode.+ * Android: Fix stripping of the git-annex binary.+ * Android: Make terminal app show git-annex version number.+ * Android: Re-enable XMPP support.+ * reinject: Allow to be used in direct mode.+ * Futher improvements to git repo repair. Has now been tested in tens+ of thousands of intentionally damaged repos, and successfully+ repaired them all.+ * Allow use of --unused in bare repository.++ -- Joey Hess <joeyh@debian.org> Wed, 27 Nov 2013 18:41:44 -0400+ git-annex (5.20131120) unstable; urgency=low * Fix Debian package to not try to run test suite, since haskell-tasty
Command/ImportFeed.hs view
@@ -106,7 +106,7 @@ liftIO $ withTmpFile "feed" $ \f h -> do fileEncoding h ifM (Url.download url [] [] f ua)- ( liftIO $ parseFeedString <$> hGetContentsStrict h+ ( parseFeedString <$> hGetContentsStrict h , return Nothing )
Command/Reinject.hs view
@@ -14,7 +14,7 @@ import qualified Command.Fsck def :: [Command]-def = [notDirect $ command "reinject" (paramPair "SRC" "DEST") seek+def = [command "reinject" (paramPair "SRC" "DEST") seek SectionUtility "sets content of annexed file"] seek :: [CommandSeek]
Command/Upgrade.hs view
@@ -25,8 +25,4 @@ start = do showStart "upgrade" "." r <- upgrade False- ifM isDirect- ( setVersion directModeVersion- , setVersion defaultVersion- ) next $ next $ return r
Git/Config.hs view
@@ -110,8 +110,13 @@ -} updateLocation :: Repo -> IO Repo updateLocation r@(Repo { location = LocalUnknown d })- | isBare r = updateLocation' r $ Local d Nothing- | otherwise = updateLocation' r $ Local (d </> ".git") (Just d)+ | isBare r = ifM (doesDirectoryExist dotgit)+ ( updateLocation' r $ Local dotgit Nothing+ , updateLocation' r $ Local d Nothing+ )+ | otherwise = updateLocation' r $ Local dotgit (Just d)+ where+ dotgit = (d </> ".git") updateLocation r@(Repo { location = l@(Local {}) }) = updateLocation' r l updateLocation r = return r
Git/Fsck.hs view
@@ -17,7 +17,6 @@ import Git import Git.Command import Git.Sha-import Git.CatFile import Utility.Batch import qualified Data.Set as S@@ -40,7 +39,7 @@ findBroken :: Bool -> Repo -> IO FsckResults findBroken batchmode r = do (output, fsckok) <- processTranscript command' (toCommand params') Nothing- let objs = parseFsckOutput output+ let objs = findShas output badobjs <- findMissing objs r if S.null badobjs && not fsckok then return Nothing@@ -57,30 +56,23 @@ {- Finds objects that are missing from the git repsitory, or are corrupt. -- - Note that catting a corrupt object will cause cat-file to crash;- - this is detected and it's restarted.+ - This does not use git cat-file --batch, because catting a corrupt+ - object can cause it to crash, or to report incorrect size information.a -} findMissing :: [Sha] -> Repo -> IO MissingObjects-findMissing objs r = go objs [] =<< start+findMissing objs r = S.fromList <$> filterM (not <$$> present) objs where- start = catFileStart' False r- go [] c h = do- catFileStop h- return $ S.fromList c- go (o:os) c h = do- v <- tryIO $ isNothing <$> catObjectDetails h o- case v of- Left _ -> do- void $ tryIO $ catFileStop h- go os (o:c) =<< start- Right True -> go os (o:c) h- Right False -> go os c h+ present o = either (const False) (const True) <$> tryIO (dump o)+ dump o = runQuiet+ [ Param "show"+ , Param (show o)+ ] r -parseFsckOutput :: String -> [Sha]-parseFsckOutput = catMaybes . map extractSha . concat . map words . lines+findShas :: String -> [Sha]+findShas = catMaybes . map extractSha . concat . map words . lines fsckParams :: Repo -> [CommandParam]-fsckParams = gitCommandLine+fsckParams = gitCommandLine $ [ Param "fsck" , Param "--no-dangling" , Param "--no-reflogs"
Git/Objects.hs view
@@ -9,6 +9,7 @@ import Common import Git+import Git.Sha objectsDir :: Repo -> FilePath objectsDir r = localGitDir r </> "objects"@@ -16,12 +17,17 @@ packDir :: Repo -> FilePath packDir r = objectsDir r </> "pack" +packIdxFile :: FilePath -> FilePath+packIdxFile = flip replaceExtension "idx"+ listPackFiles :: Repo -> IO [FilePath] listPackFiles r = filter (".pack" `isSuffixOf`) <$> catchDefaultIO [] (dirContents $ packDir r) -packIdxFile :: FilePath -> FilePath-packIdxFile = flip replaceExtension "idx"+listLooseObjectShas :: Repo -> IO [Sha]+listLooseObjectShas r = catchDefaultIO [] $+ mapMaybe (extractSha . concat . reverse . take 2 . reverse . splitDirectories)+ <$> dirContentsRecursiveSkipping (== "pack") (objectsDir r) looseObjectFile :: Repo -> Sha -> FilePath looseObjectFile r sha = objectsDir r </> prefix </> rest
Git/Repair.hs view
@@ -36,73 +36,38 @@ import qualified Git.Branch as Branch import Utility.Tmp import Utility.Rsync+import Utility.FileMode import qualified Data.Set as S import qualified Data.ByteString.Lazy as L import Data.Tuple.Utils -{- Given a set of bad objects found by git fsck, removes all- - corrupt objects, and returns a list of missing objects,- - which need to be found elsewhere to finish recovery.- -- - Since git fsck may crash on corrupt objects, and so not- - report the full set of corrupt or missing objects,- - this removes corrupt objects, and re-runs fsck, until it- - stabilizes.- -- - To remove corrupt objects, unpack all packs, and remove the packs- - (to handle corrupt packs), and remove loose object files.+{- Given a set of bad objects found by git fsck, which may not+ - be complete, finds and removes all corrupt objects, and+ - returns a list of missing objects, which need to be+ - found elsewhere to finish recovery. -}-cleanCorruptObjects :: FsckResults -> Repo -> IO MissingObjects-cleanCorruptObjects mmissing r = check mmissing- where- check Nothing = do- putStrLn "git fsck found a problem but no specific broken objects. Perhaps a corrupt pack file?"- ifM (explodePacks r)- ( retry S.empty- , return S.empty- )- check (Just bad)- | S.null bad = return S.empty- | otherwise = do- putStrLn $ unwords - [ "git fsck found"- , show (S.size bad)- , "broken objects."- ]- exploded <- explodePacks r- removed <- removeLoose r bad- if exploded || removed- then retry bad- else return bad- retry oldbad = do- putStrLn "Re-running git fsck to see if it finds more problems."- v <- findBroken False r- case v of- Nothing -> do- hPutStrLn stderr $ unwords- [ "git fsck found a problem, which was not corrected after removing"- , show (S.size oldbad)- , "corrupt objects."- ]- return S.empty- Just newbad -> do- removed <- removeLoose r newbad- let s = S.union oldbad newbad- if not removed || s == oldbad- then return s- else retry s+cleanCorruptObjects :: FsckResults -> Repo -> IO (Maybe MissingObjects)+cleanCorruptObjects fsckresults r = do+ void $ explodePacks r+ objs <- listLooseObjectShas r+ bad <- findMissing objs r+ void $ removeLoose r $ S.union bad (fromMaybe S.empty fsckresults)+ -- Rather than returning the loose objects that were removed, re-run+ -- fsck. Other missing objects may have been in the packs,+ -- and this way fsck will find them.+ findBroken False r removeLoose :: Repo -> MissingObjects -> IO Bool removeLoose r s = do- let fs = map (looseObjectFile r) (S.toList s)- count <- length <$> filterM doesFileExist fs- if (count > 0)+ fs <- filterM doesFileExist (map (looseObjectFile r) (S.toList s))+ let count = length fs+ if count > 0 then do putStrLn $ unwords- [ "removing"+ [ "Removing" , show count- , "corrupt loose objects"+ , "corrupt loose objects." ] mapM_ nukeFile fs return True@@ -118,57 +83,62 @@ mapM_ go packs return True where- go packfile = do+ go packfile = withTmpFileIn (localGitDir r) "pack" $ \tmp _ -> do+ moveFile packfile tmp+ nukeFile $ packIdxFile packfile+ allowRead tmp -- May fail, if pack file is corrupt. void $ tryIO $- pipeWrite [Param "unpack-objects"] r $ \h ->- L.hPut h =<< L.readFile packfile- nukeFile packfile- nukeFile $ packIdxFile packfile+ pipeWrite [Param "unpack-objects", Param "-r"] r $ \h ->+ L.hPut h =<< L.readFile tmp {- Try to retrieve a set of missing objects, from the remotes of a - repository. Returns any that could not be retreived.- - + - - If another clone of the repository exists locally, which might not be a - remote of the repo being repaired, its path can be passed as a reference - repository.+ + - Can also be run with Nothing, if it's not known which objects are+ - missing, just that some are. (Ie, fsck failed badly.) -}-retrieveMissingObjects :: MissingObjects -> Maybe FilePath -> Repo -> IO MissingObjects+retrieveMissingObjects :: Maybe MissingObjects -> Maybe FilePath -> Repo -> IO (Maybe MissingObjects) retrieveMissingObjects missing referencerepo r- | S.null missing = return missing+ | missing == Just S.empty = return $ Just S.empty | otherwise = withTmpDir "tmprepo" $ \tmpdir -> do unlessM (boolSystem "git" [Params "init", File tmpdir]) $ error $ "failed to create temp repository in " ++ tmpdir tmpr <- Config.read =<< Construct.fromAbsPath tmpdir stillmissing <- pullremotes tmpr (remotes r) fetchrefstags missing- if S.null stillmissing- then return stillmissing+ if stillmissing == Just S.empty+ then return $ Just S.empty else pullremotes tmpr (remotes r) fetchallrefs stillmissing where pullremotes tmpr [] fetchrefs stillmissing = case referencerepo of Nothing -> return stillmissing Just p -> ifM (fetchfrom p fetchrefs tmpr) ( do+ void $ explodePacks tmpr void $ copyObjects tmpr r- findMissing (S.toList stillmissing) r+ case stillmissing of+ Nothing -> return $ Just S.empty+ Just s -> Just <$> findMissing (S.toList s) r , return stillmissing )- pullremotes tmpr (rmt:rmts) fetchrefs s- | S.null s = return s+ pullremotes tmpr (rmt:rmts) fetchrefs ms+ | ms == Just S.empty = return $ Just S.empty | otherwise = do- putStrLn $ "Trying to recover missing objects from remote " ++ repoDescribe rmt+ putStrLn $ "Trying to recover missing objects from remote " ++ repoDescribe rmt ++ "." ifM (fetchfrom (repoLocation rmt) fetchrefs tmpr) ( do+ void $ explodePacks tmpr void $ copyObjects tmpr r- stillmissing <- findMissing (S.toList s) r- pullremotes tmpr rmts fetchrefs stillmissing- , do- putStrLn $ unwords- [ "failed to fetch from remote"- , repoDescribe rmt- , "(will continue without it, but making this remote available may improve recovery)"- ]- pullremotes tmpr rmts fetchrefs s+ case ms of+ Nothing -> pullremotes tmpr rmts fetchrefs ms+ Just s -> do+ stillmissing <- findMissing (S.toList s) r+ pullremotes tmpr rmts fetchrefs (Just stillmissing)+ , pullremotes tmpr rmts fetchrefs ms ) fetchfrom fetchurl ps = runBool $ [ Param "fetch"@@ -182,7 +152,7 @@ fetchallrefs = [ Param "+*:*" ] {- Copies all objects from the src repository to the dest repository.- - This is done using rsync, so it copies all missing object, and all+ - This is done using rsync, so it copies all missing objects, and all - objects they rely on. -} copyObjects :: Repo -> Repo -> IO Bool copyObjects srcr destr = rsync@@ -241,51 +211,44 @@ {- Gets all refs, including ones that are corrupt. - git show-ref does not output refs to commits that are directly - corrupted, so it is not used.+ -+ - Relies on packed refs being exploded before it's called. -} getAllRefs :: Repo -> IO [Ref]-getAllRefs r = do- packedrs <- mapMaybe parsePacked . lines- <$> catchDefaultIO "" (readFile $ packedRefsFile r)- loosers <- map toref <$> dirContentsRecursive refdir- return $ packedrs ++ loosers+getAllRefs r = map toref <$> dirContentsRecursive refdir where refdir = localGitDir r </> "refs" toref = Ref . relPathDirToFile (localGitDir r) +explodePackedRefsFile :: Repo -> IO ()+explodePackedRefsFile r = do+ let f = packedRefsFile r+ whenM (doesFileExist f) $ do+ rs <- mapMaybe parsePacked . lines+ <$> catchDefaultIO "" (safeReadFile f)+ forM_ rs makeref+ nukeFile f+ where+ makeref (sha, ref) = do+ let dest = localGitDir r ++ show ref+ createDirectoryIfMissing True (parentDir dest)+ unlessM (doesFileExist dest) $+ writeFile dest (show sha)+ packedRefsFile :: Repo -> FilePath packedRefsFile r = localGitDir r </> "packed-refs" -parsePacked :: String -> Maybe Ref+parsePacked :: String -> Maybe (Sha, Ref) parsePacked l = case words l of (sha:ref:[])- | isJust (extractSha sha) -> Just $ Ref ref+ | isJust (extractSha sha) && Ref.legal True ref ->+ Just (Ref sha, Ref ref) _ -> Nothing {- git-branch -d cannot be used to remove a branch that is directly- - pointing to a corrupt commit. However, it's tried first. -}+ - pointing to a corrupt commit. -} nukeBranchRef :: Branch -> Repo -> IO ()-nukeBranchRef b r = void $ usegit <||> byhand- where- usegit = runBool- [ Param "branch"- , Params "-r -d"- , Param $ show $ Ref.base b- ] r- byhand = do- nukeFile $ localGitDir r </> show b- whenM (doesFileExist packedrefs) $- withTmpFile "packed-refs" $ \tmp h -> do- ls <- lines <$> readFile packedrefs- hPutStr h $ unlines $- filter (not . skiprefline) ls- hClose h- renameFile tmp packedrefs- return True- skiprefline l = case parsePacked l of- Just packedref- | packedref == b -> True- _ -> False- packedrefs = packedRefsFile r+nukeBranchRef b r = nukeFile $ localGitDir r </> show b {- Finds the most recent commit to a branch that does not need any - of the missing objects. If the input branch is good as-is, returns it.@@ -444,51 +407,88 @@ | numitems > 10 = take 10 items ++ ["(and " ++ show (numitems - 10) ++ " more)"] | otherwise = items +{- Fix problems that would prevent repair from working at all+ -+ - A missing or corrupt .git/HEAD makes git not treat the repository as a+ - git repo. If there is a git repo in a parent directory, it may move up+ - the tree and use that one instead. So, cannot use `git show-ref HEAD` to+ - test it.+ -+ - Explode the packed refs file, to simplify dealing with refs, and because+ - fsck can complain about bad refs in it.+ -}+preRepair :: Repo -> IO ()+preRepair g = do+ unlessM (validhead <$> catchDefaultIO "" (safeReadFile headfile)) $ do+ nukeFile headfile+ writeFile headfile "ref: refs/heads/master"+ explodePackedRefsFile g+ where+ headfile = localGitDir g </> "HEAD"+ validhead s = "ref: refs/" `isPrefixOf` s || isJust (extractSha s)+ {- Put it all together. -} runRepair :: Bool -> Repo -> IO (Bool, MissingObjects, [Branch]) runRepair forced g = do+ preRepair g putStrLn "Running git fsck ..." fsckresult <- findBroken False g if foundBroken fsckresult- then runRepairOf fsckresult forced Nothing g+ then runRepair' fsckresult forced Nothing g else do putStrLn "No problems found." return (True, S.empty, []) -successfulRepair :: (Bool, MissingObjects, [Branch]) -> Bool-successfulRepair = fst3- runRepairOf :: FsckResults -> Bool -> Maybe FilePath -> Repo -> IO (Bool, MissingObjects, [Branch]) runRepairOf fsckresult forced referencerepo g = do+ preRepair g+ runRepair' fsckresult forced referencerepo g++runRepair' :: FsckResults -> Bool -> Maybe FilePath -> Repo -> IO (Bool, MissingObjects, [Branch])+runRepair' fsckresult forced referencerepo g = do missing <- cleanCorruptObjects fsckresult g stillmissing <- retrieveMissingObjects missing referencerepo g- if S.null stillmissing- then if repoIsLocalBare g- then successfulfinish stillmissing []- else ifM (checkIndex stillmissing g)- ( successfulfinish stillmissing []- , do- putStrLn "No missing objects found, but the index file is corrupt!"- if forced- then corruptedindex- else needforce stillmissing- ) - else do- putStrLn $ unwords- [ show (S.size stillmissing)- , "missing objects could not be recovered!"- ]- if forced- then continuerepairs stillmissing- else unsuccessfulfinish stillmissing+ case stillmissing of+ Just s+ | S.null s -> if repoIsLocalBare g+ then successfulfinish S.empty []+ else ifM (checkIndex S.empty g)+ ( successfulfinish s []+ , do+ putStrLn "No missing objects found, but the index file is corrupt!"+ if forced+ then corruptedindex+ else needforce S.empty+ )+ | otherwise -> if forced+ then ifM (checkIndex s g)+ ( continuerepairs s+ , corruptedindex+ )+ else do+ putStrLn $ unwords+ [ show (S.size s)+ , "missing objects could not be recovered!"+ ]+ unsuccessfulfinish s+ Nothing+ | forced -> ifM (pure (repoIsLocalBare g) <||> checkIndex S.empty g)+ ( do+ missing' <- cleanCorruptObjects Nothing g+ case missing' of+ Nothing -> return (False, S.empty, [])+ Just stillmissing' -> continuerepairs stillmissing'+ , corruptedindex+ )+ | otherwise -> unsuccessfulfinish S.empty where continuerepairs stillmissing = do (remotebranches, goodcommits) <- removeTrackingBranches stillmissing emptyGoodCommits g unless (null remotebranches) $ putStrLn $ unwords- [ "removed"+ [ "Removed" , show (length remotebranches)- , "remote tracking branches that referred to missing objects"+ , "remote tracking branches that referred to missing objects." ] (resetbranches, deletedbranches, _) <- resetLocalBranches stillmissing goodcommits g displayList (map show resetbranches)@@ -528,8 +528,7 @@ successfulfinish stillmissing modifiedbranches = do mapM_ putStrLn [ "Successfully recovered repository!"- , "You should run \"git fsck\" to make sure, but it looks like"- , "everything was recovered ok."+ , "You should run \"git fsck\" to make sure, but it looks like everything was recovered ok." ] return (True, stillmissing, modifiedbranches) unsuccessfulfinish stillmissing = do@@ -542,3 +541,11 @@ needforce stillmissing = do putStrLn "To force a recovery to a usable state, retry with the --force parameter." return (False, stillmissing, [])++successfulRepair :: (Bool, MissingObjects, [Branch]) -> Bool+successfulRepair = fst3++safeReadFile :: FilePath -> IO String+safeReadFile f = do+ allowRead f+ readFileStrictAnyEncoding f
Makefile view
@@ -77,7 +77,7 @@ rm -rf tmp dist git-annex $(mans) configure *.tix .hpc \ doc/.ikiwiki html dist tags Build/SysConfig.hs build-stamp \ Setup Build/InstallDesktopFile Build/EvilSplicer \- Build/Standalone Build/OSXMkLibs \+ Build/Standalone Build/OSXMkLibs Build/DistributionUpdate \ git-union-merge find . -name \*.o -exec rm {} \; find . -name \*.hi -exec rm {} \;@@ -133,6 +133,8 @@ sort "$(LINUXSTANDALONE_DEST)/libdirs.tmp" | uniq > "$(LINUXSTANDALONE_DEST)/libdirs" rm -f "$(LINUXSTANDALONE_DEST)/libdirs.tmp" + cd tmp/git-annex.linux && find . -type f > git-annex.MANIFEST+ cd tmp/git-annex.linux && find . -type l >> git-annex.MANIFEST cd tmp && tar czf git-annex-standalone-$(shell dpkg --print-architecture).tar.gz git-annex.linux OSXAPP_DEST=tmp/build-dmg/git-annex.app@@ -157,19 +159,18 @@ install -d "$(OSXAPP_BASE)/templates" ./Build/OSXMkLibs $(OSXAPP_BASE)+ cd $(OSXAPP_DEST) && find . -type f > Contents/MacOS/git-annex.MANIFEST+ cd $(OSXAPP_DEST) && find . -type l >> Contents/MacOS/git-annex.MANIFEST rm -f tmp/git-annex.dmg hdiutil create -format UDBZ -srcfolder tmp/build-dmg \ -volname git-annex -o tmp/git-annex.dmg- # temporarily still create compressed image too- rm -f tmp/git-annex.dmg.bz2- bzip2 --fast < tmp/git-annex.dmg > tmp/git-annex.dmg.bz2 -ANDROID_FLAGS?=-f-XMPP+ANDROID_FLAGS?= # Cross compile for Android. # Uses https://github.com/neurocyte/ghc-android android: Build/EvilSplicer echo "Running native build, to get TH splices.."- if [ ! -e dist/setup/setup ]; then $(CABAL) configure -f-Production -O0 $(ANDROID_FLAGS); fi+ if [ ! -e dist/setup/setup ]; then $(CABAL) configure -f-Production -O0 $(ANDROID_FLAGS) -fAndroidSplice; fi mkdir -p tmp if ! $(CABAL) build --ghc-options=-ddump-splices 2> tmp/dump-splices; then tail tmp/dump-splices >&2; exit 1; fi echo "Setting up Android build tree.."@@ -188,7 +189,7 @@ sed -i 's/Build-type: Custom/Build-type: Simple/' tmp/androidtree/git-annex.cabal # Build just once, but link twice, for 2 different versions of Android. mkdir -p tmp/androidtree/dist/build/git-annex/4.0 tmp/androidtree/dist/build/git-annex/4.3- if [ ! -e tmp/androidtree/dist/setup/setup ]; then \+ if [ ! -e tmp/androidtree/dist/setup-config ]; then \ cd tmp/androidtree && $$HOME/.ghc/$(shell cat standalone/android/abiversion)/arm-linux-androideabi/bin/cabal configure -fAndroid $(ANDROID_FLAGS); \ fi cd tmp/androidtree && $$HOME/.ghc/$(shell cat standalone/android/abiversion)/arm-linux-androideabi/bin/cabal build \@@ -219,5 +220,9 @@ hdevtools: hdevtools --stop-server || true hdevtools check git-annex.hs -g -cpp -g -i -g -idist/build/git-annex/git-annex-tmp -g -i. -g -idist/build/autogen -g -Idist/build/autogen -g -Idist/build/git-annex/git-annex-tmp -g -IUtility -g -DWITH_TESTSUITE -g -DWITH_S3 -g -DWITH_ASSISTANT -g -DWITH_INOTIFY -g -DWITH_DBUS -g -DWITH_PAIRING -g -DWITH_XMPP -g -optP-include -g -optPdist/build/autogen/cabal_macros.h -g -odir -g dist/build/git-annex/git-annex-tmp -g -hidir -g dist/build/git-annex/git-annex-tmp -g -stubdir -g dist/build/git-annex/git-annex-tmp -g -threaded -g -Wall -g -XHaskell98 -g -XPackageImports++distributionupdate:+ ghc --make Build/DistributionUpdate+ ./Build/DistributionUpdate .PHONY: git-annex git-union-merge git-recover-repository tags build-stamp
Seek.hs view
@@ -141,13 +141,15 @@ withKeyOptions :: (Key -> CommandStart) -> CommandSeek -> CommandSeek withKeyOptions keyop fallbackop params = do bare <- fromRepo Git.repoIsLocalBare- allkeys <- Annex.getFlag "all" <||> pure bare+ allkeys <- Annex.getFlag "all" unused <- Annex.getFlag "unused" auto <- Annex.getState Annex.auto- case (allkeys , unused, auto ) of+ case (allkeys || bare , unused, auto ) of (True , False , False) -> go loggedKeys (False , True , False) -> go unusedKeys- (True , True , _ ) -> error "Cannot use --all with --unused."+ (True , True , _ )+ | bare && not allkeys -> go unusedKeys+ | otherwise -> error "Cannot use --all with --unused." (False , False , _ ) -> fallbackop params (_ , _ , True ) | bare -> error "Cannot use --auto in a bare repository."
Test.hs view
@@ -79,8 +79,8 @@ directenv <- prepare True let tests = testGroup "Tests" [ localOption (QuickCheckTests 1000) properties- , unitTests indirectenv "(indirect)" , unitTests directenv "(direct)"+ , unitTests indirectenv "(indirect)" ] #else -- Windows is only going to use direct mode, so don't test twice.
+ Types/Distribution.hs view
@@ -0,0 +1,38 @@+{- Data type for a distribution of git-annex+ -+ - Copyright 2013 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Types.Distribution where++import Types.Key+import Data.Time.Clock+import Git.Config (isTrue, boolConfig)++data GitAnnexDistribution = GitAnnexDistribution+ { distributionUrl :: String+ , distributionKey :: Key+ , distributionVersion :: GitAnnexVersion+ , distributionReleasedate :: UTCTime+ , distributionUrgentUpgrade :: Maybe GitAnnexVersion+ }+ deriving (Read, Show, Eq)++type GitAnnexVersion = String++data AutoUpgrade = AskUpgrade | AutoUpgrade | NoAutoUpgrade+ deriving (Eq)++toAutoUpgrade :: (Maybe String) -> AutoUpgrade+toAutoUpgrade Nothing = AskUpgrade+toAutoUpgrade (Just s)+ | s == "ask" = AskUpgrade+ | isTrue s == Just True = AutoUpgrade+ | otherwise = NoAutoUpgrade++fromAutoUpgrade :: AutoUpgrade -> String+fromAutoUpgrade AskUpgrade = "ask"+fromAutoUpgrade AutoUpgrade = boolConfig True+fromAutoUpgrade NoAutoUpgrade = boolConfig False
Types/GitConfig.hs view
@@ -17,6 +17,7 @@ import qualified Git.Config import Utility.DataUnits import Config.Cost+import Types.Distribution {- Main git-annex settings. Each setting corresponds to a git-config key - such as annex.foo -}@@ -42,6 +43,7 @@ , annexCrippledFileSystem :: Bool , annexLargeFiles :: Maybe String , annexFsckNudge :: Bool+ , annexAutoUpgrade :: AutoUpgrade , coreSymlinks :: Bool , gcryptId :: Maybe String }@@ -70,6 +72,7 @@ , annexCrippledFileSystem = getbool (annex "crippledfilesystem") False , annexLargeFiles = getmaybe (annex "largefiles") , annexFsckNudge = getbool (annex "fscknudge") True+ , annexAutoUpgrade = toAutoUpgrade $ getmaybe (annex "autoupgrade") , coreSymlinks = getbool "core.symlinks" True , gcryptId = getmaybe "core.gcrypt-id" }
Upgrade.hs view
@@ -1,6 +1,6 @@ {- git-annex upgrade support -- - Copyright 2010 Joey Hess <joey@kitenet.net>+ - Copyright 2010, 2013 Joey Hess <joey@kitenet.net> - - Licensed under the GNU GPL version 3 or higher. -}@@ -11,6 +11,7 @@ import Common.Annex import Annex.Version+import Config #ifndef mingw32_HOST_OS import qualified Upgrade.V0 import qualified Upgrade.V1@@ -36,7 +37,14 @@ ok = return Nothing upgrade :: Bool -> Annex Bool-upgrade automatic = go =<< getVersion+upgrade automatic = do+ upgraded <- go =<< getVersion+ when upgraded $+ ifM isDirect+ ( setVersion directModeVersion+ , setVersion defaultVersion+ )+ return upgraded where #ifndef mingw32_HOST_OS go (Just "0") = Upgrade.V0.upgrade
Utility/FileMode.hs view
@@ -64,6 +64,10 @@ allowWrite :: FilePath -> IO () allowWrite f = modifyFileMode f $ addModes [ownerWriteMode] +{- Turns a file's owner read bit back on. -}+allowRead :: FilePath -> IO ()+allowRead f = modifyFileMode f $ addModes [ownerReadMode]+ {- Allows owner and group to read and write to a file. -} groupSharedModes :: [FileMode] groupSharedModes =
Utility/Misc.hs view
@@ -21,6 +21,9 @@ import Utility.Exception #endif +import Utility.FileSystemEncoding+import Utility.Monad+ {- A version of hgetContents that is not lazy. Ensures file is - all read before it gets closed. -} hGetContentsStrict :: Handle -> IO String@@ -29,6 +32,13 @@ {- A version of readFile that is not lazy. -} readFileStrict :: FilePath -> IO String readFileStrict = readFile >=> \s -> length s `seq` return s++{- Reads a file strictly, and using the FileSystemEncofing, so it will+ - never crash on a badly encoded file. -}+readFileStrictAnyEncoding :: FilePath -> IO String+readFileStrictAnyEncoding f = withFile f ReadMode $ \h -> do+ fileEncoding h+ hClose h `after` hGetContentsStrict h {- Like break, but the item matching the condition is not included - in the second result list.
Utility/Quvi.hs view
@@ -11,9 +11,13 @@ import Common import Utility.Url+import Build.SysConfig (newquvi) import Data.Aeson import Data.ByteString.Lazy.UTF8 (fromString)+import qualified Data.Map as M+import Network.URI (uriAuthority, uriRegName)+import Data.Char data Page = Page { pageTitle :: String@@ -25,6 +29,7 @@ , linkUrl :: URLString } deriving (Show) +{- JSON instances for quvi 0.4. -} instance FromJSON Page where parseJSON (Object v) = Page <$> v .: "page_title"@@ -37,6 +42,20 @@ <*> v .: "url" parseJSON _ = mzero +{- "enum" format used by quvi 0.9 -}+parseEnum :: String -> Maybe Page+parseEnum s = Page+ <$> get "QUVI_MEDIA_PROPERTY_TITLE"+ <*> ((:[]) <$>+ ( Link+ <$> get "QUVI_MEDIA_STREAM_PROPERTY_CONTAINER"+ <*> get "QUVI_MEDIA_STREAM_PROPERTY_URL"+ )+ )+ where+ get = flip M.lookup m+ m = M.fromList $ map (separate (== '=')) $ lines s+ type Query a = [CommandParam] -> URLString -> IO a {- Throws an error when quvi is not installed. -}@@ -54,8 +73,11 @@ query ps url = flip catchNonAsync (const $ return Nothing) (query' ps url) query' :: Query (Maybe Page)-query' ps url = decode . fromString- <$> readProcess "quvi" (toCommand $ ps ++ [Param url])+query' ps url+ | newquvi = parseEnum+ <$> readProcess "quvi" (toCommand $ [Param "dump", Param "-p", Param "enum"] ++ ps ++ [Param url])+ | otherwise = decode . fromString+ <$> readProcess "quvi" (toCommand $ ps ++ [Param url]) queryLinks :: Query [URLString] queryLinks ps url = maybe [] (map linkUrl . pageLinks) <$> query ps url@@ -65,17 +87,47 @@ check :: Query Bool check ps url = maybe False (not . null . pageLinks) <$> query ps url -{- Checks if an url is supported by quvi, without hitting it, or outputting+{- Checks if an url is supported by quvi, as quickly as possible+ - (without hitting it if possible), and without outputting - anything. Also returns False if quvi is not installed. -} supported :: URLString -> IO Bool-supported url = boolSystem "quvi" [Params "-v mute --support", Param url]+supported url+ {- Use quvi-info to see if the url's domain is supported.+ - If so, have to do a online verification of the url. -}+ | newquvi = (firstlevel <&&> secondlevel)+ `catchNonAsync` (\_ -> return False)+ | otherwise = boolSystem "quvi" [Params "--verbosity mute --support", Param url]+ where+ firstlevel = case uriAuthority =<< parseURIRelaxed url of+ Nothing -> return False+ Just auth -> do+ let domain = map toLower $ uriRegName auth+ let basedomain = intercalate "." $ reverse $ take 2 $ reverse $ split "." domain+ any (\h -> domain `isSuffixOf` h || basedomain `isSuffixOf` h) + . map (map toLower) <$> listdomains+ secondlevel = snd <$> processTranscript "quvi"+ (toCommand [Param "dump", Param "-o", Param url]) Nothing -quiet :: CommandParam-quiet = Params "-v quiet"+listdomains :: IO [String]+listdomains + | newquvi = concatMap (split ",") + . concatMap (drop 1 . words) + . filter ("domains: " `isPrefixOf`) . lines+ <$> readProcess "quvi"+ (toCommand [Param "info", Param "-p", Param "domains"])+ | otherwise = return [] -noredir :: CommandParam-noredir = Params "-e -resolve"+{- Disables progress, but not information output. -}+quiet :: CommandParam+quiet+ -- Cannot use quiet as it now disables informational output.+ -- No way to disable progress.+ | newquvi = Params "--verbosity verbose"+ | otherwise = Params "--verbosity quiet" {- Only return http results, not streaming protocols. -} httponly :: CommandParam-httponly = Params "-c http"+httponly+ -- No way to do it with 0.9?+ | newquvi = Params ""+ | otherwise = Params "-c http"
Utility/Tmp.hs view
@@ -62,7 +62,7 @@ withTmpDirIn tmpdir template = bracket create remove where remove d = whenM (doesDirectoryExist d) $- return () -- removeDirectoryRecursive d+ removeDirectoryRecursive d create = do createDirectoryIfMissing True tmpdir makenewdir (tmpdir </> template) (0 :: Int)
Utility/Url.hs view
@@ -14,7 +14,8 @@ checkBoth, exists, download,- downloadQuiet+ downloadQuiet,+ parseURIRelaxed ) where import Common
debian/changelog view
@@ -1,3 +1,30 @@+git-annex (5.20131127) unstable; urgency=low++ * webapp: Detect when upgrades are available, and upgrade if the user+ desires.+ (Only when git-annex is installed using the prebuilt binaries+ from git-annex upstream, not from eg Debian.)+ * assistant: Detect when the git-annex binary is modified or replaced,+ and either prompt the user to restart the program, or automatically+ restart it.+ * annex.autoupgrade configures both the above upgrade behaviors.+ * Added support for quvi 0.9. Slightly suboptimal due to limitations in its+ interface compared with the old version.+ * Bug fix: annex.version did not get set on automatic upgrade to v5 direct+ mode repo, so the upgrade was performed repeatedly, slowing commands down.+ * webapp: Fix bug that broke switching between local repositories+ that use the new guarded direct mode.+ * Android: Fix stripping of the git-annex binary.+ * Android: Make terminal app show git-annex version number.+ * Android: Re-enable XMPP support.+ * reinject: Allow to be used in direct mode.+ * Futher improvements to git repo repair. Has now been tested in tens+ of thousands of intentionally damaged repos, and successfully+ repaired them all.+ * Allow use of --unused in bare repository.++ -- Joey Hess <joeyh@debian.org> Wed, 27 Nov 2013 18:41:44 -0400+ git-annex (5.20131120) unstable; urgency=low * Fix Debian package to not try to run test suite, since haskell-tasty
+ doc/assistant/downloadupgrade.png view
binary file changed (absent → 9071 bytes)
+ doc/assistant/upgradecomplete.png view
binary file changed (absent → 4817 bytes)
+ doc/bugs/Assistant_has_created_155_semitrusted_repositories.mdwn view
@@ -0,0 +1,191 @@+### Please describe the problem.+git annex status reports 160 semitrusted repositories. Four of them are the ones I created (only via webapp, I think I never edited any git-annex config file). One is 00000000-0000-0000-0000-000000000001 -- web+ and although I do not know what it is, it is not something new. The remaining 155 appeared spontaneously after several Gb of data (mostly many small files) were added to an Annex (in an 'archive' directory) operated in direct mode by the assistant.++++### What steps will reproduce the problem?+Add several Gb of files was enough to trigger this problem, but I did not try to reproduce it. It happened the day I installed the 4.20131106~bpo70+1 version.++### What version of git-annex are you using? On what operating system?++4.20131106~bpo70+1 on debian squeeze (7.2), with git 1.8.4.rc3.+++### Please provide any additional information below.+May be related or not: at some point the webapp displayed two warning boxes. One of them held a message that I did not wirte down and proposed to "Restart the thread". This apparently worked since the box disappeared. The other warning box indicated "NetWatcherFallback crashed: unknown response from git cat-file" and proposed to restart the thread. Trying to "restart the thread" via the provided button just did not trigger any response of the webapp which seemed dead at that point.++In spite of the git annex status shown below, the webapp still shows only the expected four repositories.++Output of git annex status (hostname and xmpp account name were edited away):+[[!format sh """+# If you can, paste a complete transcript of the problem occurring here.+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log+repository mode: direct+trusted repositories: +0+semitrusted repositories: 160+ 00000000-0000-0000-0000-000000000001 -- web+ 0ab193eb-0c76-4559-a93c-2e30ed8630a8 -- someMachineIown_datadir (archive)+ 1384784127.91222s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384784164.437824s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384784176.944372s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384784179.254498s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384785147.558938s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785147.717223s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785159.041203s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785159.199504s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785185.79485s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785187.318128s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785215.236504s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785215.389096s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785313.539843s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785313.701305s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785315.596206s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785344.184461s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785348.192805s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785402.70316s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785406.524044s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384785446.074236s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384873605.313126s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384873697.029999s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384873761.687234s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384873774.608376s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384926279.456728s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384926368.736s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384926454.99433s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384926494.152645s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384926504.438232s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384934790.89717s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384934848.757067s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384934899.087168s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384934908.238587s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384948772.14552s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384948805.441196s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384948813.397132s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384948921.45481s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384948924.855852s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384949073.988946s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384949082.298976s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384949399.608138s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384949581.12213s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384949583.9923s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384949700.22807s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384949765.484768s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955202.85962s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955230.953995s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955402.534938s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955457.1885s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955524.603709s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955611.891061s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955677.84592s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955689.293082s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955894.057476s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955910.723021s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955914.732132s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955968.717875s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384955969.634658s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384956004.284925s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384956029.567195s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384956188.628995s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384956379.844701s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384956381.613833s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384956387.923418s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384956395.418701s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384956408.792928s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384956504.019733s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384956519.578085s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384956524.419783s -- 1 391b0557-dc68-4e40-b6d0-da3033588753+ 1384965891.562742s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384965891.815119s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384965903.355602s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384965905.276128s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384965978.806653s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384965979.393089s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966097.495566s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966097.704474s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966154.97658s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966156.967406s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966233.310488s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966233.522324s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966241.284523s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966241.475381s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966301.688497s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966303.427685s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966392.875983s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966393.38718s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966404.708568s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966406.441164s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966553.557387s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966555.752786s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966653.725847s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966654.23288s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966695.201885s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966695.689398s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966784.556877s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966786.574886s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966791.446852s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966793.218318s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384966884.335685s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384966886.147083s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384967054.857465s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384967055.158871s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384967190.980027s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384967193.176584s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384967328.93796s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384967330.428095s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384967526.127311s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384967526.588491s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384967627.132549s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384967627.685201s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384967686.283694s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384967686.728086s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384967768.270887s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384967768.58402s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384967769.245615s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384967771.122238s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384967813.8197s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384967814.168477s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384967915.243469s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384967917.020051s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384968031.757775s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384968032.190452s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384968035.733635s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384968036.03299s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384968144.555556s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384968144.714535s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384968150.090148s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384968150.820567s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384968304.393177s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384968304.613624s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384968604.499519s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384968604.813256s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384968702.566939s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384968704.427767s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384968725.375289s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384968725.939271s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384968798.402904s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384968798.659754s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384969055.285004s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384969055.715448s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384969159.885115s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384969162.382266s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384969184.633052s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384969185.413769s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384969374.791849s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384969377.497842s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384969475.469111s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384969489.697737s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384969492.087023s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384969492.58214s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384969784.725195s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384969786.49773s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 1384969814.984624s -- 1 0ab193eb-0c76-4559-a93c-2e30ed8630a8+ 1384969815.397676s -- 0 391b0557-dc68-4e40-b6d0-da3033588753+ 391b0557-dc68-4e40-b6d0-da3033588753 -- here (client)+ 668ef9d8-68c6-484e-89e5-06634d590a11 -- rsync.net_datadir_annex (transfer)+ b0d3c000-0ac9-4a05-aef4-47f826d5c759 -- user.name (client)+++# End of transcript or log.+"""]]
doc/bugs/Finding_an_Unused_file.mdwn view
@@ -146,7 +146,7 @@ """]] > If `git log -S` does not find the key, then it was not used for any-> commit currently in the git repository. Which is certianly possible;+> commit currently in the git repository. Which is certainly possible; > for example `git annex add file; git rm file`. > > This is a dup of [[todo/wishlist: option to print more info with 'unused']]; [[done]] --[[Joey]]
+ doc/bugs/Git_annex_add_fails_on_read-only_files.mdwn view
@@ -0,0 +1,37 @@+### Please describe the problem.++Git annex cannot add/import files in folders without w or x permission++Note that (as stated in the comments) this might not be a bug. The problem might somewhere within Git, because Git does not manage file permissions very well. I was just hoping that I could import large directory trees into git-annex with a simple call to "git annex import"; now it seems I have to fix their permissions first.++### What steps will reproduce the problem?++ $ cd /tmp+ $ mkdir -p folder/subfolder+ $ echo "some text" > folder/subfolder/some_file.txt+ $ chmod 500 folder/subfolder+ $ mkdir annex+ $ cd annex+ $ git init+ $ git annex init "Testing git annex"+ $ git annex import ../folder+ Fails+ $ chmod 600 ../folder/subfolder+ $ git annex import ../folder+ Fails+ $ chmod 700 ../folder/subfolder+ $ git annex import ../folder+ Works. Subfolder now has 755 permissions++### What version of git-annex are you using? On what operating system?++ git-annex version: 4.20131106+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP Feeds Quvi TDFA CryptoHash+ key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL+ remote types: git gcrypt S3 bup directory rsync web webdav glacier hook+ local repository version: 3+ default repository version: 3+ supported repository versions: 3 4+ upgrade supported from repository versions: 0 1 2++ git version 1.8.4.3
doc/bugs/Lost_S3_Remote/comment_1_6e80e6db6671581d471fc9a54181c04c._comment view
@@ -6,5 +6,5 @@ content=""" Despite `status` listing S3 support, your git-annex is actually built with S3stub, probably because it failed to find the necessary S3 module at build time. Rebuild git-annex and watch closely, you'll see \"** building without S3 support\". Look above that for the error and fix it. -It was certianly a bug that it showed S3 as supported when built without it. I've fixed that.+It was certainly a bug that it showed S3 as supported when built without it. I've fixed that. """]]
+ doc/bugs/Too_many_open_files.mdwn view
@@ -0,0 +1,55 @@+### Please describe the problem.++The transferrer crashes after a while due to too many open files++### What steps will reproduce the problem?++Have a huge annex. Connect two local machines, one with the huge annex, the other one without. Let them copy files…++### What version of git-annex are you using? On what operating system?++latest version+git-annex version: 5.20131117-gbd514dc+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV FsEvents XMPP DNS Feeds Quvi TDFA CryptoHash+key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL+remote types: git gcrypt S3 bup directory rsync web webdav glacier hook++on Mac OS X 10.9++### Please provide any additional information below.++[[!format sh """+# If you can, paste a complete transcript of the problem occurring here.+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log++[2013-11-22 10:49:19 CET] Transferrer: Downloaded oktaeder.png+[2013-11-22 10:49:19 CET] Transferrer: Downloaded oktaeder.png+[2013-11-22 10:49:19 CET] Transferrer: Downloaded oktaeder.png+[2013-11-22 10:49:20 CET] Transferrer: Downloaded klett-cover-neu.jpg+[2013-11-22 10:49:20 CET] Transferrer: Downloaded klett-cover-neu.jpg+[2013-11-22 10:49:20 CET] Transferrer: Downloaded kara-worl..ditor.gif+git-annex: runInteractiveProcess: pipe: Too many open files+Committer crashed: lsof: createProcess: resource exhausted (Too many open files)+[2013-11-22 10:49:20 CET] Committer: warning Committer crashed: lsof: createProcess: resource exhausted (Too many open files)+[2013-11-22 10:49:20 CET] Transferrer: Downloaded kara-worl..ditor.gif+[2013-11-22 10:49:20 CET] Transferrer: Downloaded kara-worl..ditor.gif+[2013-11-22 10:49:20 CET] Transferrer: Downloaded image1.png+[2013-11-22 10:49:21 CET] Transferrer: Downloaded image1.png+[2013-11-22 10:49:21 CET] Transferrer: Downloaded image.png+[2013-11-22 10:49:21 CET] Transferrer: Downloaded image.png+[2013-11-22 10:49:21 CET] Transferrer: Downloaded ikoseder.png+[2013-11-22 10:49:21 CET] Transferrer: Downloaded ikoseder.png+[2013-11-22 10:49:22 CET] Transferrer: Downloaded ikoseder.png+[2013-11-22 10:49:22 CET] Transferrer: Downloaded ikosaeder.jpg+git-annex: runInteractiveProcess: pipe: Too many open files+ok+(Recording state in git...)+git-annex: socket: resource exhausted (Too many open files)+[2013-11-22 10:49:22 CET] Transferrer: Downloaded ikosaeder.jpg+Transferrer crashed: getCurrentDirectory: resource exhausted (Too many open files)+[2013-11-22 10:49:22 CET] Transferrer: warning Transferrer crashed: getCurrentDirectory: resource exhausted (Too many open files)+git-annex: runInteractiveProcess: pipe: Too many open files+git-annex: runInteractiveProcess: pipe: Too many open files++# End of transcript or log.+"""]]
+ doc/bugs/direct_mode_sync_should_avoid_git_commit.mdwn view
@@ -0,0 +1,5 @@+Per forum post linking to this bug, git commit can be very slow when run in a filesystem without symlink support, and seems to be reading the content of files just in order to show typechanged messages in the status.++So, git annex sync should stop using git commit when in direct mode, and instead manually make its own commit. Git.Branch.commit and Git.Branch.update should be able to easily be used for this.++PS: this page was created elsewhere, and therefore not listed in bugs page
+ doc/bugs/git-annex_does_not_install_on_windows_without_admin_rights.mdwn view
@@ -0,0 +1,19 @@+### Please describe the problem.++Installing on Windows requires installing git followed by git-annex. Installing the former works without admin rights, but the latter cannot be installed afterwards.++### What steps will reproduce the problem?++1. Create a Windows account without admin rights+2. Install git+3. Install git-annex++### What version of git-annex are you using? On what operating system?++Latest release on MS Windows.++### Please provide any additional information below.+++Installing git creates read-only directories that cannot be used by the git-annex install afterwards. Without admin rights, the read-only flag of the git dir cannot be altered.+
doc/bugs/git_annex_indirect_can_fail_catastrophically.mdwn view
@@ -70,7 +70,7 @@ Any update on this? Why is `-a` used here? -- [[anarcat]] -> -a is not really the problem. You certianly do usually want+> -a is not really the problem. You certainly do usually want > to commit your changes before converting to direct mode. > > [[done]]; now when this happens it catches the exception and
+ doc/bugs/repair_fails_when_home_on_seperate_partition.mdwn view
@@ -0,0 +1,60 @@+### Please describe the problem.+++### What steps will reproduce the problem?++(1) Place a broken repo on a different mount point than the root partition.++(2) Run+ git annex repair.++### What version of git-annex are you using? On what operating system?++ 5.20131118-gc7e5cde on Ubuntu 12.04++### Please provide any additional information below.++[[!format sh """+# If you can, paste a complete transcript of the problem occurring here.+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log++$ git annex repair --force++Running git fsck ...+git fsck found 74 broken objects.+Unpacking all pack files.+Unpacking objects: 100% (2307/2307), done.+Unpacking objects: 100% (241565/241565), done.+Re-running git fsck to see if it finds more problems.+Initialized empty Git repository in /tmp/tmprepo.0/.git/+Trying to recover missing objects from remote pi.fritz.box__var_lib_store_annex+Trying to recover missing objects from remote pi.fritz.box__var_lib_store_annex+74 missing objects could not be recovered!+++Deleted remote branch pi.fritz.box__var_lib_store_annex/master (was dffa056).+error: Could not read 4e01bbdc7ce31247ad66ab13ca46925ac2c8db9a+fatal: Failed to traverse parents of commit 718525a48b4d6b3404eda5e189332d73c968a2be+Deleted remote branch pi.fritz.box__var_lib_store_annex/synced/git-annex (was 718525a).+Deleted remote branch pi.fritz.box__var_lib_store_annex/synced/master (was 9aedf69).+Deleted remote branch pi.fritz.box_annex/synced/master (was 92b1042).+Deleted remote branch store/master (was b059380).+removed 5 remote tracking branches that referred to missing objects+fatal: bad object refs/heads/git-annex+fatal: bad object refs/heads/git-annex+fatal: bad object refs/heads/git-annex+error: remote branch 'git-annex' not found.++git-annex: /tmp/packed-refs19813: rename: unsupported operation (Invalid cross-device link)+failed+git-annex: repair: 1 failed+++# End of transcript or log.+"""]]++> Thanks for reporting. As far as I can see, this was fixed+> accidentially, when I rewrote the packed refs file handling code to not+> re-write the file. It had been using a temp file, and renaming it, thus+> the problem. I checked the repair code and can find no other probems+> of this sort currently in it. [[done]] --[[Joey]]
+ doc/bugs/test_failures_on_window_for_5.20131118.mdwn view
@@ -0,0 +1,20 @@+### Please describe the problem.++git annex test reports failures++### What steps will reproduce the problem?++running git annex test (from standard cmd, with: git version: 1.7.11.msysgit.1)++### What version of git-annex are you using? On what operating system?++5.20131118 from installers++### Please provide any additional information below.++operating system:++windows XP, NTFS = 1 FAIL+windows 7, NTFS = 2 FAILs++see attachment for full log of git annex test output
doc/bugs/utf8/comment_13_7044d2c5bb1c91ee37eb9868963a1ff2._comment view
@@ -37,5 +37,5 @@ copy foo (checking foo...) [2013-07-27 16:40:42 EDT] call: ssh [\"-T\",\"fozz@git-annex-markdown.lang.speechmarks.com-fozz_phone.2Dannex.IdWwlXHtSsjVUMcq\",\"git-annex-shell 'inannex' '' 'SHA256E-s29--093429efb0d1427753d1f038f5279ec4df66785a1b2429b3fa5e3a01bcb75bd8' --uuid 111\"] -So, I don't understand how this could have happened. Although my recent changes mean it'll use a 62 byte path max on Android now, which certianly should avoid the problem, even if there's some actual bug here that I cannot reproduce.+So, I don't understand how this could have happened. Although my recent changes mean it'll use a 62 byte path max on Android now, which certainly should avoid the problem, even if there's some actual bug here that I cannot reproduce. """]]
doc/builds.mdwn view
@@ -9,8 +9,8 @@ <h2>Android</h2> <iframe width=1024 scrolling=no frameborder=0 marginheight=0 marginwidth=0 src="https://downloads.kitenet.net/git-annex/autobuild/android/"> </iframe>-<h2>OSX Mountain Lion</h2>-<iframe width=1024 scrolling=no frameborder=0 marginheight=0 marginwidth=0 src="https://downloads.kitenet.net/git-annex/autobuild/x86_64-apple-mountain-lion/">+<h2>OSX Mavericks</h2>+<iframe width=1024 scrolling=no frameborder=0 marginheight=0 marginwidth=0 src="https://downloads.kitenet.net/git-annex/autobuild/x86_64-apple-mavericks/"> </iframe> <h2>OSX Lion</h2> <iframe width=1024 scrolling=no frameborder=0 marginheight=0 marginwidth=0 src="http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/">
doc/design/assistant/blog/day_140__release_monday.mdwn view
@@ -19,7 +19,7 @@ should be done by the end of today. Also found a real stinker of a bug in `dirContentsRecursive`, which was-just completely broken, apparently since day 1. Fixing that has certianly+just completely broken, apparently since day 1. Fixing that has certainly fixed buggy behavior of `git annex import`. It seems that the other user of it, the transfer log code, luckily avoided the deep directory trees that triggered the bug.
doc/design/assistant/blog/day_83__3-way.mdwn view
@@ -68,6 +68,6 @@ B and C, there would be an upload loop 'B -> C -> D -> B`). So unless I can find a better event to hook into, this idea is doomed. -I do have another idea to fix the same problem. C could certianly remember+I do have another idea to fix the same problem. C could certainly remember that it saw a file and didn't know where to get the content from, and then when it receives a git push of a git-annex branch, try again.
doc/design/assistant/gpgkeys.mdwn view
@@ -7,7 +7,7 @@ 1. Help user set up a gpg key if they don't have one. This could be a special-purpose key dedicated to being used by git-annex. It might be nice to leave the user with a securely set up general purpose key,- but that would certianly preclude prompting for its password in the+ but that would certainly preclude prompting for its password in the webapp. Indeed, the password prompt is the main problem here. Best solution would be to get gpg agent working on all supported platforms.
doc/design/assistant/polls/Android_default_directory.mdwn view
@@ -4,4 +4,4 @@ want the first time they run it, but to save typing on android, anything that gets enough votes will be included in a list of choices as well. -[[!poll open=yes expandable=yes 62 "/sdcard/annex" 6 "Whole /sdcard" 4 "DCIM directory (photos and videos only)" 1 "Same as for regular git-annex. ~/annex/"]]+[[!poll open=yes expandable=yes 62 "/sdcard/annex" 6 "Whole /sdcard" 5 "DCIM directory (photos and videos only)" 1 "Same as for regular git-annex. ~/annex/"]]
+ doc/design/assistant/upgrading.mdwn view
@@ -0,0 +1,52 @@+The assistant should support upgrading itself.++## non-distro upgrades++When git-annex was installed from this website, the assistant should poll+periodically (once a day or so) to see if there is a new version.+It downloads, over https, a .info file, which contains a serialized data+type containing upgrade information. The url it's downloaded from is+configured by setting `UPGRADE_LOCATION` when building git-annex on the+autobuilders.++When a new version is found, the webapp prompts the user to start the+upgrade. (annex.autoupgrade can be set to true to upgrade w/o prompting.)++The upgrade process is automatic, and rather tricky. The file is downloaded+using git-annex (as a regular key!), and is then unpacked into a new+directory, and the programfile updated to point to it. Then git-annex+restarts itself.++### manifest files++To clean up the old installation, a git-annex.MANIFEST file is looked for+in it, and the files listed, as well as empty directories, are deleted.+I don't want to accidentially delete something I didn't ship!++## restart on upgrade++When git-annex is installed from a proper distribution package, there is no+need for the above. But, the assistant still needs to notice when git-annex+get upgraded, and offer to restart (or automatically restart when+annex.autoupgrade is set).++This is done using the DirWatcher, watching the directory containing the+git-annex binary. Or, in the case of a non-distro install, watching the+directory where eg git-annex.linux/ was unpacked.++When an change is detected, restart.++## multi-daemon upgrades++A single system may have multiple assistant daemons running in different+repositories.++In this case, one daemon should do the non-distro upgrade, and the rest+should notice the upgrade and restart.++I don't want every daemon trying to download the file at once..++Approach: The first new version is installed into a stable directory, based+on its version. So, start the upgrade by making this directory. If upgrade+is already in progress, the directory will already exist. (Remove directory+if upgrade fails.)
doc/design/roadmap.mdwn view
@@ -6,7 +6,7 @@ * Month 1 [[!traillink assistant/encrypted_git_remotes]] * Month 2 [[!traillink assistant/disaster_recovery]]-* **Month 3 user-driven features and polishing**+* **Month 3 user-driven features and polishing** [[todo/direct_mode_guard]] [[assistant/upgrading]] * Month 4 improve special remote interface & git-annex enhancement contest * Month 5 [[!traillink assistant/xmpp_security]] * Month 6 Windows assistant and webapp
doc/devblog/day_-4__forgetting.mdwn view
@@ -72,7 +72,7 @@ to handle this case, too.. * For some reason the automatic transitioning code triggers- a "(recovery from race)" commit. This is certianly a bug somewhere,+ a "(recovery from race)" commit. This is certainly a bug somewhere, because you can't have a race with only 1 participant. ----
doc/devblog/day_48__direct_mode_guard_design.mdwn view
@@ -3,7 +3,7 @@ direct mode repository seems increasingly important. First, considered moving `.git`, so git won't know it's a git repository.-This doesn't seem *too* hard to do, but there will certianly be unexpected+This doesn't seem *too* hard to do, but there will certainly be unexpected places that assume `.git` is the directory name. I dislike it more and more as I think about it though, because it moves
+ doc/devblog/day_61__damage_driven_development__II.mdwn view
@@ -0,0 +1,15 @@+Pushed out a minor release of git-annex today, mostly to fix build problems+on Debian. No strong reason to upgrade to it otherwise.++Continued where I left off with the Git.Destroyer. Fixed quite a lot of+edge cases where git repair failed due to things like a corrupted .git/HEAD+file (this makes git think it's not in a git repository), corrupt+git objects that have an unknown object type and so crash git hard, and+an interesting failure mode where git fsck wants to allocate 116 GB of+memory due to a corrupted object size header. Reported that last to the git+list, as well as working around it.++At the end of the day, I ran a test creating 10000 corrupt git+repositories, and **all** of them were recovered! Any improvements will+probably involve finding new ways to corrupt git repositories that my code+can't think of. ;)
+ doc/devblog/day_62__upgrade_alerts.mdwn view
@@ -0,0 +1,22 @@+Still working on the git repair code. Improved the test suite, which found+some more bugs, and so I've been running tests all day and occasionally+going and fixing a bug in the repair code. The hardest part of repairing a+git repo has turned out to be reliably determining which objects in it are+broken. Bugs in git don't help (but the git devs are going to fix the one I+reported).++But the interesting new thing today is that I added some upgrade alert code+to the webapp. Ideally everyone would get git-annex and other software as+part of an OS distribution, which would include its own upgrade system -- +But the [survey](http://git-annex-survey.branchable.com/polls/2013/how_installed/)+tells me that a quarter of installs are from the prebuilt binaries I+distribute.++So, those builds are going to be built with knowledge of an upgrade url,+and will periodically download a small info file (over https) to see if a+newer version is available, and show an alert.++I think all that's working, though I have not yet put the info files in+place and tested it. The actual upgrade process will be a manual+download and reinstall, to start with, and then perhaps I'll automate it+further, depending on how hard that is on the different platforms.
+ doc/devblog/day_63__leverage.mdwn view
@@ -0,0 +1,24 @@+The difference picking the right type can make! Last night, I realized that+the where I had a `distributionSha256sum :: String`, I should instead use+`distributionKey :: Key`. This means that when git-annex is eventually+downloading an upgrade, it can treat it as just another Key being+downloaded from the web. So the webapp will show that transfer along with+all the rest, and I can leverage tons of code for a new purpose. For+example, it can simply fsck the key once it's downloaded to verify its+checksum.++Also, built a DistriutionUpdate program, which I'll run to generate the+info files for a new version. And since I keep git-annex releases in a+git-annex repo, this too leverages a lot of git-annex modules, and ended up+being just 60 easy lines of code. The upgrade notification code is tested+and working now.++And, I made the assistant detect when the git-annex program binary is+replaced or modified. Used my existing DirWatcher code for that. The plan+is to restart the assistant on upgrade, although I need to add some sanity+checks (eg, reuse the lsof code) first. And yes, this will work even for+`apt-get upgrade`!++----++Today's work was sponsored by Paul Tötterman
+ doc/devblog/day_64__overkill.mdwn view
@@ -0,0 +1,31 @@+Completely finished up with making the assistant detect when git-annex's+binary has changed and handling the restart.++It's a bit tricky because during an upgrade there can be two assistant+daemons running at the same time, in the same repository. Although I+disable the watcher of the old one first. Luckily, git-annex has long+supported running multiple concurrent git-annex processes in the same+repository.++The surprisingly annoying part turned out to be how to make the webapp+redirect the browser to the new url when it's upgraded. Particularly needed+when automatic upgrades are enabled, since the user will not then be taking+any action in the webapp that could result in a redirect. My solution to this+feels like overkill; the webapp does ajax long polling until it gets an+url, and then redirects to it. Had to write javascript code and ugh.++But, that turned out to also be useful when manually restarting the webapp+(removed some horrible old code that ran a shell script to do it before),+and also when shutting the webapp down.++[[!img assistant/downloadupgrade.png alt="assistant downloading an upgrade to itself"]]++Getting back to upgrades, I have the assistant downloading the upgrade, and+running a hook action once the key is transferred. Now all I need is some+platform-specific code to install it. Will probably be hairy, especially on+OSX where I need to somehow unmount the old git-annex dmg and mount the new+one, from within a program running on the old dmg.++----++Today's work was sponsored by Evan Deaubl.
+ doc/devblog/day_65__wrapping_up_upgrades.mdwn view
@@ -0,0 +1,5 @@+[[!img assistant/upgradecomplete.png]]++Upgrades are fully working on Linux. OSX code is written but intested and I+thought of one bug it certainly has on my evening walk. Probably another+hour's work left later this evening to finish it off.
+ doc/devblog/day_66__upgrade_testing.mdwn view
@@ -0,0 +1,17 @@+Upgrades should be working on OSX Mavericks, Linux, and sort of on Android.+This needs more testing, so I have temporarily made the daily builds think+they are an older version than the last git-annex release. So when you+install a daily build, and start the webapp, it should try to upgrade+(really downgrade) to the last release. Tests appreciated.++Looking over the whole upgrade code base, it took 700 lines of code+to build the whole thing, of which 75 are platform specific (and mostly+come down to just 3 or 4 shell commands). Not bad..++----++Last night, added support for quvi 0.9, which has a completely changed+command line interface from the 0.4 version.++Plan to spend tomorrow catching up on bug reports etc and then low activity+for rest of the week.
+ doc/devblog/day_67_thanksgiving_rush.mdwn view
@@ -0,0 +1,19 @@+My last day before thanksgiving, getting caught up with some recent bug+reports and, quite a rush to get a lot of fixes in. Adding to the fun,+wintery weather means very limited power today.++It was a very productive day, especially for Android, which hopefully has+XMPP working again (at least it builds..), halved the size of the package,+etc.++Fixed a stupid bug in the automatic v5 upgrade code; annex.version was not+being set to 5, and so every git annex command was+actually re-running the upgrade.++Fixed another bug I introduced last Friday, which the test suite luckily+caught, that broke using some local remotes in direct mode.++Tracked down a behavior that makes `git annex sync` quite slow on+filesystems that don't support symlinks. I need to switch direct mode to +not using `git commit` at all, and use plumbing to make commits there.+Will probably work on this over the holiday.
doc/devblog/day_9__Friday_the_13th.mdwn view
@@ -10,7 +10,7 @@ quite ugly; more direct mode mapping breakage which resulted in files not being accessible. Also fsck on Windows failed to detect and fix the problem. All fixed now. (If you use git-annex on Windows, you should-certianly upgrade and run `git annex fsck`.)+certainly upgrade and run `git annex fsck`.) As with most bugs in the Windows port, the underlying cause turned out to be stupid: `isSymlink` always returned False on Windows. Which makes sense
+ doc/forum/New_special_remote_suggeston_-_clean_directory.mdwn view
@@ -0,0 +1,15 @@+The [[special remotes]] available all do great things and enable a ton of different services to be integrated.++Strikingly, the one service I can't satisfactorily integrate with git-annex is a remote folder on a eg NAS (think: computer without git-annex installed) that I want to look like the original annex. As in, when I do a 'tree annexdir' it'd look the same on both locations (except, on the remote there would not be any symlinks, it'd be like it was in directmode, and there would not be a .git subdir).++## Why? Use Case?++I have a Synology NAS that I share access with with my wife. I want her to be able to access the files (photos/videos/music) in a sane manner (ie: not traversing sub-sub-sub 'randomly' named directories) but I also want to be able to manage them with git-annex on my machine (to gain the standard git-annex benefits, specifically the bob the archivist use case). The NAS has the ability to use ssh+rsync, so I'll assume those two tools can be used.++This special remote could be thought of as the 'least common denominator of special remotes'; almost any server with ssh+rsync could be a remote, no matter if you have install privs or if the architecture (eg: ARM) is supported by git-annex.++## Issues?++First and foremost, this can't be (really really shouldn't be) a trusted remote; my wife could accidentally delete all files on the NAS while I am away. So my local git-annex shouldn't assume the NAS counts towards numcopies (unless I'm a real masochist).++Secondly, what to do when files change/are added/removed on the special remote? Probably the same thing that the assistant does with everything. The only thing special is that new/modified files will need to be copied locally from this special remote before being added to the annex (to get hash and such).
+ doc/forum/Some_mounted_devices_not_detected.mdwn view
@@ -0,0 +1,3 @@+Automounted USB devices are not detected by the git-annex webapp on my Debian testing/squeeze installation, only drives with entries in /etc/fstab show up in the device list. Is there any way to tweak/get around this?++I'm running version 4.20131106 (couldn't manage to build the package for sid).
+ doc/forum/could_not_read_from_remote_repository.mdwn view
@@ -0,0 +1,36 @@+hi, i'm trying to set up my notebook and desktop pc to sync my documents. so i used local computers in the web app as a sync option, but on my notebook i get the following error:++ [2013-11-26 11:29:03 CET] main: Pairing in progress+ X11 forwarding request failed+ /home/max/.ssh/git-annex-shell: line 4: exec: git-annex-shell: not found+ X11 forwarding request failed on channel 0+ /home/max/.ssh/git-annex-shell: line 4: exec: git-annex-shell: not found+ fatal: Could not read from remote repository.+ + Please make sure you have the correct access rights+ and the repository exists.+ [2013-11-26 11:29:31 CET] PairListener: Syncing with desk_Private_Dokumente + X11 forwarding request failed on channel 0+ /home/max/.ssh/git-annex-shell: line 4: exec: git-annex-shell: not found+ fatal: Could not read from remote repository.++ Please make sure you have the correct access rights+ and the repository exists.++ merge: refs/remotes/desk_Private_Dokumente/master - not something we can merge++ merge: refs/remotes/desk_Private_Dokumente/synced/master - not something we can merge+ X11 forwarding request failed+ /home/max/.ssh/git-annex-shell: line 4: exec: git-annex-shell: not found+ X11 forwarding request failed on channel 0+ /home/max/.ssh/git-annex-shell: line 4: exec: git-annex-shell: not found+ fatal: Could not read from remote repository.++ Please make sure you have the correct access rights+ and the repository exists.++my desktop succeeded in adding the repository. ++any idea whats going wrong ?++thanks
+ doc/forum/dropping_files_not_working_when_using_git_annex_assistant.txt view
@@ -0,0 +1,18 @@+Just playing with git-annex which looks great so far, but I noticed that when you make use off "git annex assistant" to watch and sync your repo with the remote it doesn't drop files anymore. They just stay in the repo.++What I have is the following:++- 2 repo's in direct mode+- they both have each other as remote+- they're synced and stay synced with the assistant daemon running (in both repo's started "git annex assistant")+- is see changes coming and precessed, so so far so good.++Then I drop in one repo a path for instance like : git annex drop iso+Afterwards I still see the files (and contents) in that repo. New files in the iso path are still synced to the other and vise versa.++Then I kill the assistant on both side's and drop the path again. This time it's dropped as expected and the contents of the file in the iso path are gone.+Starting the assistant again brings is back though :(++I really liked the assistant feature and possibility of dropping the files from one repo, but they don't seem to work together.++Is this a bur or expected behaviour? I think the latter since the assistant also does the git annex get commands so sounds logical?
+ doc/forum/s3_vs_ssh_Performance_Problems.mdwn view
@@ -0,0 +1,8 @@+I backup/sync my music using annex. I used to have one repo with 3 clones, one full copy on my vps, one full copy and one partial copy on my laptops. I decided to move all data to s3. Declared my vps repo dead, purged history (I do not care about history for this particular repo) pushed the git repo to a different computer (bare repo no data) and data to s3 (gpg encrypted). I've just finished uploading all files (around 200gb) couple files failed during the initial upload so I did a `git annex copy --quiet --to mys3 --fast` this command used to take 15 20 secs on my laptop when sending data to vps using ssh but now it took 2 hours to complete (pushing mem usage to 90%).++I have one other repo (1.5gb in size 42k files using indirect mode, data gpg encrypted on s3) using the same setup except this repos content has always been on s3 i had the same behavior on this repo too. adding a file and running a copy to push content to s3 took couple hours even if I add a single 1kb file. I used to blame my hard drive, damn thing is slow but now I think this is related to s3. is there any workaround for this?++Both machines are using,++ git-annex version: 4.20130913-gd20a4f2+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP Feeds Quvi
+ doc/forum/unsynced_folder.mdwn view
@@ -0,0 +1,3 @@+If I have an archive with a lot of big files, is it possible to get one of them without using the command line, and without it popping up on other clients of that repository?+Is it possible to have a folder that will not be synced with other clients but will still download the file when i copy it from archive?+.gitignore probably wont work because that will not get the file from archive.
doc/git-annex.mdwn view
@@ -544,7 +544,7 @@ to their local `git-annex` branches. So the forgetfulness will automatically propigate out from its starting point until all repositories running git-annex have forgotten their old history. (You may need to force- git to push the branch to any git repositories not running git-annex.+ git to push the branch to any git repositories not running git-annex.) * `repair` @@ -1146,6 +1146,21 @@ When set to false, prevents the webapp from reminding you when using repositories that lack consistency checks.++* `annex.autoupgrade`++ When set to ask (the default), the webapp will check for new versions+ and prompt if they should be upgraded to. When set to true, automatically+ upgrades without prompting (on some supported platforms). When set to+ false, disables any upgrade checking.++ Note that upgrade checking is only done when git-annex is installed+ from one of the prebuilt images from its website. This does not+ bypass eg, a Linux distribution's own upgrade handling code.++ This setting also controls whether to restart the git-annex assistant+ when the git-annex binary is detected to have changed. That is useful+ no matter how you installed git-annex. * `annex.autocommit`
+ doc/ikiwiki/pagespec.mdwn view
@@ -0,0 +1,86 @@+[[!meta robots="noindex, follow"]]+To select a set of pages, such as pages that are locked, pages+whose commit emails you want subscribe to, or pages to combine into a+blog, the wiki uses a PageSpec. This is an expression that matches+a set of pages.++The simplest PageSpec is a simple list of pages. For example, this matches+any of the three listed pages:++ foo or bar or baz++More often you will want to match any pages that have a particular thing in+their name. You can do this using a glob pattern. "`*`" stands for any part+of a page name, and "`?`" for any single letter of a page name. So this+matches all pages about music, and any [[SubPage]]s of the SandBox, but does+not match the SandBox itself:++ *music* or SandBox/*++You can also prefix an item with "`!`" to skip pages that match it. So to+match all pages except for Discussion pages and the SandBox:++ * and !SandBox and !*/Discussion++Some more elaborate limits can be added to what matches using these functions:++* "`glob(someglob)`" - matches pages and other files that match the given glob.+ Just writing the glob by itself is actually a shorthand for this function.+* "`page(glob)`" - like `glob()`, but only matches pages, not other files+* "`link(page)`" - matches only pages that link to a given page (or glob)+* "`tagged(tag)`" - matches pages that are tagged or link to the given tag (or+ tags matched by a glob)+* "`backlink(page)`" - matches only pages that a given page links to+* "`creation_month(month)`" - matches only files created on the given month+ number+* "`creation_day(mday)`" - or day of the month+* "`creation_year(year)`" - or year+* "`created_after(page)`" - matches only files created after the given page+ was created+* "`created_before(page)`" - matches only files created before the given page+ was created+* "`internal(glob)`" - like `glob()`, but matches even internal-use + pages that globs do not usually match.+* "`title(glob)`", "`author(glob)`", "`authorurl(glob)`",+ "`license(glob)`", "`copyright(glob)`", "`guid(glob)`" + - match pages that have the given metadata, matching the specified glob.+* "`user(username)`" - tests whether a modification is being made by a+ user with the specified username. If openid is enabled, an openid can also+ be put here. Glob patterns can be used in the username. For example, + to match all openid users, use `user(*://*)`+* "`admin()`" - tests whether a modification is being made by one of the+ wiki admins.+* "`ip(address)`" - tests whether a modification is being made from the+ specified IP address. Glob patterns can be used in the address. For+ example, `ip(127.0.0.*)`+* "`comment(glob)`" - matches comments to a page matching the glob.+* "`comment_pending(glob)`" - matches unmoderated, pending comments.+* "`postcomment(glob)`" - matches only when comments are being + posted to a page matching the specified glob++For example, to match all pages in a blog that link to the page about music+and were written in 2005:++ blog/* and link(music) and creation_year(2005)++Note the use of "and" in the above example, that means that only pages that+match each of the three expressions match the whole. Use "and" when you+want to combine expression like that; "or" when it's enough for a page to+match one expression. Note that it doesn't make sense to say "index and+SandBox", since no page can match both expressions.++More complex expressions can also be created, by using parentheses for+grouping. For example, to match pages in a blog that are tagged with either+of two tags, use:++ blog/* and (tagged(foo) or tagged(bar))++Note that page names in PageSpecs are matched against the absolute+filenames of the pages in the wiki, so a pagespec "foo" used on page+"a/b" will not match a page named "a/foo" or "a/b/foo". To match+relative to the directory of the page containing the pagespec, you can+use "./". For example, "./foo" on page "a/b" matches page "a/foo".++To indicate the name of the page the PageSpec is used in, you can+use a single dot. For example, `link(.)` matches all the pages+linking to the page containing the PageSpec.
doc/install/OSX.mdwn view
@@ -23,7 +23,7 @@ [Jimmy Tang](http://www.sgenomics.org/~jtang/) autobuilds the app for OSX Lion. -* [autobuild of git-annex.dmg.bz2](http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/ref/master/git-annex.dmg.bz2) ([build logs](http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/))+* [autobuild of git-annex.dmg](http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/ref/master/git-annex.dmg.bz2) ([build logs](http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/)) * [past builds](http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/sha1/) -- directories are named from the commitid's [[Joey]] autobuilds the app for Mavericks.
doc/install/OSX/comment_32_a46d8e3e7795b9afb1e1c2be943d12af._comment view
@@ -4,7 +4,7 @@ subject="comment 32" date="2013-10-21T22:47:14Z" content="""-You probably need to install libdbus dev stuff, and then the haskell dbus library. But it's certianly going to need code changes to make git-annex use dbus in any way on OSX, assuming there are even useful dbus events generated for network connections and drives being mounted on OSX.+You probably need to install libdbus dev stuff, and then the haskell dbus library. But it's certainly going to need code changes to make git-annex use dbus in any way on OSX, assuming there are even useful dbus events generated for network connections and drives being mounted on OSX. It was saying \"gcrypt\" when it meant \"git-remote-gcrypt\". """]]
+ doc/install/cabal/comment_29_ac082dca67f4a29b06070c0283130f52._comment view
@@ -0,0 +1,39 @@+[[!comment format=mdwn+ username="robohack"+ ip="24.67.98.78"+ subject="cabal install failing due to problems building pcre-light-0.4"+ date="2013-11-21T20:17:10Z"+ content="""+After a fresh install of Haskell, and following the instructions above, I end up with the following rather bizarre and unexpected problem:++ $ cabal install git-annex --bindir=$HOME/bin -f\"-assistant -webapp -webdav -pairing -xmpp -dns\"+ Resolving dependencies...+ Configuring pcre-light-0.4...+ Building pcre-light-0.4...+ Preprocessing library pcre-light-0.4...+ Base.hsc:103:18: error: pcre.h: No such file or directory+ Base.hsc: In function ‘main’:+ Base.hsc:402: error: ‘PCRE_ANCHORED’ undeclared (first use in this function)+ Base.hsc:402: error: (Each undeclared identifier is reported only once+ Base.hsc:402: error: for each function it appears in.)+ Base.hsc:405: error: ‘PCRE_AUTO_CALLOUT’ undeclared (first use in this function)++(followed by an error for every other macro that was expected to be defined in the header...)++ compiling dist/build/Text/Regex/PCRE/Light/Base_hsc_make.c failed (exit code 1)+ command was: /usr/bin/gcc -c dist/build/Text/Regex/PCRE/Light/Base_hsc_make.c -o dist/build/Text/Regex/PCRE/Light/Base_hsc_make.o -m64 -fno-stack-protector -m64 -fno-stack-protector -m64 -D__GLASGOW_HASKELL__=700 -Ddarwin_BUILD_OS -Ddarwin_HOST_OS -Dx86_64_BUILD_ARCH -Dx86_64_HOST_ARCH -I/sw/lib/ghc-7.0.4/bytestring-0.9.1.10/include -Idist/build/autogen -include dist/build/autogen/cabal_macros.h -I/sw/lib/ghc-7.0.4/base-4.3.1.0/include -Idist/build/autogen -include dist/build/autogen/cabal_macros.h -Idist/build/autogen -include dist/build/autogen/cabal_macros.h -Idist/build/autogen -include dist/build/autogen/cabal_macros.h -I/sw/lib/ghc-7.0.4/include -Idist/build/autogen -include dist/build/autogen/cabal_macros.h -I/sw/lib/ghc-7.0.4/include -Idist/build/autogen -include dist/build/autogen/cabal_macros.h -I/sw/lib/ghc-7.0.4/include/+ Failed to install pcre-light-0.4+ cabal: Error: some packages failed to install:+ git-annex-3.20120230 depends on pcre-light-0.4 which failed to install.+ pcre-light-0.4 failed during the building phase. The exception was:+ ExitFailure 1++This is a somewhat older Mac OS X 10.6.8 system.++I do have PCRE already installed via Fink, and pcre.h is in /sw/include. I see other -I/sw/... things in the compile command above, but obviously /sw/include is not one of them.++Any clues for me?++(Why the heck does git-annex need pcre in particular anyway??? I saw another regex library get installed earlier somewhere in this (massive) process.)++"""]]
+ doc/install/cabal/comment_30_ad639c07cb79e89406e95c1dafce3a01._comment view
@@ -0,0 +1,35 @@+[[!comment format=mdwn+ username="robohack"+ ip="24.67.98.78"+ subject="hmmm... ok, the PCRE problem was odd, but now this:"+ date="2013-11-21T20:30:54Z"+ content="""+The PCRE problem is solved trivially in my case with a couple more cabal install options, though the need for these seems oddly dissatisfying given the reams of other stuff that was successfully built and installed without these options.++Now however I seem to have encountered a deeper problem:++ $ cabal install git-annex --bindir=$HOME/bin --extra-include-dirs=/sw/include --extra-lib-dirs=/sw/lib + Resolving dependencies...+ [1 of 1] Compiling Main ( /var/folders/7h/7hWHR5m8HPKOnUEvQU7HU++++TI/-Tmp-/git-annex-3.20120230-84797/git-annex-3.20120230/Setup.hs, /var/folders/7h/7hWHR5m8HPKOnUEvQU7HU++++TI/-Tmp-/git-annex-3.20120230-84797/git-annex-3.20120230/dist/setup/Main.o )+ Linking /var/folders/7h/7hWHR5m8HPKOnUEvQU7HU++++TI/-Tmp-/git-annex-3.20120230-84797/git-annex-3.20120230/dist/setup/setup ...+ hsc2hs Utility/StatFS.hsc+ perl -i -pe 's/^{-# INCLUDE.*//' Utility/StatFS.hs+ ghc -O2 -Wall -ignore-package monads-fd --make configure+ + Utility/StatFS.hsc:54:8:+ Could not find module `GHC.Foreign':+ Use -v to see a list of the files searched for.+ make: *** [Build/SysConfig.hs] Error 1+ Configuring git-annex-3.20120230...+ Building git-annex-3.20120230...+ Preprocessing executable 'git-annex' for git-annex-3.20120230...+ + Git/Version.hs:11:18:+ Could not find module `Build.SysConfig':+ Use -v to see a list of the files searched for.+ Failed to install git-annex-3.20120230+ cabal: Error: some packages failed to install:+ git-annex-3.20120230 failed during the building phase. The exception was:+ ExitFailure 1++"""]]
+ doc/install/cabal/comment_31_4763b24a29627d55f465b9ea260ea7ec._comment view
@@ -0,0 +1,22 @@+[[!comment format=mdwn+ username="robohack"+ ip="24.67.98.78"+ subject="a different error trying to build from the git repo...."+ date="2013-11-21T21:14:54Z"+ content="""+I'm using the ghc7.0 branch because Fink's GHC is still at 7.0.4....++ $ cabal build + Building git-annex-3.20120523...+ Preprocessing executable 'git-annex' for git-annex-3.20120523...+ [ 78 of 163] Compiling Utility.Url ( Utility/Url.hs, dist/build/git-annex/git-annex-tmp/Utility/Url.o )+ + Utility/Url.hs:111:88:+ Couldn't match expected type `Maybe URI' with actual type `URI'+ In the second argument of `fromMaybe', namely+ `(newURI `relativeTo` u)'+ In the expression: fromMaybe newURI (newURI `relativeTo` u)+ In an equation for `newURI_abs':+ newURI_abs = fromMaybe newURI (newURI `relativeTo` u)++"""]]
+ doc/install/cabal/comment_32_1d34c294486c85b1149675fa5861ae35._comment view
@@ -0,0 +1,10 @@+[[!comment format=mdwn+ username="http://joeyh.name/"+ ip="209.250.56.64"+ subject="comment 32"+ date="2013-11-22T16:27:36Z"+ content="""+@robohack, the ghc7.0 branch is not being maintained, and is so old I don't recommend it. To build it against current cabal you will probably need to version its dependency on network to an older version than 2.4.0. ++Also, git-annex has not depended on pcre for a long time. But you're building thoroughly old version so get to trip over every bug that's been reported for the past 2 years..+"""]]
doc/internals.mdwn view
@@ -16,7 +16,7 @@ [[key-value_backends|backends]]. The file inside also has the name of the key. This two-level structure is used because it allows the write bit to be removed from the subdirectories as well as from the files. That prevents accidentially-deleting or changing the file contents. See [[permissions]] for details.+deleting or changing the file contents. See [[lockdown]] for details. In [[direct_mode]], file contents are not stored in here, and instead are stored directly in the file. However, the same symlinks are still
+ doc/news/2013_git-annex_user_survey.mdwn view
@@ -0,0 +1,5 @@+Similar to the yearly git user survey, I am doing a+[2013 git-annex user survey](http://git-annex-survey.branchable.com/polls/2013/).++If you use git-annex,+please take a few minutes to answer my questions!
− doc/news/version_4.20131024.mdwn
@@ -1,43 +0,0 @@-git-annex 4.20131024 released with [[!toggle text="these changes"]]-[[!toggleable text="""- * webapp: Fix bug when adding a remote and git-remote-gcrypt- is not installed.- * The assitant can now run scheduled incremental fsck jobs on the local- repository and remotes. These can be configured using vicfg or with the- webapp.- * repair: New command, which can repair damaged git repositories- (even ones not using git-annex).- * webapp: When git repository damange is detected, repairs can be- done using the webapp UI.- * Automatically and safely detect and recover from dangling- .git/annex/index.lock files, which would prevent git from- committing to the git-annex branch, eg after a crash.- * assistant: Detect stale git lock files at startup time, and remove them.- * addurl: Better sanitization of generated filenames.- * Better sanitization of problem characters when generating URL and WORM- keys.- * The control socket path passed to ssh needs to be 17 characters- shorter than the maximum unix domain socket length, because ssh- appends stuff to it to make a temporary filename. Closes: #[725512](http://bugs.debian.org/725512)- * status: Fix space leak in local mode, introduced in version 4.20130920.- * import: Skip .git directories.- * Remove bogus runshell loop check.- * addurl: Improve message when adding url with wrong size to existing file.- * Fixed handling of URL keys that have no recorded size.- * status: Fix a crash if a temp file went away while its size was- being checked for status.- * Deal with git check-attr -z output format change in git 1.8.5.- * Work around sed output difference that led to version containing a newline- on OSX.- * sync: Fix automatic resolution of merge conflicts where one side is an- annexed file, and the other side is a non-annexed file, or a directory.- * S3: Try to ensure bucket name is valid for archive.org.- * assistant: Bug fix: When run in a subdirectory, files from incoming merges- were wrongly added to that subdirectory, and removed from their original- locations.- * Windows: Deal with strange msysgit 1.8.4 behavior of not understanding- DOS formatted paths for --git-dir and --work-tree.- * Removed workaround for bug in git 1.8.4r0.- * Added git-recover-repository command to git-annex source- (not built by default; this needs to move to someplace else).- * webapp: Move sidebar to the right hand side of the screen."""]]
+ doc/news/version_5.20131127.mdwn view
@@ -0,0 +1,24 @@+git-annex 5.20131127 released with [[!toggle text="these changes"]]+[[!toggleable text="""+ * webapp: Detect when upgrades are available, and upgrade if the user+ desires.+ (Only when git-annex is installed using the prebuilt binaries+ from git-annex upstream, not from eg Debian.)+ * assistant: Detect when the git-annex binary is modified or replaced,+ and either prompt the user to restart the program, or automatically+ restart it.+ * annex.autoupgrade configures both the above upgrade behaviors.+ * Added support for quvi 0.9. Slightly suboptimal due to limitations in its+ interface compared with the old version.+ * Bug fix: annex.version did not get set on automatic upgrade to v5 direct+ mode repo, so the upgrade was performed repeatedly, slowing commands down.+ * webapp: Fix bug that broke switching between local repositories+ that use the new guarded direct mode.+ * Android: Fix stripping of the git-annex binary.+ * Android: Make terminal app show git-annex version number.+ * Android: Re-enable XMPP support.+ * reinject: Allow to be used in direct mode.+ * Futher improvements to git repo repair. Has now been tested in tens+ of thousands of intentionally damaged repos, and successfully+ repaired them all.+ * Allow use of --unused in bare repository."""]]
+ doc/special_remotes/comment_20_6b7242721f2f2c77b634568cb737e3e3._comment view
@@ -0,0 +1,13 @@+[[!comment format=mdwn+ username="https://www.google.com/accounts/o8/id?id=AItOawnWvnTWY6LrcPB4BzYEBn5mRTpNhg5EtEg"+ nickname="Bence"+ subject="Testing a special remote"+ date="2013-11-24T08:24:36Z"+ content="""+Is there a unit test or integration test to check for the behavior of a special remote implementation and/or validity?++I don't speak Haskell, so maybe there are some in the source but maybe I wouldn't recognize, so I haven't checked. If there are any tests how should I use it?++Thank you,+Bence+"""]]
+ doc/special_remotes/comment_21_5c11e69c28b9ed4cbe238a36c0839a47._comment view
@@ -0,0 +1,15 @@+[[!comment format=mdwn+ username="http://joeyh.name/"+ ip="209.250.56.64"+ subject="comment 21"+ date="2013-11-24T15:58:30Z"+ content="""+@Bence the closest I have is some tests of particular special remotes inside Test.hs. The shell equivilant of that code is:++[[!format sh \"\"\"+set -e+git annex copy file --to remote # tests store+git annex drop file # tests checkpresent when remote has file+git annex move file --from remote # tests retrieve and remove+\"\"\"]]+"""]]
doc/special_remotes/xmpp.mdwn view
@@ -24,7 +24,7 @@ ## XMPP server support status [[!table data=""" Provider|Status|Type|Notes-[[Gmail|http://gmail.com]]|Working|?|Google apps users will have to configure `.git/annex/creds/xmpp` manually+[[Gmail|http://gmail.com]]|Working|?|Google Apps: [setup your SRV records](http://www.olark.com/gtalk/check_srv) or configure `.git/annex/creds/xmpp` manually [[Coderollers|http://www.coderollers.com/xmpp-server/]]|Working|[[Openfire|http://www.igniterealtime.org/projects/openfire/]] [[jabber.me|http://jabber.me/]]|Working|[[Tigase|http://www.tigase.org/]] [[xmpp.ru.net|https://www.xmpp.ru.net]]|Working|[[jabberd2|http://jabberd2.org/]]
+ doc/special_remotes/xmpp/comment_9_eda76b826491c96b1ce072aacf9d3adf._comment view
@@ -0,0 +1,23 @@+[[!comment format=mdwn+ username="https://www.google.com/accounts/o8/id?id=AItOawlu-fdXIt_RF9ggvg4zP0yBbtjWQwHAMS4"+ nickname="Jörn"+ subject="Same problem, no XMPP showing up in daemon.log"+ date="2013-11-21T21:13:16Z"+ content="""+I have the same setup like @RaspberryPie, except that my server is not running on the Pi but on Debian7-amd64. On my client (OSX, self-compiled using cabal) I can see XMPP log entries like @RaspberryPi, however, on the Debian7 machine (also self-compiled) I do not see any XMPP entry in the daemon.log. Setup regarding .git/annex/creds/xmpp and the special xmpp remote is correct (checked a thousand times).++Do you have any idea what could be wrong, Joey? Thanks a lot.++Output of git annex version:++ git-annex version: 5.20131120+ build flags: Assistant Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS Feeds Quvi CryptoHash + key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL+ remote types: git gcrypt S3 bup directory rsync web webdav glacier hook+ local repository version: 4+ default repository version: 3+ supported repository versions: 3 5+ upgrade supported from repository versions: 0 1 2 4++Jörn+"""]]
+ doc/sync/comment_6_012e9d4468d0b88ee3c5dad3911c3606._comment view
@@ -0,0 +1,10 @@+[[!comment format=mdwn+ username="https://www.google.com/accounts/o8/id?id=AItOawkI9AR8BqG4RPw_Ov2lnDCJWMuM6WMRobQ"+ nickname="Dav"+ subject="Syncing only a specific branch"+ date="2013-11-24T17:48:22Z"+ content="""+By default, `git annex sync` will sync to all remotes, unless you specify a remote. So, I have to specify, e.g., `git annex sync origin`. I can simplify this with aliases, I suppose, but I do a lot of teaching non-programmer scientists... so it'd be nice to be able to configure this (so beginning users don't have to keep track of as many things).++Is there (or will there be) a way to do this?+"""]]
+ doc/sync/comment_7_6276e100d1341f1a0be368f54de0ae7b._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="http://joeyh.name/"+ ip="209.250.56.64"+ subject="comment 7"+ date="2013-11-26T20:08:33Z"+ content="""+I feel that syncing with all remotes by default is the right thing for git annex sync to do. +"""]]
+ doc/tips/Crude_Windows_Sync.mdwn view
@@ -0,0 +1,35 @@+Here's a workaround to start syncing folders on Windows right now. It's a bit command line heavy, so you might need to set this up for your users. But I would much rather do this than use some other syncing solution and then have to migrate.++(1) Create a remote server git annex repository with the assistant on Linux or Mac.++(2) [Install git](http://git-scm.com/) on the Windows machine.++(3) [Install git-annex for Windows](http://git-annex.branchable.com/install/Windows/) on the Windows machine. Don't forget to run the installer as administrator.++(4) Run _Git Bash_ from the system menu, and run these commands to clone your repository.++ ssh-keygen+ cat .ssh/id_rsa.pub | ssh username@my-server.com "cat >> ~/.ssh/authorized_keys"+ git clone username@my-server.com:/path/to/annex+ cd annex+ git annex init++(5) Create a script that will trigger a full sync++ echo '+ #!/bin/bash+ git annex sync+ git annex get *+ git annex add .+ git annex sync+ git annex copy * --to origin + ' > sync.sh+ chmod +x sync.sh+ ./sync.sh++(6) Copy the "Git Bash" shortcut from your windows menu to your desktop, and change the link target to:++ C:\Program Files\Git\bin\sh.exe" --login -i "annex/sync.sh"++Now ask your users to run this shortcut before and after they change files. You can also put it into the "autostart" folder to sync at boot.+
doc/todo/Check_if_an_upgrade_is_available_in_the_webapp.mdwn view
@@ -1,3 +1,5 @@ Especially on Mac OSX (and Windows, and maybe Android), it would be great to be able to check in the webapp if an upgrade is available. A deeper integration with these OS would be even better: for example on Mac OSX, an icon on the status bar list available upgrades for some programs, including LibreOffice and others which are not installed by default. Also, it would be great to be able to download and install git-annex upgrades directly from the webapp.++> comprehensively [[done]]; [[design/assistant/upgrading]] --[[Joey]]
+ doc/todo/Not_working_on_Android-x86.mdwn view
@@ -0,0 +1,19 @@+[[!meta title="Android is only autobuilt for arm, not x86 or mips"]]++### Please describe the problem.++git-annex doesn't start on [Android-x86](http://www.android-x86.org) in VirtualBox (version 4.1.18-dfsg-2+deb7u1).++On Android 4.2.2 (android-x86-4.2-20130228.iso) it starts the terminal which prints nothing but `[Terminal session finished]`.+On Android 4.3 (android-x86-4.3-20130725.iso) it starts the terminal and prints:++ In mgmain JNI_OnLoad+ + [Terminal session finished]++The browser/webapp is never started.++### What version of git-annex are you using? On what operating system?++Version 1.0.52 for Android. I made sure to install the correct APK files for each version of Android.+
doc/todo/checksum_verification_on_transfer.mdwn view
@@ -1,6 +1,6 @@ Since most file transfers, particularly to/from encrypted special remotes involve git-annex streaming through the contents of the file anyway, it should be possible to add a verification of the checksum nearly for free. The main thing needed is probably a faster haskell checksum library than Data.Digest.Pure.Sha, which is probably slow enough to be annoying. -I have not verified if an upload could be aborted before sending the data to the remote if a checksum failure is detected. It may be dependent on the individual special remote implementations. Some probably stream the encrypted data directly out the wire, while others need to set up a temp file to run a command on. It would certianly be possible to at least make the upload abort and fail if a bad checksum was detected.+I have not verified if an upload could be aborted before sending the data to the remote if a checksum failure is detected. It may be dependent on the individual special remote implementations. Some probably stream the encrypted data directly out the wire, while others need to set up a temp file to run a command on. It would certainly be possible to at least make the upload abort and fail if a bad checksum was detected. Doing the same for downloads is less useful, because the data is there locally to be fscked. The real advantage would be doing the check for uploads, to ensure that hard-to-detect corrupted files don't reach special remotes.
+ doc/todo/dumb_plaindir_remote___40__e.g._for_NAS_mounts__41__.mdwn view
@@ -0,0 +1,5 @@+I've an external USB hard disc attached to my (fritzbox) router that is only accessible through SMB/CIFS. I'd like have all my annexed files on this drive in kind of direct-mode so that I can also access the files without git-annex.++I tried to put a direct-mode repo on the drive but this is painfully slow. The git-annex process than runs on my desktop and accesses the repo over SMB over the slow fritzbox over USB.++I'd wish that git-annex could be told to just use a (mounted) folder as a direct-mode remote.
+ doc/todo/quvi_0.9_support.mdwn view
@@ -0,0 +1,8 @@+quvi 0.9 has a completely different interface; git-annex needs to be made+to detect and use it.++I have already fixed the worst problem, which caused git-annex addurl to+think that every url was a valid quvi url. --[[Joey]]++> [[done]], 0.9 is supported, although the version is detected at build+> time. --[[Joey]]
doc/todo/special_remote_for_amazon_glacier.mdwn view
@@ -3,7 +3,7 @@ The main difficulty is that glacier is organized into vaults, and accessing a file in a vault takes ~4 hours. A naive implementation would make `git-annex get` wait for 4 hours, which is certianly not reasonable.+annex get` wait for 4 hours, which is certainly not reasonable. One approach I am pondering is to make each glacier vault a separate special remote. You could then request git-annex to spin up a remote, and
doc/todo/wishlist:_make_git_annex_reinject_work_in_direct_mode.mdwn view
@@ -16,3 +16,6 @@ Release: 12.04 Codename: precise ~~~~++> [[fixed|done]]. Why did I take so long to do this, it was a trivial 1+> word change! --[[Joey]]
git-annex.1 view
@@ -499,7 +499,7 @@ to their local \fBgit\-annex\fP branches. So the forgetfulness will automatically propigate out from its starting point until all repositories running git\-annex have forgotten their old history. (You may need to force-git to push the branch to any git repositories not running git\-annex.+git to push the branch to any git repositories not running git\-annex.) .IP .IP "\fBrepair\fP" This can repair many of the problems with git repositories that \fBgit fsck\fP @@ -1030,6 +1030,20 @@ .IP "\fBannex.fscknudge\fP" When set to false, prevents the webapp from reminding you when using repositories that lack consistency checks.+.IP+.IP "\fBannex.autoupgrade\fP"+When set to ask (the default), the webapp will check for new versions+and prompt if they should be upgraded to. When set to true, automatically+upgrades without prompting (on some supported platforms). When set to+false, disables any upgrade checking.+.IP+Note that upgrade checking is only done when git\-annex is installed+from one of the prebuilt images from its website. This does not+bypass eg, a Linux distribution's own upgrade handling code.+.IP+This setting also controls whether to restart the git\-annex assistant+when the git\-annex binary is detected to have changed. That is useful+no matter how you installed git\-annex. .IP .IP "\fBannex.autocommit\fP" Set to false to prevent the git\-annex assistant from automatically
git-annex.cabal view
@@ -1,5 +1,5 @@ Name: git-annex-Version: 5.20131120+Version: 5.20131127 Cabal-Version: >= 1.8 License: GPL-3 Maintainer: Joey Hess <joey@kitenet.net>@@ -56,9 +56,13 @@ Description: Enable production build (slower build; faster binary) Flag Android- Description: Building for Android+ Description: Cross building for Android Default: False +Flag AndroidSplice+ Description: Building to get TH splices for Android+ Default: False+ Flag TestSuite Description: Embed the test suite into git-annex @@ -155,7 +159,9 @@ if flag(Android) Build-Depends: data-endian- CPP-Options: -D__ANDROID__+ CPP-Options: -D__ANDROID__ -DANDROID_SPLICES+ if flag(AndroidSplice)+ CPP-Options: -DANDROID_SPLICES if flag(Webapp) && (! os(windows)) Build-Depends:
standalone/android/Makefile view
@@ -15,6 +15,8 @@ GITTREE=$(GIT_ANNEX_ANDROID_SOURCETREE)/git/installed-tree +VER=$(shell perl -e '$$_=<>;print m/\((.*?)\)/'<../../CHANGELOG)+ build: start if [ ! -e "$(GIT_ANNEX_ANDROID_SOURCETREE)" ]; then $(MAKE) source; fi $(MAKE) $(GIT_ANNEX_ANDROID_SOURCETREE)/openssl/build-stamp@@ -25,6 +27,8 @@ $(MAKE) $(GIT_ANNEX_ANDROID_SOURCETREE)/git/build-stamp $(MAKE) $(GIT_ANNEX_ANDROID_SOURCETREE)/term/build-stamp + perl -i -pe 's/(android:versionName=)"[^"]+"/$$1"'$(VER)'"/' $(GIT_ANNEX_ANDROID_SOURCETREE)/term/AndroidManifest.xml+ # Debug build because it does not need signing keys. cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && tools/build-debug @@ -76,10 +80,12 @@ mkdir -p ../../tmp/4.0 ../../tmp/4.3 cp ../../tmp/androidtree/dist/build/git-annex/4.3/git-annex $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi/lib.git-annex.so+ arm-linux-androideabi-strip --strip-unneeded --remove-section=.comment --remove-section=.note $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi/lib.git-annex.so cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && ant debug cp $(GIT_ANNEX_ANDROID_SOURCETREE)/term/bin/Term-debug.apk ../../tmp/4.3/git-annex.apk- + cp ../../tmp/androidtree/dist/build/git-annex/4.0/git-annex $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi/lib.git-annex.so+ arm-linux-androideabi-strip --strip-unneeded --remove-section=.comment --remove-section=.note $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi/lib.git-annex.so cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && ant debug cp $(GIT_ANNEX_ANDROID_SOURCETREE)/term/bin/Term-debug.apk ../../tmp/4.0/git-annex.apk
standalone/windows/build.sh view
@@ -11,6 +11,8 @@ PATH="$HP/bin:$HP/lib/extralibs/bin:/c/Program Files (x86)/NSIS:$PATH" +UPGRADE_LOCATION=http://downloads.kitenet.net/git-annex/windows/current/git-annex-installer.exe+ # Run a command with the cygwin environment available. # However, programs not from cygwin are preferred. withcyg () {
static/longpolling.js view
@@ -1,11 +1,10 @@-// Updates a div with a specified id, by polling an url,-// which should return a new div, with the same id.- connfails=0; longpollcallbacks = $.Callbacks(); -function longpoll(url, divid, cont, fail) {+// Updates a div with a specified id, by polling an url,+// which should return a new div, with the same id.+function longpoll_div(url, divid, cont, fail) { $.ajax({ 'url': url, 'dataType': 'html',@@ -23,6 +22,21 @@ else { cont(); }+ }+ });+}++function longpoll_data(url, cont) {+ $.ajax({+ 'url': url,+ 'dataType': 'text',+ 'success': function(data, status, jqxhr) {+ connfails=0;+ cont(1, data);+ },+ 'error': function(jqxhr, msg, e) {+ connfails=connfails+1;+ cont(0); } }); }
templates/configurators/ssh/add.hamlet view
@@ -4,7 +4,7 @@ <p> You can use nearly any server that has ssh and rsync. For example, you # could use a <a href="http://linode.com/">Linode</a> or #- <a href="http://www.vix.com/personalcolo/">another VPS</a>, or #+ <a href="http://vix.su/personalcolo/">another VPS</a>, or # an account on a friend's server. <p> $case status
+ templates/configurators/upgrade/android.hamlet view
@@ -0,0 +1,9 @@+<div .span9 .hero-unit>+ <h2>+ Upgrading git-annex+ <p>+ To start the upgrade #+ <a .btn .btn-primary href="#{url}">+ Download #{takeFileName url}+ <p>+ Once the download is complete, open the file to upgrade git-annex.
+ templates/control/notrunning.hamlet view
@@ -0,0 +1,10 @@+<div .span9 .hero-unit>+ <p>+ Bye bye!+<div .modal .fade #shutdownmodal>+ <div .modal-header>+ <h3>+ git-annex has shut down+ <div .modal-body>+ <p>+ You can now close this browser window.
+ templates/control/notrunning.julius view
@@ -0,0 +1,3 @@+$(function() {+ $('#shutdownmodal').modal('show');+});
− templates/control/restarting.hamlet
@@ -1,2 +0,0 @@-<div .span9 .hero-unit>- Restarting...
− templates/control/shutdownconfirmed.hamlet
@@ -1,2 +0,0 @@-<div .span9 .hero-unit>- Shutting down...
templates/notifications/longpolling.julius view
@@ -1,7 +1,7 @@ $(function() { $.get("@{geturl}", function(url){ var f = function() {- longpoll(url, #{ident}+ longpoll_div(url, #{ident} , function() { setTimeout(f, #{delay}); } , function() { window.location.reload(true); } );
+ templates/page.julius view
@@ -0,0 +1,22 @@+$(function() {+ $.get("@{NotifierGlobalRedirR}", function(url){+ var f = function() {+ longpoll_data(url,+ function(ok, redirurl) {+ if (ok) {+ if (redirurl) {+ window.location = redirurl;+ }+ else {+ setTimeout(f, 10);+ }+ }+ else {+ setTimeout(f, 5000);+ }+ }+ );+ };+ setTimeout(f, 500);+ });+});
templates/sidebar/alert.hamlet view
@@ -19,7 +19,8 @@ #{l}<br> $else #{message}- $maybe button <- alertButton alert+ $if not (null buttons) <br>- <a .btn .btn-primary href="@{ClickAlert aid}">- #{buttonLabel button}+ $forall (button, bnum) <- buttons+ <a .btn :buttonPrimary button:.btn-primary :not (buttonPrimary button):.btn-success href="@{ClickAlert aid bnum}">+ #{buttonLabel button}