packages feed

git-annex 3.20120924 → 3.20121001

raw patch · 125 files changed

+1834/−487 lines, 125 filessetup-changedbinary-added

Files

Annex/UUID.hs view
@@ -36,12 +36,7 @@ 	where 		gen [] = error $ "no output from " ++ command 		gen (l:_) = toUUID l-		command = SysConfig.uuid-		params-			-- request a random uuid be generated-			| command == "uuid" = ["-m"]-			-- uuidgen generates random uuid by default-			| otherwise = []+		(command:params) = words SysConfig.uuid  {- Get current repository's UUID. -} getUUID :: Annex UUID
+ Assistant/Install.hs view
@@ -0,0 +1,71 @@+{- Assistant installation+ -+ - Copyright 2012 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++{-# LANGUAGE CPP #-}++module Assistant.Install where++import Assistant.Common+import Assistant.Install.AutoStart+import Assistant.Ssh+import Locations.UserConfig+import Utility.FileMode++#ifdef darwin_HOST_OS+import Utility.OSX+#else+import Utility.FreeDesktop+#endif++import System.Posix.Env++standaloneAppBase :: IO (Maybe FilePath)+standaloneAppBase = getEnv "GIT_ANNEX_APP_BASE"++{- The standalone app does not have an installation process.+ - So when it's run, it needs to set up autostarting of the assistant+ - daemon, as well as writing the programFile, and putting a+ - git-annex-shell wrapper into ~/.ssh+ -+ - Note that this is done every time it's started, so if the user moves+ - it around, the paths this sets up won't break.+ -}+ensureInstalled :: IO ()+ensureInstalled = go =<< standaloneAppBase+	where+		go Nothing = noop+		go (Just base) = do+			let program = base ++ "runshell git-annex"+			programfile <- programFile+			createDirectoryIfMissing True (parentDir programfile)+			writeFile programfile program++#ifdef darwin_HOST_OS+			autostartfile <- userAutoStart osxAutoStartLabel+#else+			autostartfile <- autoStartPath "git-annex"+				<$> userConfigDir+#endif+			installAutoStart program autostartfile++			{- This shim is only updated if it doesn't+			 - already exist with the right content. This+			 - ensures that there's no race where it would have+			 - worked, but is unavailable due to being updated. -}+			sshdir <- sshDir+			let shim = sshdir </> "git-annex-shell"+			let content = unlines+				[ "#!/bin/sh"+				, "set -e"+				, "exec", base </> "runshell" ++ +				  " git-annex-shell -c \"$SSH_ORIGINAL_COMMAND\""+				]+			curr <- catchDefaultIO "" $ readFileStrict shim+			when (curr /= content) $ do+				createDirectoryIfMissing True (parentDir shim)+				writeFile shim content+				modifyFileMode shim $ addModes [ownerExecuteMode]
+ Assistant/Install/AutoStart.hs view
@@ -0,0 +1,38 @@+{- Assistant autostart file installation+ -+ - Copyright 2012 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++{-# LANGUAGE CPP #-}++module Assistant.Install.AutoStart where++import Utility.FreeDesktop+#ifdef darwin_HOST_OS+import Utility.OSX+import Utility.Path+import System.Directory+#endif++installAutoStart :: FilePath -> FilePath -> IO ()+installAutoStart command file = do+#ifdef darwin_HOST_OS+	createDirectoryIfMissing True (parentDir file)+	writeFile file $ genOSXAutoStartFile osxAutoStartLabel command+		["assistant", "--autostart"]+#else+	writeDesktopMenuFile (fdoAutostart command) file+#endif++osxAutoStartLabel :: String+osxAutoStartLabel = "com.branchable.git-annex.assistant"++fdoAutostart :: FilePath -> DesktopEntry+fdoAutostart command = genDesktopEntry+	"Git Annex Assistant"+	"Autostart"+	False+	(command ++ " assistant --autostart")+	[]
Assistant/MakeRemote.hs view
@@ -25,6 +25,7 @@  import qualified Data.Text as T import qualified Data.Map as M+import Data.Char  {- Sets up and begins syncing with a new ssh or rsync remote. -} makeSshRemote :: ThreadState -> DaemonStatusHandle -> ScanRemoteMap -> Bool -> SshData -> IO ()@@ -55,13 +56,10 @@ 	void remoteListRefresh 	maybe (error "failed to add remote") return =<< Remote.byName (Just name) -{- Inits a rsync special remote, and returns the name of the remote. -}+{- Inits a rsync special remote, and returns its name. -} makeRsyncRemote :: String -> String -> Annex String-makeRsyncRemote name location = makeRemote name location $ const $ do-	(u, c) <- Command.InitRemote.findByName name-	c' <- R.setup Rsync.remote u $ M.union config c-	describeUUID u name-	configSet u c'+makeRsyncRemote name location = makeRemote name location $+	const $ makeSpecialRemote name Rsync.remote config 	where 		config = M.fromList 			[ ("encryption", "shared")@@ -69,6 +67,14 @@ 			, ("type", "rsync") 			] +{- Inits a special remote. -}+makeSpecialRemote :: String -> RemoteType -> R.RemoteConfig -> Annex ()+makeSpecialRemote name remotetype config = do+	(u, c) <- Command.InitRemote.findByName name+	c' <- R.setup remotetype u $ M.union config c+	describeUUID u name+	configSet u c'+ {- Returns the name of the git remote it created. If there's already a  - remote at the location, returns its name. -} makeGitRemote :: String -> String -> Annex String@@ -86,7 +92,7 @@ 	r <- fromRepo id 	if not (any samelocation $ Git.remotes r) 		then do-			let name = uniqueRemoteName r basename 0+			let name = uniqueRemoteName basename 0 r 			a name 			return name 		else return basename@@ -94,14 +100,19 @@ 		samelocation x = Git.repoLocation x == location  {- Generate an unused name for a remote, adding a number if- - necessary. -}-uniqueRemoteName :: Git.Repo -> String -> Int -> String-uniqueRemoteName r basename n+ - necessary.+ -+ - Ensures that the returned name is a legal git remote name. -}+uniqueRemoteName :: String -> Int -> Git.Repo -> String+uniqueRemoteName basename n r 	| null namecollision = name-	| otherwise = uniqueRemoteName r basename (succ n)+	| otherwise = uniqueRemoteName legalbasename (succ n) r 	where 		namecollision = filter samename (Git.remotes r) 		samename x = Git.remoteName x == Just name 		name-			| n == 0 = basename-			| otherwise = basename ++ show n+			| n == 0 = legalbasename+			| otherwise = legalbasename ++ show n+		legalbasename = filter legal basename+		legal '_' = True+		legal c = isAlphaNum c
Assistant/Ssh.hs view
@@ -119,10 +119,20 @@ 	writeFile keyfile $ unlines $ filter (/= keyline) ls  {- Implemented as a shell command, so it can be run on remote servers over- - ssh. -}+ - ssh.+ -+ - The ~/.ssh/git-annex-shell wrapper script is created if not already+ - present.+ -} addAuthorizedKeysCommand :: Bool -> SshPubKey -> String addAuthorizedKeysCommand rsynconly pubkey = join "&&" 	[ "mkdir -p ~/.ssh"+	, join "; "+		[ "if [ ! -e " ++ wrapper ++ " ]"+		, "then (" ++ join ";" (map echoval script) ++ ") > " ++ wrapper+		, "fi"+		]+	, "chmod 700 " ++ wrapper 	, "touch ~/.ssh/authorized_keys" 	, "chmod 600 ~/.ssh/authorized_keys" 	, unwords@@ -131,15 +141,23 @@ 		, ">>~/.ssh/authorized_keys" 		] 	]+	where+		echoval v = "echo " ++ shellEscape v+		wrapper = "~/.ssh/git-annex-shell"+		script =+			[ "#!/bin/sh"+			, "set -e"+			, "exec git-annex-shell -c \"$SSH_ORIGINAL_COMMAND\""+			]  authorizedKeysLine :: Bool -> SshPubKey -> String authorizedKeysLine rsynconly pubkey 	{- TODO: Locking down rsync is difficult, requiring a rather 	 - long perl script. -} 	| rsynconly = pubkey-	| otherwise = limitcommand "git-annex-shell -c" ++ pubkey+	| otherwise = limitcommand ++ pubkey 	where-		limitcommand c = "command=\"perl -e 'exec qw(" ++ c ++ "), $ENV{SSH_ORIGINAL_COMMAND}'\",no-agent-forwarding,no-port-forwarding,no-X11-forwarding "+		limitcommand = "command=\"~/.ssh/git-annex-shell\",no-agent-forwarding,no-port-forwarding,no-X11-forwarding "  {- Generates a ssh key pair. -} genSshKeyPair :: IO SshKeyPair@@ -205,6 +223,10 @@ knownHost hostname = do 	sshdir <- sshDir 	ifM (doesFileExist $ sshdir </> "known_hosts")-		( not . null <$> readProcess "ssh-keygen" ["-F", T.unpack hostname]+		( not . null <$> checkhost 		, return False 		)+	where+		{- ssh-keygen -F can crash on some old known_hosts file -}+		checkhost = catchDefaultIO "" $+			readProcess "ssh-keygen" ["-F", T.unpack hostname]
Assistant/Threads/Committer.hs view
@@ -205,15 +205,6 @@ 			openfiles <- S.fromList . map fst3 . filter openwrite <$> 				liftIO (Lsof.queryDir tmpdir) -			-- TODO this is here for debugging a problem on-			-- OSX, and is pretty expensive, so remove later-			liftIO $ debug thisThread-				[ "checking changes:"-				, show changes-				, "vs open files:"-				, show openfiles-				]-			 			let checked = map (check openfiles) changes  			{- If new events are received when files are closed,
Assistant/Threads/MountWatcher.hs view
@@ -22,8 +22,6 @@ import Remote.List import qualified Types.Remote as Remote -import Control.Concurrent-import qualified Control.Exception as E import qualified Data.Set as S  #if WITH_DBUS@@ -31,6 +29,8 @@ import DBus.Client import DBus import Data.Word (Word32)+import Control.Concurrent+import qualified Control.Exception as E #else #warning Building without dbus support; will use mtab polling #endif
Assistant/Threads/NetWatcher.hs view
@@ -19,13 +19,12 @@ import Remote.List import qualified Types.Remote as Remote -import qualified Control.Exception as E- #if WITH_DBUS import Utility.DBus import DBus.Client import DBus import Data.Word (Word32)+import qualified Control.Exception as E #else #warning Building without dbus support; will poll for network connection changes #endif@@ -34,11 +33,11 @@ thisThread = "NetWatcher"  netWatcherThread :: ThreadState -> DaemonStatusHandle -> ScanRemoteMap -> NamedThread-netWatcherThread st dstatus scanremotes = thread $ #if WITH_DBUS+netWatcherThread st dstatus scanremotes = thread $ 	dbusThread st dstatus scanremotes #else-	noop+netWatcherThread _ _ _ = thread noop #endif 	where 		thread = NamedThread thisThread
Assistant/Threads/WebApp.hs view
@@ -20,6 +20,7 @@ import Assistant.WebApp.Configurators.Local import Assistant.WebApp.Configurators.Ssh import Assistant.WebApp.Configurators.Pairing+import Assistant.WebApp.Configurators.S3 import Assistant.WebApp.Documentation import Assistant.WebApp.OtherRepos import Assistant.ThreadedMonad
Assistant/WebApp.hs view
@@ -114,13 +114,13 @@ 	webapp <- lift getYesod 	[whamlet|<input type="hidden" name="auth" value="#{secretToken webapp}">|] -{- A button with an icon, and maybe label, that can be clicked to perform- - some action.+{- A button with an icon, and maybe label or tooltip, that can be+ - clicked to perform some action.  - With javascript, clicking it POSTs the Route, and remains on the same  - page.  - With noscript, clicking it GETs the Route. -}-actionButton :: Route WebApp -> (Maybe String) -> String -> String -> Widget-actionButton route label buttonclass iconclass = $(widgetFile "actionbutton")+actionButton :: Route WebApp -> (Maybe String) -> (Maybe String) -> String -> String -> Widget+actionButton route label tooltip buttonclass iconclass = $(widgetFile "actionbutton")  type UrlRenderFunc = Route WebApp -> [(Text, Text)] -> Text type UrlRenderer = MVar (UrlRenderFunc)
Assistant/WebApp/Configurators.hs view
@@ -65,6 +65,7 @@ 			Just c -> case M.lookup "type" c of 				Just "rsync" -> u `enableswith` EnableRsyncR 				Just "directory" -> u `enableswith` EnableDirectoryR+				Just "S3" -> u `enableswith` EnableS3R 				_ -> Nothing 		u `enableswith` r = Just (u, Just $ r u) 		list l = runAnnex [] $ do
Assistant/WebApp/Configurators/Local.hs view
@@ -90,19 +90,22 @@ {- On first run, if run in the home directory, default to putting it in  - ~/Desktop/annex, when a Desktop directory exists, and ~/annex otherwise.  -- - If run in another directory, the user probably wants to put it there. -}+ - If run in another directory, that the user can write to,+ - the user probably wants to put it there. -} defaultRepositoryPath :: Bool -> IO FilePath defaultRepositoryPath firstrun = do 	cwd <- liftIO $ getCurrentDirectory 	home <- myHomeDir 	if home == cwd && firstrun-		then do+		then inhome+		else ifM (canWrite cwd) ( return cwd, inhome )+	where+		inhome = do 			desktop <- userDesktopDir 			ifM (doesDirectoryExist desktop) 				( relHome $ desktop </> gitAnnexAssistantDefaultDir 				, return $ "~" </> gitAnnexAssistantDefaultDir 				)-		else return cwd  newRepositoryForm :: FilePath -> Form RepositoryPath newRepositoryForm defpath msg = do
+ Assistant/WebApp/Configurators/S3.hs view
@@ -0,0 +1,124 @@+{- git-annex assistant webapp configurator for Amazon S3+ -+ - Copyright 2012 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU AGPL version 3 or higher.+ -}++{-# LANGUAGE TypeFamilies, QuasiQuotes, MultiParamTypeClasses, TemplateHaskell, OverloadedStrings, RankNTypes #-}++module Assistant.WebApp.Configurators.S3 where++import Assistant.Common+import Assistant.MakeRemote+import Assistant.Sync+import Assistant.WebApp+import Assistant.WebApp.Types+import Assistant.WebApp.SideBar+import Assistant.ThreadedMonad+import Utility.Yesod+import qualified Remote.S3 as S3+import Logs.Remote+import Remote (prettyListUUIDs)+import Types.Remote (RemoteConfig)++import Yesod+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Map as M++s3Configurator :: Widget -> Handler RepHtml+s3Configurator a = bootstrap (Just Config) $ do+	sideBarDisplay+	setTitle "Add an Amazon S3 repository"+	a++data StorageClass = StandardRedundancy | ReducedRedundancy+	deriving (Eq, Enum, Bounded)++instance Show StorageClass where+	show StandardRedundancy = "STANDARD" +	show ReducedRedundancy = "REDUCED_REDUNDANCY"++data S3Input = S3Input+	{ accessKeyID :: Text+	, secretAccessKey :: Text+	-- Free form text for datacenter because Amazon adds new ones.+	, datacenter :: Text+	, storageClass :: StorageClass+	, repoName :: Text+	}++data S3Creds = S3Creds Text Text++extractCreds :: S3Input -> S3Creds+extractCreds i = S3Creds (accessKeyID i) (secretAccessKey i)++s3InputAForm :: AForm WebApp WebApp S3Input+s3InputAForm = S3Input+	<$> areq textField "Access Key ID" Nothing+	<*> areq passwordField "Secret Access Key" Nothing+	<*> areq textField "Datacenter" (Just "US")+	<*> areq (selectFieldList storageclasses) "Storage class" (Just StandardRedundancy)+	<*> areq textField "Repository name" (Just "S3")+	where+		storageclasses :: [(Text, StorageClass)]+		storageclasses =+			[ ("Standard redundancy", StandardRedundancy)+			, ("Reduced redundancy (costs less)", ReducedRedundancy)+			]++s3CredsAForm :: AForm WebApp WebApp S3Creds+s3CredsAForm = S3Creds+	<$> areq textField "Access Key ID" Nothing+	<*> areq passwordField "Secret Access Key" Nothing++getAddS3R :: Handler RepHtml+getAddS3R = s3Configurator $ do+	((result, form), enctype) <- lift $+		runFormGet $ renderBootstrap s3InputAForm+	case result of+		FormSuccess s3input -> lift $ do+			let name = T.unpack $ repoName s3input+			makeS3Remote (extractCreds s3input) name $ M.fromList+				[ ("encryption", "shared")+				, ("type", "S3")+				, ("datacenter", T.unpack $ datacenter s3input)+				, ("storageclass", show $ storageClass s3input)+				]+		_ -> showform form enctype+	where+		showform form enctype = do+			let authtoken = webAppFormAuthToken+			$(widgetFile "configurators/adds3")++getEnableS3R :: UUID -> Handler RepHtml+getEnableS3R uuid = s3Configurator $ do+	((result, form), enctype) <- lift $+		runFormGet $ renderBootstrap s3CredsAForm+	case result of+		FormSuccess s3creds -> lift $ do+			m <- runAnnex M.empty readRemoteLog+			let name = fromJust $ M.lookup "name" $+				fromJust $ M.lookup uuid m+			makeS3Remote s3creds name M.empty+		_ -> showform form enctype+	where+		showform form enctype = do+			let authtoken = webAppFormAuthToken+			description <- lift $ runAnnex "" $+				T.pack . concat <$> prettyListUUIDs [uuid]+			$(widgetFile "configurators/enables3")++makeS3Remote :: S3Creds -> String -> RemoteConfig -> Handler ()+makeS3Remote (S3Creds ak sk) name config = do+	webapp <- getYesod+	let st = fromJust $ threadState webapp+	remotename <- runAnnex name $ fromRepo $ uniqueRemoteName name 0+	liftIO $ do+		S3.s3SetCredsEnv ( T.unpack ak, T.unpack sk)+		r <- runThreadState st $ addRemote $ do+			makeSpecialRemote name S3.remote config+			return remotename+		syncNewRemote st (daemonStatus webapp) (scanRemotes webapp) r+	redirect RepositoriesR
Assistant/WebApp/Configurators/Ssh.hs view
@@ -24,7 +24,7 @@ import Data.Text (Text) import qualified Data.Text as T import qualified Data.Map as M-import Network.BSD+import Network.Socket import System.Posix.User  sshConfigurator :: Widget -> Handler RepHtml@@ -63,13 +63,15 @@ 		check_hostname = checkM (liftIO . checkdns) textField 		checkdns t = do 			let h = T.unpack t-			r <- catchMaybeIO $ getHostByName h-			return $ case r of+			r <- catchMaybeIO $ getAddrInfo canonname (Just h) Nothing+			return $ case catMaybes . map addrCanonName <$> r of 				-- canonicalize input hostname if it had no dot-				Just hostentry+				Just (fullname:_) 					| '.' `elem` h -> Right t-					| otherwise -> Right $ T.pack $ hostName hostentry+					| otherwise -> Right $ T.pack fullname+				Just [] -> Right t 				Nothing -> Left bad_hostname+		canonname = Just $ defaultHints { addrFlags = [AI_CANONNAME] }  		check_username = checkBool (all (`notElem` "/:@ \t") . T.unpack) 			bad_username textField@@ -175,7 +177,8 @@  - a special ssh key will need to be generated just for this server.  -  - Once logged into the server, probe to see if git-annex-shell is- - available, or rsync.+ - available, or rsync. Note that on OSX, ~/.ssh/git-annex-shell may be+ - present, while git-annex-shell is not in PATH.  -} testServer :: SshInput -> IO (Either ServerStatus SshData) testServer (SshInput { hostname = Nothing }) = return $@@ -200,6 +203,7 @@ 				[ report "loggedin" 				, checkcommand "git-annex-shell" 				, checkcommand "rsync"+				, checkcommand osx_shim 				] 			knownhost <- knownHost hn 			let sshopts = filter (not . null) $ extraopts ++@@ -214,6 +218,7 @@ 			parsetranscript . fst <$> sshTranscript sshopts "" 		parsetranscript s 			| reported "git-annex-shell" = UsableSshInput+			| reported osx_shim = UsableSshInput 			| reported "rsync" = UsableRsyncServer 			| reported "loggedin" = UnusableServer 				"Neither rsync nor git-annex are installed on the server. Perhaps you should go install them?"@@ -224,6 +229,7 @@ 		checkcommand c = "if which " ++ c ++ "; then " ++ report c ++ "; fi" 		token r = "git-annex-probe " ++ r 		report r = "echo " ++ token r+		osx_shim = "~/.ssh/git-annex-shell"  {- Runs a ssh command; if it fails shows the user the transcript,  - and if it succeeds, runs an action. -}
Assistant/WebApp/DashBoard.hs view
@@ -44,7 +44,6 @@ 	webapp <- lift getYesod 	current <- lift $ M.toList <$> getCurrentTransfers 	queued <- liftIO $ getTransferQueue $ transferQueue webapp-	let ident = "transfers" 	autoUpdate ident NotifierTransfersR (10 :: Int) (10 :: Int) 	let transfers = simplifyTransfers $ current ++ queued 	if null transfers@@ -54,6 +53,7 @@ 			) 		else $(widgetFile "dashboard/transfers") 	where+		ident = "transfers" 		isrunning info = not $ 			transferPaused info || isNothing (startedTime info) @@ -142,7 +142,7 @@ 			return False 		) 	where-#if OSX+#ifdef darwin_HOST_OS 		cmd = "open" #else 		cmd = "xdg-open"
Assistant/WebApp/Documentation.hs view
@@ -9,15 +9,37 @@  module Assistant.WebApp.Documentation where +import Assistant.Common import Assistant.WebApp import Assistant.WebApp.Types import Assistant.WebApp.SideBar+import Assistant.Install (standaloneAppBase) import Utility.Yesod+import Build.SysConfig (packageversion)  import Yesod +{- The full license info may be included in a file on disk that can+ - be read in and displayed. -}+licenseFile :: IO (Maybe FilePath)+licenseFile = do+	base <- standaloneAppBase+	return $ (</> "LICENSE") <$> base+ getAboutR :: Handler RepHtml getAboutR = bootstrap (Just About) $ do 	sideBarDisplay 	setTitle "About git-annex"+	builtinlicense <- isJust <$> liftIO licenseFile 	$(widgetFile "documentation/about")++getLicenseR :: Handler RepHtml+getLicenseR = do+	v <- liftIO licenseFile+	case v of+		Nothing -> redirect AboutR+		Just f -> bootstrap (Just About) $ do+			-- no sidebar, just pages of legalese..+			setTitle "License"+			license <- liftIO $ readFile f+			$(widgetFile "documentation/license")
Assistant/WebApp/Types.hs view
@@ -28,7 +28,7 @@ import Data.Text (Text, pack, unpack) import Control.Concurrent.STM -staticFiles "static"+publicFiles "static"  mkYesodData "WebApp" $(parseRoutesFile "Assistant/WebApp/routes") 
Assistant/WebApp/routes view
@@ -2,6 +2,7 @@ /noscript NoScriptR GET /noscript/auto NoScriptAutoR GET /about AboutR GET+/about/license LicenseR GET  /config ConfigR GET /config/repository RepositoriesR GET@@ -15,7 +16,8 @@ /config/repository/add/ssh/confirm/#SshData ConfirmSshR GET /config/repository/add/ssh/make/git/#SshData MakeSshGitR GET /config/repository/add/ssh/make/rsync/#SshData MakeSshRsyncR GET-/config/repository/add/rsync.net AddRsyncNetR GET+/config/repository/add/cloud/rsync.net AddRsyncNetR GET+/config/repository/add/cloud/S3 AddS3R GET  /config/repository/pair/start StartPairR GET /config/repository/pair/inprogress/#SecretReminder InprogressPairR GET@@ -23,6 +25,7 @@  /config/repository/enable/rsync/#UUID EnableRsyncR GET /config/repository/enable/directory/#UUID EnableDirectoryR GET+/config/repository/enable/S3/#UUID EnableS3R GET  /transfers/#NotificationId TransfersR GET /sidebar/#NotificationId SideBarR GET
Build/Configure.hs view
@@ -19,7 +19,7 @@ 	, testCp "cp_a" "-a" 	, testCp "cp_p" "-p" 	, testCp "cp_reflink_auto" "--reflink=auto"-	, TestCase "uuid generator" $ selectCmd "uuid" ["uuid", "uuidgen"] ""+	, TestCase "uuid generator" $ selectCmd "uuid" ["uuid -m", "uuid", "uuidgen"] "" 	, TestCase "xargs -0" $ requireCmd "xargs_0" "xargs -0 </dev/null" 	, TestCase "rsync" $ requireCmd "rsync" "rsync --version >/dev/null" 	, TestCase "curl" $ testCmd "curl" "curl --version >/dev/null"
Build/InstallDesktopFile.hs view
@@ -15,15 +15,16 @@ import Utility.Path import Utility.Monad import Locations.UserConfig+import Utility.OSX+import Assistant.Install.AutoStart  import Control.Applicative-import Control.Monad import System.Directory import System.Environment import System.Posix.User-import System.Posix.Types import System.Posix.Files import System.FilePath+import Data.Maybe  {- The command can be either just "git-annex", or the full path to use  - to run it. -}@@ -43,49 +44,42 @@ 	(command ++ " assistant --autostart") 	[] -isRoot :: IO Bool-isRoot = do-	uid <- fromIntegral <$> getRealUserID-	return $ uid == 0+systemwideInstall :: IO Bool+systemwideInstall = isroot <||> destdirset+	where+		isroot = do+			uid <- fromIntegral <$> getRealUserID+			return $ uid == (0 :: Int)+		destdirset = isJust <$> catchMaybeIO (getEnv "DESTDIR")  inDestDir :: FilePath -> IO FilePath inDestDir f = do 	destdir <- catchDefaultIO "" (getEnv "DESTDIR")-	return $ destdir </> f+	return $ destdir ++ "/" ++ f  writeFDODesktop :: FilePath -> IO () writeFDODesktop command = do-	datadir <- ifM isRoot ( return systemDataDir, userDataDir )+	datadir <- ifM systemwideInstall ( return systemDataDir, userDataDir ) 	writeDesktopMenuFile (desktop command)  		=<< inDestDir (desktopMenuFilePath "git-annex" datadir) -	configdir <- ifM isRoot ( return systemConfigDir, userConfigDir )-	writeDesktopMenuFile (autostart command) +	configdir <- ifM systemwideInstall ( return systemConfigDir, userConfigDir )+	installAutoStart command  		=<< inDestDir (autoStartPath "git-annex" configdir) -	ifM isRoot-		( return ()-		, do-			programfile <- inDestDir =<< programFile-			createDirectoryIfMissing True (parentDir programfile)-			writeFile programfile command-		)- writeOSXDesktop :: FilePath -> IO () writeOSXDesktop command = do-	home <- myHomeDir--	let base = "Library" </> "LaunchAgents" </> label ++ ".plist"-	autostart <- ifM isRoot ( inDestDir $ "/" </> base , inDestDir $ home </> base)-	createDirectoryIfMissing True (parentDir autostart)-	writeFile autostart $ genOSXAutoStartFile label command+	installAutoStart command =<< inDestDir =<< ifM systemwideInstall+		( return $ systemAutoStart osxAutoStartLabel+		, userAutoStart osxAutoStartLabel+		) +	{- Install the OSX app in non-self-contained mode. -} 	let appdir = "git-annex.app" 	installOSXAppFile appdir "Contents/Info.plist" Nothing 	installOSXAppFile appdir "Contents/Resources/git-annex.icns" Nothing-	installOSXAppFile appdir "Contents/MacOS/git-annex" (Just webappscript)+	installOSXAppFile appdir "Contents/MacOS/git-annex-webapp" (Just webappscript) 	where-		label = "com.branchable.git-annex.assistant" 		webappscript = unlines 			[ "#!/bin/sh" 			, command ++ " webapp"@@ -93,9 +87,9 @@  installOSXAppFile :: FilePath -> FilePath -> Maybe String -> IO () installOSXAppFile appdir appfile mcontent = do-	let src = "ui-macos" </> appdir </> appfile+	let src = "standalone" </> "macos" </> appdir </> appfile 	home <- myHomeDir-	dest <- ifM isRoot+	dest <- ifM systemwideInstall 		( return $ "/Applications" </> appdir </> appfile 		, return $ home </> "Desktop" </> appdir </> appfile 		)@@ -106,33 +100,23 @@ 	mode <- fileMode <$> getFileStatus src 	setFileMode dest mode -genOSXAutoStartFile :: String -> String -> String-genOSXAutoStartFile label command = unlines-	[ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"-	, "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"-	, "<plist version=\"1.0\">"-	, "<dict>"-	, "<key>Label</key>"-	, "<string>" ++ label ++ "</string>"-	, "<key>ProgramArguments</key>"-	, "<array>"-	, "<string>" ++ command ++ "</string>"-	, "<string>assistant</string>"-	, "<string>--autostart</string>"-	, "</array>"-	, "<key>RunAtLoad</key>"-	, "</dict>"-	, "</plist>"-	]--writeDesktop :: FilePath -> IO ()+install :: FilePath -> IO ()+install command = do #ifdef darwin_HOST_OS-writeDesktop = writeOSXDesktop+	writeOSXDesktop command #else-writeDesktop = writeFDODesktop+	writeFDODesktop command #endif+	ifM systemwideInstall+		( return ()+		, do+			programfile <- inDestDir =<< programFile+			createDirectoryIfMissing True (parentDir programfile)+			writeFile programfile command+		) +main :: IO () main = getArgs >>= go 	where 		go [] = error "specify git-annex command"-		go (command:_) = writeDesktop command+		go (command:_) = install command
CHANGELOG view
@@ -1,3 +1,33 @@+git-annex (3.20121001) unstable; urgency=low++  * fsck: Now has an incremental mode. Start a new incremental fsck pass+    with git annex fsck --incremental. Now the fsck can be interrupted+    as desired, and resumed with git annex fsck --more.+    Thanks, Justin Azoff+  * New --time-limit option, makes long git-annex commands stop after+    a specified amount of time.+  * fsck: New --incremental-schedule option which is nice for scheduling+    eg, monthly incremental fsck runs in cron jobs.+  * Fix fallback to ~/Desktop when xdg-user-dir is not available.+    Closes: #688833+  * S3: When using a shared cipher, S3 credentials are not stored encrypted+    in the git repository, as that would allow anyone with access to+    the repository access to the S3 account. Instead, they're stored+    in a 600 mode file in the local git repo.+  * webapp: Avoid crashing when ssh-keygen -F chokes on an invalid known_hosts+    file.+  * Always do a system wide installation when DESTDIR is set. Closes: #689052+  * The Makefile now builds with the new yesod by default.+    Systems like Debian that have the old yesod 1.0.1 should set+    GIT_ANNEX_LOCAL_FEATURES=-DWITH_OLD_YESOD+  * copy: Avoid updating the location log when no copy is performed.+  * configure: Test that uuid -m works, falling back to plain uuid if not.+  * Avoid building the webapp on Debian architectures that do not yet+    have template haskell and thus yesod. (Should be available for arm soonish+    I hope).++ -- Joey Hess <joeyh@debian.org>  Mon, 01 Oct 2012 13:56:55 -0400+ git-annex (3.20120924) unstable; urgency=low    * assistant: New command, a daemon which does everything watch does,@@ -23,7 +53,7 @@     files and reading from checksum commands.   * sync: Pushes the git-annex branch to remote/synced/git-annex, rather     than directly to remote/git-annex.-  * Now supports matchig files that are present on a number of remotes+  * Now supports matching files that are present on a number of remotes     with a specified trust level. Example: --copies=trusted:2     Thanks, Nicolas Pouillard 
@@ -9,7 +9,7 @@ Copyright: © 2012 Joey Hess <joey@kitenet.net> License: AGPL-3+ -Files: doc/logo* */favicon.ico ui-macos/git-annex.app/Contents/Resources/git-annex.icns+Files: doc/logo* */favicon.ico standalone/osx/git-annex.app/Contents/Resources/git-annex.icns Copyright: 2007 Henrik Nyh <http://henrik.nyh.se/>            2010 Joey Hess <joey@kitenet.net> License: other
Command/Fsck.hs view
@@ -7,8 +7,6 @@  module Command.Fsck where -import System.Posix.Process (getProcessID)- import Common.Annex import Command import qualified Annex@@ -27,7 +25,14 @@ import Config import qualified Option import Types.Key+import Utility.HumanTime +import System.Posix.Process (getProcessID)+import Data.Time.Clock.POSIX+import Data.Time+import System.Posix.Types (EpochTime)+import System.Locale+ def :: [Command] def = [withOptions options $ command "fsck" paramPaths seek 	"check for problems"]@@ -35,25 +40,71 @@ fromOption :: Option fromOption = Option.field ['f'] "from" paramRemote "check remote" +startIncrementalOption :: Option+startIncrementalOption = Option.flag ['S'] "incremental" "start an incremental fsck"++moreIncrementalOption :: Option+moreIncrementalOption = Option.flag ['m'] "more" "continue an incremental fsck"++incrementalScheduleOption :: Option+incrementalScheduleOption = Option.field [] "incremental-schedule" paramTime+	"schedule incremental fscking"+ options :: [Option]-options = [fromOption]+options = +	[ fromOption+	, startIncrementalOption+	, moreIncrementalOption+	, incrementalScheduleOption+	]  seek :: [CommandSeek] seek = 	[ withField fromOption Remote.byName $ \from ->-		withFilesInGit $ whenAnnexed $ start from-	, withBarePresentKeys startBare+	  withIncremental $ \i -> withFilesInGit $ whenAnnexed $ start from i+	, withIncremental $ \i -> withBarePresentKeys $ startBare i 	] -start :: Maybe Remote -> FilePath -> (Key, Backend) -> CommandStart-start from file (key, backend) = do+withIncremental :: (Incremental -> CommandSeek) -> CommandSeek+withIncremental = withValue $ do+	i <- maybe (return False) (checkschedule . parseDuration)+		=<< Annex.getField (Option.name incrementalScheduleOption)+	starti <- Annex.getFlag (Option.name startIncrementalOption)+	morei <- Annex.getFlag (Option.name moreIncrementalOption)+	case (i, starti, morei) of+		(False, False, False) -> return NonIncremental+		(False, True, _) -> startIncremental+		(False ,False, True) -> ContIncremental <$> getStartTime+		(True, _, _) ->+			maybe startIncremental (return . ContIncremental . Just)+				=<< getStartTime+	where+		startIncremental = do+			recordStartTime+			return StartIncremental++		checkschedule Nothing = error "bad --incremental-schedule value"+		checkschedule (Just delta) = do+			Annex.addCleanup "" $ do+				v <- getStartTime+				case v of+					Nothing -> noop+					Just started -> do+						now <- liftIO getPOSIXTime+						when (now - realToFrac started >= delta) $+							resetStartTime+			return True++start :: Maybe Remote -> Incremental -> FilePath -> (Key, Backend) -> CommandStart+start from inc file (key, backend) = do 	numcopies <- numCopies file-	showStart "fsck" file 	case from of-		Nothing -> next $ perform key file backend numcopies-		Just r -> next $ performRemote key file backend numcopies r+		Nothing -> go $ perform key file backend numcopies+		Just r -> go $ performRemote key file backend numcopies r+	where+		go = runFsck inc file key -perform :: Key -> FilePath -> Backend -> Maybe Int -> CommandPerform+perform :: Key -> FilePath -> Backend -> Maybe Int -> Annex Bool perform key file backend numcopies = check 	-- order matters 	[ fixLink key file@@ -65,13 +116,13 @@  {- To fsck a remote, the content is retrieved to a tmp file,  - and checked locally. -}-performRemote :: Key -> FilePath -> Backend -> Maybe Int -> Remote -> CommandPerform+performRemote :: Key -> FilePath -> Backend -> Maybe Int -> Remote -> Annex Bool performRemote key file backend numcopies remote = 	dispatch =<< Remote.hasKey remote key 	where 		dispatch (Left err) = do 			showNote err-			stop+			return False 		dispatch (Right True) = withtmp $ \tmpfile -> 			ifM (getfile tmpfile) 				( go True (Just tmpfile)@@ -111,30 +162,23 @@ 				error "fsck should be run without parameters in a bare repository" 			map a <$> loggedKeys -startBare :: Key -> CommandStart-startBare key = case Backend.maybeLookupBackendName (Types.Key.keyBackendName key) of+startBare :: Incremental -> Key -> CommandStart+startBare inc key = case Backend.maybeLookupBackendName (Types.Key.keyBackendName key) of 	Nothing -> stop-	Just backend -> do-		showStart "fsck" (key2file key)-		next $ performBare key backend+	Just backend -> runFsck inc (key2file key) key $ performBare key backend  {- Note that numcopies cannot be checked in a bare repository, because  - getting the numcopies value requires a working copy with .gitattributes  - files. -}-performBare :: Key -> Backend -> CommandPerform+performBare :: Key -> Backend -> Annex Bool performBare key backend = check 	[ verifyLocationLog key (key2file key) 	, checkKeySize key 	, checkBackend backend key 	] -check :: [Annex Bool] -> CommandPerform	-check = sequence >=> dispatch-	where-		dispatch vs-			| all (== True) vs = next $ return True-			| otherwise = stop-+check :: [Annex Bool] -> Annex Bool+check cs = all id <$> sequence cs  {- Checks that the file's symlink points correctly to the content. -} fixLink :: Key -> FilePath -> Annex Bool@@ -303,3 +347,91 @@ 	Remote.logStatus remote key InfoMissing 	return $ (if ok then "dropped from " else "failed to drop from ") 		++ Remote.name remote++data Incremental = StartIncremental | ContIncremental (Maybe EpochTime) | NonIncremental+	deriving (Eq)++runFsck :: Incremental -> FilePath -> Key -> Annex Bool -> CommandStart+runFsck inc file key a = ifM (needFsck inc key)+	( do+		showStart "fsck" file+		next $ do+			ok <- a+			when ok $+				recordFsckTime key+			next $ return ok+	, stop+	)++{- Check if a key needs to be fscked, with support for incremental fscks. -}+needFsck :: Incremental -> Key -> Annex Bool+needFsck (ContIncremental Nothing) _ = return True+needFsck (ContIncremental starttime) key = do+	fscktime <- getFsckTime key+	return $ fscktime < starttime+needFsck _ _ = return True++{- To record the time that a key was last fscked, without+ - modifying its mtime, we set the timestamp of its parent directory.+ - Each annexed file is the only thing in its directory, so this is fine.+ -+ - To record that the file was fscked, the directory's sticky bit is set.+ - (None of the normal unix behaviors of the sticky bit should matter, so+ - we can reuse this permission bit.)+ -+ - Note that this relies on the parent directory being deleted when a file+ - is dropped. That way, if it's later added back, the fsck record+ - won't still be present.+ -}+recordFsckTime :: Key -> Annex ()+recordFsckTime key = do+	parent <- parentDir <$> inRepo (gitAnnexLocation key)+	liftIO $ void $ tryIO $ do+		touchFile parent+		setSticky parent++getFsckTime :: Key -> Annex (Maybe EpochTime)+getFsckTime key = do+	parent <- parentDir <$> inRepo (gitAnnexLocation key)+	liftIO $ catchDefaultIO Nothing $ do+		s <- getFileStatus parent+		return $ if isSticky $ fileMode s+			then Just $ modificationTime s+			else Nothing++{- Records the start time of an interactive fsck.+ -+ - To guard against time stamp damange (for example, if an annex directory+ - is copied without -a), the fsckstate file contains a time that should+ - be identical to its modification time. -}+recordStartTime :: Annex ()+recordStartTime = do+	f <- fromRepo gitAnnexFsckState+	createAnnexDirectory $ parentDir f+	liftIO $ do+		nukeFile f+		h <- openFile f WriteMode+		t <- modificationTime <$> getFileStatus f+		hPutStr h $ showTime $ realToFrac t+		hClose h+	where+		showTime :: POSIXTime -> String+		showTime = show++resetStartTime :: Annex ()+resetStartTime = liftIO . nukeFile =<< fromRepo gitAnnexFsckState++{- Gets the incremental fsck start time. -}+getStartTime :: Annex (Maybe EpochTime)+getStartTime = do+	f <- fromRepo gitAnnexFsckState+	liftIO $ catchDefaultIO Nothing $ do+		timestamp <- modificationTime <$> getFileStatus f+		t <- readishTime <$> readFile f+		return $ if Just (realToFrac timestamp) == t+			then Just timestamp+			else Nothing+	where+		readishTime :: String -> Maybe POSIXTime+		readishTime s = utcTimeToPOSIXSeconds <$>+			parseTime defaultTimeLocale "%s%Qs" s
Command/Move.hs view
@@ -92,15 +92,16 @@ 			ok <- upload (Remote.uuid dest) key (Just file) noRetry $ 				Remote.storeKey dest key (Just file) 			if ok-				then finish+				then finish True 				else do 					when fastcheck $ 						warning "This could have failed because --fast is enabled." 					stop-		Right True -> finish+		Right True -> finish False 	where-		finish = do-			Remote.logStatus dest key InfoPresent+		finish remotechanged = do+			when remotechanged $+				Remote.logStatus dest key InfoPresent 			if move 				then do 					whenM (inAnnex key) $ removeAnnex key
Command/WebApp.hs view
@@ -17,6 +17,7 @@ import Assistant.TransferSlots import Assistant.Threads.WebApp import Assistant.WebApp+import Assistant.Install import Utility.WebApp import Utility.Daemon (checkDaemon, lockPidFile) import Init@@ -39,6 +40,7 @@  start :: CommandStart start = notBareRepo $ do+	liftIO $ ensureInstalled 	ifM isInitialized ( go , liftIO startNoRepo ) 	stop 	where
GitAnnex.hs view
@@ -141,9 +141,11 @@ 		"skip files with fewer copies" 	, Option ['B'] ["inbackend"] (ReqArg Limit.addInBackend paramName) 		"skip files not using a key-value backend"+	, Option ['T'] ["time-limit"] (ReqArg Limit.addTimeLimit paramTime)+		"stop after the specified amount of time" 	] ++ Option.matcher 	where-		setnumcopies v = Annex.changeState $ \s -> s {Annex.forcenumcopies = readish v }+		setnumcopies v = Annex.changeState $ \s -> s { Annex.forcenumcopies = readish v } 		setgitconfig :: String -> Annex () 		setgitconfig v = do 			newg <- inRepo $ Git.Config.store v
INSTALL view
@@ -1,85 +1,34 @@-## OS-specific instructions+## Pick your OS -* [[OSX]]-* [[Debian]]-* [[Ubuntu]]-* [[Fedora]]-* [[FreeBSD]]-* [[openSUSE]]-* [[ArchLinux]]-* [[NixOS]]-* [[Gentoo]]-* [[ScientificLinux5]] - This should cover RHEL5 clones such as CentOS5 and so on-* Windows: [[sorry, not possible yet|todo/windows_support]]+Quick commands given where possible, but see the individual pages for+details. +[[!table format=dsv header=no data="""+[[OSX]]              | [download git-annex.app](http://downloads.kitenet.net/git-annex/OSX/git-annex.dmg.bz2) **beta**+[[Linux|linux_standalone]] | [download prebuilt linux tarball](http://downloads.kitenet.net/git-annex/linux/)+[[Debian]]           | `apt-get install git-annex`+[[Ubuntu]]           | `apt-get install git-annex`+[[FreeBSD]]          | `pkg_add -r hs-git-annex`+[[ArchLinux]]        | `yaourt -Sy git-annex`+[[NixOS]]            | `nix-env -i git-annex`+[[Gentoo]]           | `emerge git-annex`+[[ScientificLinux5]] | (and other RHEL5 clones like CentOS5)+[[Fedora]]           | +[[openSUSE]]         | +Windows              | [[sorry, Windows not supported yet|todo/windows_support]]+"""]]+ ## Using cabal -As a haskell package, git-annex can be installed using cabal. For example:+As a haskell package, git-annex can be installed using cabal.+Start by installing the [Haskell Platform](http://hackage.haskell.org/platform/),+and then:  	cabal install git-annex --bindir=$HOME/bin -The above downloads the latest release. Alternatively, you can [[download]]-it yourself and [[manually_build_with_cabal|install/cabal]].--## Installation by hand--This is not recommended, it's easier to let cabal pull in the many haskell-libraries. To build and use git-annex by hand, you will need:+That installs the latest release. Alternatively, you can [[download]]+git-annex yourself and [[manually_build_with_cabal|install/cabal]]. -* Haskell stuff-  * [The Haskell Platform](http://haskell.org/platform/) (GHC 7.4 or newer)-  * [MissingH](http://github.com/jgoerzen/missingh/wiki)-  * [pcre-light](http://hackage.haskell.org/package/pcre-light)-  * [utf8-string](http://hackage.haskell.org/package/utf8-string)-  * [SHA](http://hackage.haskell.org/package/SHA)-  * [dataenc](http://hackage.haskell.org/package/dataenc)-  * [monad-control](http://hackage.haskell.org/package/monad-control)-  * [lifted-base](http://hackage.haskell.org/package/lifted-base)-  * [TestPack](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/testpack)-  * [QuickCheck 2](http://hackage.haskell.org/package/QuickCheck)-  * [HTTP](http://hackage.haskell.org/package/HTTP)-  * [json](http://hackage.haskell.org/package/json)-  * [IfElse](http://hackage.haskell.org/package/IfElse)-  * [bloomfilter](http://hackage.haskell.org/package/bloomfilter)-  * [edit-distance](http://hackage.haskell.org/package/edit-distance)-  * [hS3](http://hackage.haskell.org/package/hS3) (optional)-* Optional haskell stuff, used by the [[assistant]] and its webapp (edit Makefile to disable)-  * [stm](http://hackage.haskell.org/package/stm)-    (version 2.3 or newer)-  * [hinotify](http://hackage.haskell.org/package/hinotify)-    (Linux only)-  * [dbus](http://hackage.haskell.org/package/dbus)-  * [yesod](http://hackage.haskell.org/package/yesod)-  * [yesod-static](http://hackage.haskell.org/package/yesod-static)-  * [yesod-default](http://hackage.haskell.org/package/yesod-default)-  * [data-default](http://hackage.haskell.org/package/data-default)-  * [case-insensitive](http://hackage.haskell.org/package/case-insensitive)-  * [http-types](http://hackage.haskell.org/package/http-types)-  * [transformers](http://hackage.haskell.org/package/transformers)-  * [wai](http://hackage.haskell.org/package/wai)-  * [wai-logger](http://hackage.haskell.org/package/wai-logger)-  * [warp](http://hackage.haskell.org/package/warp)-  * [blaze-builder](http://hackage.haskell.org/package/blaze-builder)-  * [blaze-html](http://hackage.haskell.org/package/blaze-html)-  * [crypto-api](http://hackage.haskell.org/package/crypto-api)-  * [hamlet](http://hackage.haskell.org/package/hamlet)-  * [clientsession](http://hackage.haskell.org/package/clientsession)-  * [network-multicast](http://hackage.haskell.org/package/network-multicast)-  * [network-info](http://hackage.haskell.org/package/network-info)-* Shell commands-  * [git](http://git-scm.com/)-  * [uuid](http://www.ossp.org/pkg/lib/uuid/)-    (or `uuidgen` from util-linux)-  * [xargs](http://savannah.gnu.org/projects/findutils/)-  * [rsync](http://rsync.samba.org/)-  * [wget](http://www.gnu.org/software/wget/) or [curl](http://http://curl.haxx.se/) (optional, but recommended)-  * [sha1sum](ftp://ftp.gnu.org/gnu/coreutils/) (optional, but recommended;-    a sha1 command will also do)-  * [gpg](http://gnupg.org/) (optional; needed for encryption)-  * [lsof](ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/)-    (optional; recommended for watch mode)-  * multicast DNS support, provided on linux by [nss-mdns](http://www.0pointer.de/lennart/projects/nss-mdns/)-    (optional; recommended for the assistant to support pairing well)-  * [ikiwiki](http://ikiwiki.info) (optional; used to build the docs)+## Installation from scratch -Then just [[download]] git-annex and run: `make; make install`+This is not recommended, but if you really want to, see [[fromscratch]].
Limit.hs view
@@ -9,6 +9,7 @@  import Text.Regex.PCRE.Light.Char8 import System.Path.WildMatch+import Data.Time.Clock.POSIX  import Common.Annex import qualified Annex@@ -17,6 +18,7 @@ import qualified Backend import Annex.Content import Logs.Trust+import Utility.HumanTime  type Limit = Utility.Matcher.Token (FilePath -> Annex Bool) @@ -106,3 +108,17 @@ 	where 		wanted = Backend.lookupBackendName name 		check = return . maybe False ((==) wanted . snd)++addTimeLimit :: String -> Annex ()+addTimeLimit s = do+	let seconds = fromMaybe (error "bad time-limit") $ parseDuration s+	start <- liftIO getPOSIXTime+	let cutoff = start + seconds+	addLimit $ const $ do+		now <- liftIO getPOSIXTime+		if now > cutoff+			then do+				warning $ "Time limit (" ++ s ++ ") reached!"+				liftIO $ exitWith $ ExitFailure 101+			else return True+		
Locations.hs view
@@ -18,7 +18,9 @@ 	gitAnnexBadDir, 	gitAnnexBadLocation, 	gitAnnexUnusedLog,+	gitAnnexFsckState, 	gitAnnexTransferDir,+	gitAnnexCredsDir, 	gitAnnexJournalDir, 	gitAnnexJournalLock, 	gitAnnexIndex,@@ -130,7 +132,16 @@ gitAnnexUnusedLog :: FilePath -> Git.Repo -> FilePath gitAnnexUnusedLog prefix r = gitAnnexDir r </> (prefix ++ "unused") -{- .git/annex/transfer/ is used is used to record keys currently+{- .git/annex/fsckstate is used to store information about incremental fscks. -}+gitAnnexFsckState :: Git.Repo -> FilePath+gitAnnexFsckState r = gitAnnexDir r </> "fsckstate"++{- .git/annex/creds/ is used to store credentials to access some special+ - remotes. -}+gitAnnexCredsDir :: Git.Repo -> FilePath+gitAnnexCredsDir r = addTrailingPathSeparator $ gitAnnexDir r </> "creds"++{- .git/annex/transfer/ is used to record keys currently  - being transferred, and other transfer bookkeeping info. -} gitAnnexTransferDir :: Git.Repo -> FilePath gitAnnexTransferDir r = addTrailingPathSeparator $ gitAnnexDir r </> "transfer"
Makefile view
@@ -5,7 +5,9 @@  # If you get build failures due to missing haskell libraries, # you can turn off some of these features.-FEATURES=-DWITH_ASSISTANT -DWITH_S3 -DWITH_WEBAPP -DWITH_OLD_YESOD -DWITH_PAIRING+#+# If you're using an old version of yesod, enable -DWITH_OLD_YESOD+FEATURES?=$(GIT_ANNEX_LOCAL_FEATURES) -DWITH_ASSISTANT -DWITH_S3 -DWITH_WEBAPP -DWITH_PAIRING  bins=git-annex mans=git-annex.1 git-annex-shell.1@@ -21,7 +23,6 @@ OPTFLAGS=-DWITH_KQUEUE clibs=Utility/libdiskfree.o Utility/libmounts.o Utility/libkqueue.o ifeq ($(OS),Darwin)-OPTFLAGS=-DWITH_KQUEUE -DOSX # Ensure OSX compiler builds for 32 bit when using 32 bit ghc GHCARCH:=$(shell ghc -e 'print System.Info.arch') ifeq ($(GHCARCH),i386)@@ -132,5 +133,79 @@ # Upload to hackage. hackage: sdist 	@cabal upload dist/*.tar.gz++THIRDPARTY_BINS=git curl lsof xargs rsync uuid wget gpg \+	sha1sum sha224sum sha256sum sha384sum sha512sum++LINUXSTANDALONE_DEST=$(GIT_ANNEX_TMP_BUILD_DIR)/git-annex.linux+linuxstandalone: $(bins)+	rm -rf "$(LINUXSTANDALONE_DEST)"++	cp -R standalone/linux "$(LINUXSTANDALONE_DEST)"++	install -d "$(LINUXSTANDALONE_DEST)/bin"+	cp git-annex "$(LINUXSTANDALONE_DEST)/bin/"+	strip "$(LINUXSTANDALONE_DEST)/bin/git-annex"+	ln -sf git-annex "$(LINUXSTANDALONE_DEST)/bin/git-annex-shell"+	zcat standalone/licences.gz > $(LINUXSTANDALONE_DEST)/LICENSE++	for bin in $(THIRDPARTY_BINS); do \+		cp "$$(which "$$bin")" "$(LINUXSTANDALONE_DEST)/bin/" || echo "$$bin not available; skipping"; \+	done+	+	install -d "$(LINUXSTANDALONE_DEST)/git-core"+	(cd "$(shell git --exec-path)" && tar c .) | (cd "$(LINUXSTANDALONE_DEST)"/git-core && tar x)+	+	touch "$(LINUXSTANDALONE_DEST)/libdirs.tmp"+	for lib in $$(ldd "$(LINUXSTANDALONE_DEST)"/bin/* $$(find "$(LINUXSTANDALONE_DEST)"/git-core/ -type f) | grep -v -f standalone/linux/glibc-libs | grep -v "not a dynamic executable" | egrep '^	' | sed 's/^\t//' | sed 's/.*=> //' | cut -d ' ' -f 1 | sort | uniq); do \+		dir=$$(dirname "$$lib"); \+		install -d "$(LINUXSTANDALONE_DEST)/$$dir"; \+		echo "$$dir" >> "$(LINUXSTANDALONE_DEST)/libdirs.tmp"; \+		cp "$$lib" "$(LINUXSTANDALONE_DEST)/$$dir"; \+		if [ -L "$lib" ]; then \+			link=$$(readlink -f "$$lib"); \+			cp "$$link" "$(LINUXSTANDALONE_DEST)/$$(dirname "$$link")"; \+		fi; \+	done+	sort "$(LINUXSTANDALONE_DEST)/libdirs.tmp" | uniq > "$(LINUXSTANDALONE_DEST)/libdirs"+	rm -f "$(LINUXSTANDALONE_DEST)/libdirs.tmp"++	cd $(GIT_ANNEX_TMP_BUILD_DIR) && tar czf git-annex-standalone-$(shell dpkg --print-architecture).tar.gz git-annex.linux++OSXAPP_DEST=$(GIT_ANNEX_TMP_BUILD_DIR)/build-dmg/git-annex.app+OSXAPP_BASE=$(OSXAPP_DEST)/Contents/MacOS+osxapp: $(bins)+	rm -rf "$(OSXAPP_DEST)"+	install -d $(GIT_ANNEX_TMP_BUILD_DIR)/build-dmg+	cp -R standalone/osx/git-annex.app "$(OSXAPP_DEST)"++	install -d "$(OSXAPP_BASE)/bin"+	cp git-annex "$(OSXAPP_BASE)/bin/"+	strip "$(OSXAPP_BASE)/bin/git-annex"+	ln -sf git-annex "$(OSXAPP_BASE)/bin/git-annex-shell"+	gzcat standalone/licences.gz > $(OSXAPP_BASE)/LICENSE+	cp $(OSXAPP_BASE)/LICENSE $(GIT_ANNEX_TMP_BUILD_DIR)/build-dmg/LICENSE.txt++	for bin in $(THIRDPARTY_BINS); do \+		cp "$$(which "$$bin")" "$(OSXAPP_BASE)/bin/" || echo "$$bin not available; skipping"; \+	done++	install -d "$(OSXAPP_BASE)/git-core"+	(cd "$(shell git --exec-path)" && tar c .) | (cd "$(OSXAPP_BASE)"/git-core && tar x)++	touch "$(OSXAPP_BASE)/libdirs.tmp"+	for lib in $$(otool -L "$(OSXAPP_BASE)"/bin/* "$(OSXAPP_BASE)"/git-core/* | egrep '^	' | cut -d ' ' -f 1 | sed  's/^	//' | sort | uniq); do \+		dir=$$(dirname "$$lib"); \+		install -d "$(OSXAPP_BASE)/$$dir"; \+		echo "$$dir" >> "$(OSXAPP_BASE)/libdirs.tmp"; \+		cp "$$lib" "$(OSXAPP_BASE)/$$dir"; \+	done+	sort "$(OSXAPP_BASE)/libdirs.tmp" | uniq > "$(OSXAPP_BASE)/libdirs"+	rm -f "$(OSXAPP_BASE)/libdirs.tmp"+	rm -f tmp/git-annex.dmg+	hdiutil create -size 640m -format UDRW -srcfolder $(GIT_ANNEX_TMP_BUILD_DIR)/build-dmg \+		-volname git-annex -o tmp/git-annex.dmg+	rm -f tmp/git-annex.dmg.bz2+	bzip2 tmp/git-annex.dmg  .PHONY: $(bins) test install
Remote/Helper/Encryptable.hs view
@@ -88,6 +88,11 @@ 			Annex.changeState (\s -> s { Annex.ciphers = M.insert encipher cipher cache }) 			return $ Just cipher +{- Checks if there is a trusted (non-shared) cipher. -}+isTrustedCipher :: RemoteConfig -> Bool+isTrustedCipher c = +	isJust (M.lookup "cipherkeys" c) && isJust (M.lookup "cipher" c)+ {- Gets encryption Cipher, and encrypted version of Key. -} cipherKey :: Maybe RemoteConfig -> Key -> Annex (Maybe (Cipher, Key)) cipherKey Nothing _ = return Nothing
Remote/S3.hs view
@@ -5,7 +5,7 @@  - Licensed under the GNU GPL version 3 or higher.  -} -module Remote.S3 (remote) where+module Remote.S3 (remote, s3SetCredsEnv) where  import Network.AWS.AWSConnection import Network.AWS.S3Object@@ -27,6 +27,8 @@ import Crypto import Annex.Content import Utility.Base64+import Annex.Perms+import Utility.FileMode  remote :: RemoteType remote = RemoteType {@@ -85,12 +87,12 @@  		use fullconfig = do 			gitConfigSpecialRemote u fullconfig "s3" "true"-			s3SetCreds fullconfig	+			s3SetCreds fullconfig u  		defaulthost = do 			c' <- encryptionSetup c 			let fullconfig = c' `M.union` defaults-			genBucket fullconfig+			genBucket fullconfig u 			use fullconfig  		archiveorg = do@@ -206,7 +208,7 @@ 	when (isNothing $ config r) $ 		error $ "Missing configuration for special remote " ++ name r 	let bucket = M.lookup "bucket" $ fromJust $ config r-	conn <- s3Connection $ fromJust $ config r+	conn <- s3Connection (fromJust $ config r) (uuid r) 	case (bucket, conn) of 		(Just b, Just c) -> action (c, b) 		_ -> return noconn@@ -235,9 +237,9 @@ 			| isSpace c = [] 			| otherwise = "&" ++ show (ord c) ++ ";" -genBucket :: RemoteConfig -> Annex ()-genBucket c = do-	conn <- s3ConnectionRequired c+genBucket :: RemoteConfig -> UUID -> Annex ()+genBucket c u = do+	conn <- s3ConnectionRequired c u 	showAction "checking bucket" 	loc <- liftIO $ getBucketLocation conn bucket  	case loc of@@ -253,13 +255,13 @@ 		bucket = fromJust $ M.lookup "bucket" c 		datacenter = fromJust $ M.lookup "datacenter" c -s3ConnectionRequired :: RemoteConfig -> Annex AWSConnection-s3ConnectionRequired c =-	maybe (error "Cannot connect to S3") return =<< s3Connection c+s3ConnectionRequired :: RemoteConfig -> UUID -> Annex AWSConnection+s3ConnectionRequired c u =+	maybe (error "Cannot connect to S3") return =<< s3Connection c u -s3Connection :: RemoteConfig -> Annex (Maybe AWSConnection)-s3Connection c = do-	creds <- s3GetCreds c+s3Connection :: RemoteConfig -> UUID -> Annex (Maybe AWSConnection)+s3Connection c u = do+	creds <- s3GetCreds c u 	case creds of 		Just (ak, sk) -> return $ Just $ AWSConnection host port ak sk 		_ -> do@@ -272,51 +274,77 @@ 			[(p, _)] -> p 			_ -> error $ "bad S3 port value: " ++ s -{- S3 creds come from the environment if set. - - Otherwise, might be stored encrypted in the remote's config. -}-s3GetCreds :: RemoteConfig -> Annex (Maybe (String, String))-s3GetCreds c = maybe fromconfig (return . Just) =<< liftIO getenv+{- S3 creds come from the environment if set, otherwise from the cache+ - in gitAnnexCredsDir, or failing that, might be stored encrypted in+ - the remote's config. -}+s3GetCreds :: RemoteConfig -> UUID -> Annex (Maybe (String, String))+s3GetCreds c u = maybe fromcache (return . Just) =<< liftIO getenv 	where 		getenv = liftM2 (,) 			<$> get s3AccessKey 			<*> get s3SecretKey 			where 				get = catchMaybeIO . getEnv-		setenv (ak, sk) = do-			setEnv s3AccessKey ak True-			setEnv s3SecretKey sk True+		fromcache = do+			d <- fromRepo gitAnnexCredsDir+			let f = d </> fromUUID u+			v <- liftIO $ catchMaybeIO $ readFile f+			case lines <$> v of+				Just (ak:sk:[]) -> return $ Just (ak, sk)+				_ -> fromconfig 		fromconfig = do 			mcipher <- remoteCipher c 			case (M.lookup "s3creds" c, mcipher) of-				(Just s3creds, Just cipher) ->-					liftIO $ decrypt s3creds cipher+				(Just s3creds, Just cipher) -> do+					creds <- liftIO $ decrypt s3creds cipher+					case creds of+						[ak, sk] -> do+							s3CacheCreds (ak, sk) u+							return $ Just (ak, sk)+						_ -> do error "bad s3creds"		 				_ -> return Nothing-		decrypt s3creds cipher = do-			creds <- lines <$>-				withDecryptedContent cipher-					(return $ L.pack $ fromB64 s3creds)-					(return . L.unpack)-			case creds of-				[ak, sk] -> do-					setenv (ak, sk)-					return $ Just (ak, sk)-				_ -> do error "bad s3creds"+		decrypt s3creds cipher = lines <$>+			withDecryptedContent cipher+				(return $ L.pack $ fromB64 s3creds)+				(return . L.unpack) -{- Stores S3 creds encrypted in the remote's config if possible. -}-s3SetCreds :: RemoteConfig -> Annex RemoteConfig-s3SetCreds c = do-	creds <- s3GetCreds c+{- Stores S3 creds encrypted in the remote's config if possible to do so+ - securely, and otherwise locally in gitAnnexCredsDir. -}+s3SetCreds :: RemoteConfig -> UUID -> Annex RemoteConfig+s3SetCreds c u = do+	creds <- s3GetCreds c u 	case creds of 		Just (ak, sk) -> do 			mcipher <- remoteCipher c 			case mcipher of-				Just cipher -> do+				Just cipher | isTrustedCipher c -> do 					s <- liftIO $ withEncryptedContent cipher 						(return $ L.pack $ unlines [ak, sk]) 						(return . L.unpack) 					return $ M.insert "s3creds" (toB64 s) c-				Nothing -> return c+				_ -> do+					s3CacheCreds (ak, sk) u+					return c 		_ -> return c++{- The S3 creds are cached in gitAnnexCredsDir. -}+s3CacheCreds :: (String, String) -> UUID -> Annex ()+s3CacheCreds (ak, sk) u = do+	d <- fromRepo gitAnnexCredsDir+	createAnnexDirectory d+	liftIO $ do+		let f = d </> fromUUID u+		h <- openFile f WriteMode+		modifyFileMode f $ removeModes+			[groupReadMode, otherReadMode]+		hPutStr h $ unlines [ak, sk]+		hClose h++{- Sets the S3 creds in the environment. -}+s3SetCredsEnv :: (String, String) -> IO ()+s3SetCredsEnv (ak, sk) = do+	setEnv s3AccessKey ak True+	setEnv s3SecretKey sk True  s3AccessKey :: String s3AccessKey = "AWS_ACCESS_KEY_ID"
Setup.hs view
@@ -58,6 +58,6 @@  installDesktopFile :: CopyDest -> Verbosity -> PackageDescription -> LocalBuildInfo -> IO () installDesktopFile copyDest verbosity pkg lbi =-	InstallDesktopFile.writeDesktop $ dstBinDir </> "git-annex"+	InstallDesktopFile.install $ dstBinDir </> "git-annex" 	where 		dstBinDir = bindir $ absoluteInstallDirs pkg lbi copyDest
Usage.hs view
@@ -77,6 +77,8 @@ paramType = "TYPE" paramDate :: String paramDate = "DATE"+paramTime :: String+paramTime = "TIME" paramFormat :: String paramFormat = "FORMAT" paramFile :: String
− Utility/Applicative.o

binary file changed (1308 → absent bytes)

Utility/DirWatcher.hs view
@@ -102,8 +102,8 @@ #if WITH_KQUEUE type DirWatcherHandle = ThreadId watchDir :: FilePath -> Pruner -> WatchHooks -> (IO Kqueue.Kqueue -> IO Kqueue.Kqueue) -> IO DirWatcherHandle-watchDir dir ignored hooks runstartup = do-	kq <- runstartup $ Kqueue.initKqueue dir ignored+watchDir dir prune hooks runstartup = do+	kq <- runstartup $ Kqueue.initKqueue dir prune 	forkIO $ Kqueue.runHooks kq hooks #else type DirWatcherHandle = ()
− Utility/Directory.o

binary file changed (17128 → absent bytes)

− Utility/Exception.o

binary file changed (5624 → absent bytes)

Utility/FileMode.hs view
@@ -63,9 +63,12 @@ 	, ownerReadMode, groupReadMode 	] +checkMode :: FileMode -> FileMode -> Bool+checkMode checkfor mode = checkfor `intersectFileModes` mode == checkfor+ {- Checks if a file mode indicates it's a symlink. -} isSymLink :: FileMode -> Bool-isSymLink mode = symbolicLinkMode `intersectFileModes` mode == symbolicLinkMode+isSymLink = checkMode symbolicLinkMode  {- Checks if a file has any executable bits set. -} isExecutable :: FileMode -> Bool@@ -88,3 +91,12 @@ combineModes [] = undefined combineModes [m] = m combineModes (m:ms) = foldl unionFileModes m ms++stickyMode :: FileMode+stickyMode = 512++isSticky :: FileMode -> Bool+isSticky = checkMode stickyMode++setSticky :: FilePath -> IO ()+setSticky f = modifyFileMode f $ addModes [stickyMode]
− Utility/FileSystemEncoding.o

binary file changed (4868 → absent bytes)

+ Utility/HumanTime.hs view
@@ -0,0 +1,26 @@+{- Time for humans.+ -+ - Copyright 2012 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Utility.HumanTime where++import Utility.PartialPrelude++import Data.Time.Clock.POSIX (POSIXTime)++{- Parses a human-input time duration, of the form "5h" or "1m". -}+parseDuration :: String -> Maybe POSIXTime+parseDuration s = do+	num <- readish s :: Maybe Integer+	units <- findUnits =<< lastMaybe s+	return $ fromIntegral num * units+	where+		findUnits 's' = Just 1+		findUnits 'm' = Just 60+		findUnits 'h' = Just $ 60 * 60+		findUnits 'd' = Just $ 60 * 60 * 24+		findUnits 'y' = Just $ 60 * 60 * 24 * 365+		findUnits _ = Nothing
Utility/Kqueue.hs view
@@ -198,7 +198,8 @@ 	go =<< catchMaybeIO (getDirInfo $ dirName olddirinfo) 	where 		go (Just newdirinfo) = do-			let changes = olddirinfo // newdirinfo+			let changes = filter (not . pruner . changedFile) $+				 olddirinfo // newdirinfo 			let (added, deleted) = partition isAdd changes  			-- Scan newly added directories to add to the map.
− Utility/Misc.o

binary file changed (6176 → absent bytes)

− Utility/Monad.o

binary file changed (6164 → absent bytes)

+ Utility/OSX.hs view
@@ -0,0 +1,43 @@+{- OSX stuff+ -+ - Copyright 2012 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Utility.OSX where++import Utility.Path++import System.FilePath++autoStartBase :: String -> FilePath+autoStartBase label = "Library" </> "LaunchAgents" </> label ++ ".plist"++systemAutoStart :: String -> FilePath+systemAutoStart label = "/" </> autoStartBase label++userAutoStart :: String -> IO FilePath+userAutoStart label = do+	home <- myHomeDir+	return $ home </> autoStartBase label++{- Generates an OSX autostart plist file with a given label, command, and+ - params to run at boot or login. -}+genOSXAutoStartFile :: String -> String -> [String] -> String+genOSXAutoStartFile label command params = unlines+	[ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+	, "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"+	, "<plist version=\"1.0\">"+	, "<dict>"+	, "<key>Label</key>"+	, "<string>" ++ label ++ "</string>"+	, "<key>ProgramArguments</key>"+	, "<array>"+	, unlines $ map (\v -> "<string>" ++ v ++ "</string>") (command:params)+	, "</array>"+	, "<key>RunAtLoad</key>"+	, "</dict>"+	, "</plist>"+	]+	
− Utility/PartialPrelude.o

binary file changed (5448 → absent bytes)

− Utility/Path.o

binary file changed (21888 → absent bytes)

Utility/Process.hs view
@@ -101,14 +101,14 @@ 			, env = environ 			} -{- Waits for a ProcessHandle, and throws an exception if the process+{- Waits for a ProcessHandle, and throws an IOError if the process  - did not exit successfully. -} forceSuccessProcess :: CreateProcess -> ProcessHandle -> IO () forceSuccessProcess p pid = do 	code <- waitForProcess pid 	case code of 		ExitSuccess -> return ()-		ExitFailure n -> error $ showCmd p ++ " exited " ++ show n+		ExitFailure n -> fail $ showCmd p ++ " exited " ++ show n  {- Waits for a ProcessHandle and returns True if it exited successfully. -} checkSuccessProcess :: ProcessHandle -> IO Bool
− Utility/Process.o

binary file changed (26100 → absent bytes)

− Utility/SafeCommand.o

binary file changed (25780 → absent bytes)

− Utility/TempFile.o

binary file changed (6216 → absent bytes)

Utility/WebApp.hs view
@@ -44,7 +44,7 @@ runBrowser :: String -> IO Bool runBrowser url = boolSystem cmd [Param url] 	where-#if OSX+#ifdef darwin_HOST_OS 		cmd = "open" #else 		cmd = "xdg-open"@@ -80,7 +80,14 @@ 			{ addrFlags = [AI_ADDRCONFIG] 			, addrSocketType = Stream 			}-		go addr = bracketOnError (open addr) close (use addr)+		{- Repeated attempts because bind sometimes fails for an+		 - unknown reason on OSX. -} +		go addr = go' 100 addr+		go' :: Int -> AddrInfo -> IO Socket+		go' 0 _ = error "unable to bind to local socket"+		go' n addr = do+			r <- tryIO $ bracketOnError (open addr) close (use addr)+			either (const $ go' (pred n) addr) return r 		open addr = socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr) 		close = sClose 		use addr sock = do
debian/changelog view
@@ -1,3 +1,33 @@+git-annex (3.20121001) unstable; urgency=low++  * fsck: Now has an incremental mode. Start a new incremental fsck pass+    with git annex fsck --incremental. Now the fsck can be interrupted+    as desired, and resumed with git annex fsck --more.+    Thanks, Justin Azoff+  * New --time-limit option, makes long git-annex commands stop after+    a specified amount of time.+  * fsck: New --incremental-schedule option which is nice for scheduling+    eg, monthly incremental fsck runs in cron jobs.+  * Fix fallback to ~/Desktop when xdg-user-dir is not available.+    Closes: #688833+  * S3: When using a shared cipher, S3 credentials are not stored encrypted+    in the git repository, as that would allow anyone with access to+    the repository access to the S3 account. Instead, they're stored+    in a 600 mode file in the local git repo.+  * webapp: Avoid crashing when ssh-keygen -F chokes on an invalid known_hosts+    file.+  * Always do a system wide installation when DESTDIR is set. Closes: #689052+  * The Makefile now builds with the new yesod by default.+    Systems like Debian that have the old yesod 1.0.1 should set+    GIT_ANNEX_LOCAL_FEATURES=-DWITH_OLD_YESOD+  * copy: Avoid updating the location log when no copy is performed.+  * configure: Test that uuid -m works, falling back to plain uuid if not.+  * Avoid building the webapp on Debian architectures that do not yet+    have template haskell and thus yesod. (Should be available for arm soonish+    I hope).++ -- Joey Hess <joeyh@debian.org>  Mon, 01 Oct 2012 13:56:55 -0400+ git-annex (3.20120924) unstable; urgency=low    * assistant: New command, a daemon which does everything watch does,@@ -23,7 +53,7 @@     files and reading from checksum commands.   * sync: Pushes the git-annex branch to remote/synced/git-annex, rather     than directly to remote/git-annex.-  * Now supports matchig files that are present on a number of remotes+  * Now supports matching files that are present on a number of remotes     with a specified trust level. Example: --copies=trusted:2     Thanks, Nicolas Pouillard 
debian/control view
@@ -22,10 +22,11 @@ 	libghc-edit-distance-dev, 	libghc-hinotify-dev [linux-any], 	libghc-stm-dev (>= 2.3),-	libghc-dbus-dev,-	libghc-yesod-dev,-	libghc-yesod-static-dev,-	libghc-yesod-default-dev,+	libghc-dbus-dev [linux-any],+	libghc-yesod-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64],+	libghc-yesod-static-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64],+	libghc-yesod-default-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64],+	libghc-hamlet-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64], 	libghc-case-insensitive-dev, 	libghc-http-types-dev, 	libghc-transformers-dev,@@ -35,7 +36,6 @@ 	libghc-blaze-builder-dev, 	libghc-blaze-html-dev, 	libghc-crypto-api-dev,-	libghc-hamlet-dev, 	libghc-clientsession-dev, 	libghc-network-multicast-dev, 	libghc-network-info-dev,@@ -59,8 +59,8 @@ 	rsync, 	wget | curl, 	openssh-client (>= 1:5.6p1)-Recommends: lsof, libnss-mdns, gnupg-Suggests: graphviz, bup+Recommends: lsof, gnupg+Suggests: graphviz, bup, libnss-mdns Description: manage files with git, without checking their contents into git  git-annex allows managing files with git, without checking the file  contents into git. While that may seem paradoxical, it is useful when
debian/copyright view
@@ -9,7 +9,7 @@ Copyright: © 2012 Joey Hess <joey@kitenet.net> License: AGPL-3+ -Files: doc/logo* */favicon.ico ui-macos/git-annex.app/Contents/Resources/git-annex.icns+Files: doc/logo* */favicon.ico standalone/osx/git-annex.app/Contents/Resources/git-annex.icns Copyright: 2007 Henrik Nyh <http://henrik.nyh.se/>            2010 Joey Hess <joey@kitenet.net> License: other
debian/rules view
@@ -1,4 +1,12 @@ #!/usr/bin/make -f++ARCH = $(shell dpkg-architecture -qDEB_BUILD_ARCH)+ifeq (install ok installed,$(shell dpkg-query -W -f '$${Status}' libghc-yesod-dev 2>/dev/null))+export FEATURES=-DWITH_ASSISTANT -DWITH_S3 -DWITH_OLD_YESOD -DWITH_WEBAPP -DWITH_PAIRING+else+export FEATURES=-DWITH_ASSISTANT -DWITH_S3 -DWITH_PAIRING+endif+ %: 	dh $@ 
doc/assistant.mdwn view
@@ -4,7 +4,7 @@ It's very easy to use, and has all the power of git and git-annex.  Note that the git-annex assistant is still beta quality code. See-[[the_errata]] for known infelicities.+[[the_errata|errata]] for known infelicities.  ## installation 
doc/assistant/thanks.mdwn view
@@ -48,7 +48,8 @@ Andrew, Aaron De Vries, Monti Knazze, Jorge Canseco, Hamish, Mark Eichin  And special thanks to Kevin McKenzie, who also gave me a login to a Mac OSX-machine, which has proven invaluable.+machine, which has proven invaluable, and Jimmy Tang who has helped+with Mac OSX autobuilding and packaging.  ## Other Backers @@ -171,7 +172,7 @@ Christian Simonsen, Wouter Beugelsdijk, Adam Gibson, Gal Buki, James Marble, Alan Chambers, Bernd Wiehle, Simon Korzun, Daniel Glassey, Eero af Heurlin, Mikael, Timo Engelhardt, Wesley Faulkner, Jay Wo, Mike Belle,-David Fowlkes Jr., Jimmy Tang, Karl-Heinz Strass, Ed Mullins, Sam Flint,+David Fowlkes Jr., Karl-Heinz Strass, Ed Mullins, Sam Flint, Hendrica, Mark Emer Anderson, Joshua Cole, Jan Gondol, Henrik Lindhe, Albert Delgado, Patrick, Alexa Avellar, Chris, sebsn1349, Maxim Kachur, Andrew Marshall, Navjot Narula, Alwin Mathew, Christian Mangelsdorf, Avi
doc/bugs/ControlPath_too_long_for_Unix_domain_socket.mdwn view
@@ -48,3 +48,6 @@ >  > Please test and see if it works, and also if the "looping" problem > still happens. --[[Joey]]++>> Closing; I'm pretty sure the looping is just transfer retrying, to be+>> expected if they fail. [[done]] --[[Joey]] 
+ doc/bugs/OSX_alias_permissions_and_versions_problem.mdwn view
@@ -0,0 +1,31 @@+What steps will reproduce the problem?++Use assistant and create repository the a folder in home dir.+Use textedit and save a new txt to the repository folder. ++What is the expected output? What do you see instead?++The alias solution is broken. It should work more like Dropbox.+Textedit saves the file initially, but it is immediately locked.+Since it autosaves, it asks to unlock or duplicate.+Then gives the error:+"The file “Untitled 16.txt” cannot be unlocked."++If the file exists:+The document “Untitled 14” could not be saved as “Untitled 14.txt”. You don’t have permission.++If you open a file from the repository (now replaced by a symlink) with textedit, there are other problems:+- The filename will not be correct (will show the sha hash). +- It will ask to unlock, then give the error "You don’t have permission to write to the folder that the file “SHA256E-s8--8985d9832de2e28b5e1af64258c391a34d7528709ef916bac496e698c139020c.txt” is in."++What version of git-annex are you using? On what operating system?++OSX Lion+git-annex version: 3.20120924++Please provide any additional information below.++Even if you fix these problems, automatic versioning in lion will probably don't work, and the symlinks seem a hackish solution and don't seem intuitive or easy to the end user. +The sync should be transparent but it's not, and it's error prone. It would even be best to keep file copies in the git repo and sync them with the original folder than make symlinks.++Dropbox even allows to put a symlink in the dropbox directory, and it will sync the file. 
doc/bugs/Using_Github_as_remote_throws_proxy_errors.mdwn view
@@ -23,3 +23,5 @@ git-annex-3.20120825  Max OS X 10.8.1++> [[done]]; see comments --[[Joey]] 
+ doc/bugs/Webapp_fails_to_resolve_ipv6_hostname.mdwn view
@@ -0,0 +1,15 @@+What steps will reproduce the problem?++From the webapp, go to Configuration > Manage repositories > Remote server. Enter a hostname that only has an IPv6 hostname (e.g. ipv6.google.com). Click Check this server.++What is the expected output? What do you see instead?++Expect the application to attempt to check the server via SSH. Instead, it results in error "cannot resolve host name".++What version of git-annex are you using? On what operating system?++git-annex 3.20120924 on Debian testing (amd64).++Please provide any additional information below.++> Thanks, [[fixed|done]] --[[Joey]] 
+ doc/bugs/build_is_broken_at_commit_cc0e5b7.mdwn view
@@ -0,0 +1,13 @@+the build is currently borked with++<pre>+ghc -O2 -threaded -Wall -ignore-package monads-fd -ignore-package monads-tf -outputdir tmp -IUtility -DWITH_ASSISTANT -DWITH_S3 -DWITH_WEBAPP -DWITH_PAIRING -DWITH_KQUEUE -DOSX --make git-annex -o tmp/git-annex Utility/libdiskfree.o Utility/libmounts.o Utility/libkqueue.o+Assistant/Install.hs:19:8:+Could not find module `Utility'+Use -v to see a list of the files searched for.+make: *** [git-annex] Error 1+</pre>++This was first introduced at commit e88e3ba++> oops, -DOSX is not a good idea. [[done]] --[[Joey]] 
+ doc/bugs/cabal_configure_is_broken_on_OSX_builds.mdwn view
@@ -0,0 +1,14 @@+Seems the last few commits have borked 'cabal configure' on OSX with the following error message++<pre>+[jtang@laplace git-annex (master)]$ cabal configure +Resolving dependencies...++Build/InstallDesktopFile.hs:19:8:+    Could not find module `Assistant.OSX'+    Use -v to see a list of the files searched for.+</pre>++Looks like a missing module.++> Was broken everywhere really, so I fixed it. [[done]] --[[Joey]] 
doc/bugs/git_defunct_processes___40__child_of_git-annex_assistant__41__.mdwn view
@@ -30,3 +30,5 @@ I have done this on my copy for testing it.  For testing, I am also using two repositories on the same computer.  I set this up from the command line, as the web app does not seem to support syncing to two different git folders on the same computer.++> [[done]]; see comments --[[Joey]] 
doc/bugs/lsof__47__committer_thread_loops_occassionally.mdwn view
@@ -49,3 +49,5 @@ I ran " git annex watch -d --foreground" to watch what was going one, and just created a .gitignore file and the the commiter/lsof thread just loops over and over.... I only noticed as my laptop battery had drained at somepoint when git-annex was running in the background.  [[!meta title="assistant: lsof/committer thread loops occassionally"]]++> Closing this since it doesn't seem reproducible. [[done]] --[[Joey]]
doc/bugs/pasting_into_annex_on_OSX.mdwn view
@@ -15,4 +15,7 @@ Please provide any additional information below.  > Ok, I've put in the one second delay to adding by default on OSX.-> I consider this bug [[done]], at least for now..+> I consider this bug done, at least for now..++>> Reopening since I've heard from someone else that it can still happen.+>> --[[Joey]] 
+ doc/bugs/removable_device_configurator_chokes_on_spaces.mdwn view
@@ -0,0 +1,18 @@+# What steps will reproduce the problem?++1. Get a removable device and create a filesystem with a label containing a space, e.g.:+    # mkfs.ext4 -L "Backup Home" /dev/sdb1+2. Open the webapp and add a new repository on a removabledevice+3. Select the devices mountpoint, e.g. /media/Backup\ Home++# What is the expected output? What do you see instead?++The configurator should remove spaces for branch names, but it actually seems to call git remote add with "Backup Home" as argument which is invalid.++The assistant produces an internal server error and subsequently crashes completely.++# What version of git-annex are you using? On what operating system?++git-annex 3.20120924 from the Debian package in sid on Debian wheezy, amd64.++> Thanks for reporting this, I've fixed it in git. [[done]] --[[Joey]] 
+ doc/bugs/xdg-user-dir_error.mdwn view
@@ -0,0 +1,8 @@+Run *git annex webapp* in Debian Sid with KDE.++It opens the web browser with this error: **Internal Server Error** *xdg-user-dir ["DESKTOP"] exited 127*.++I've tried to changing the xdg-user-dir config with no success.++> This is fixed in my master branch. Workaround: Install the xdg-user-dirs+> package. [[done]] --[[Joey]]
doc/contact.mdwn view
@@ -8,3 +8,4 @@ of managing their large personal files.  For realtime chat, use the `#vcs-home` channel on irc.oftc.net.+You can also watch incoming commits there.
doc/design/assistant.mdwn view
@@ -25,7 +25,7 @@  * [[desymlink]] * [[deltas]]-* [[!traillink leftovers]]+* [[leftovers]]  ## blog 
doc/design/assistant/OSX.mdwn view
@@ -4,6 +4,9 @@ * icon to start webapp **done** * Use OSX's "network reachability functionality" to detect when on a network   <http://developer.apple.com/library/mac/#documentation/Networking/Conceptual/SystemConfigFrameworks/SC_Intro/SC_Intro.html#//apple_ref/doc/uid/TP40001065>+* daily build seems to have a bad yesod-static, resulting in the url+  for `/static/jquery-full.js` redirecting to `/jquery-full.js?etag=foo',+  which is a 404. Works ok when I build it on oberon.  Gripes: 
+ doc/design/assistant/blog/day_91__break.mdwn view
@@ -0,0 +1,7 @@+Mostly took a break from working on the assistant today. Instead worked+on adding incremental fsck to git-annex. Well, that will be something+that assistant will use, eventually, probably.++Jimmy and I have been working on a self-contained OSX app for using the+assistant, that doesn't depend on installing git, etc. More on that+once we have something that works.
+ doc/design/assistant/blog/day_92__S3.mdwn view
@@ -0,0 +1,23 @@+Amazon S3 was the second most popular choice in the+[[polls/prioritizing_special_remotes]] poll, and since I'm not sure how+I want to support phone/mp3 players, I did it first.++So I added a configurator today to easily set up an Amazon S3 repository.+That was straightforward and didn't take long since git-annex already+supported S3.++The hard part, of course, is key distribution. Since the webapp so far+can only configure the shared encryption method, and not fullblown gpg keys,+I didn't feel it would be secure to store the S3 keys in the git repository.+Anyone with access to that git repo would have full access to S3 ... just not+acceptable. Instead, the webapp stores the keys in a 600 mode file locally,+and they're not distributed at all.++When the same S3 repository is enabled on another computer, it prompts for+keys then too. I did add a hint about using the IAM Management Console in+this case -- it should be possible to set up users in IAM who can only+access a single bucket, although I have not tried to set that up.++---++Also, more work on the standalone OSX app.
+ doc/design/assistant/blog/day_93__OSX_standalone_app.mdwn view
@@ -0,0 +1,23 @@+Various bug fixes, and work on the OSX app today:++* Avoid crashing when ssh-keygen fails due to not being able to parse+  `authorized_keys`.. seems a lot of people have crufty unparsable+  `authorized_keys` files.+* On OSX, for some reason the webapp was failing to start sometimes due+  to bind failing with EINVAL. I don't understand why, as that should+  only happen if the socket is already bound, which it should not as+  it's just been created. I was able to work around this by retrying+  with a new socket when bind fails.+* When setting up `authorized_keys` to let `git-annex-shell` be run,+  it had been inserting a perl oneliner into it. I changed that+  to instead call a `~/.ssh/git-annex-shell` wrapper script that it sets+  up. The benefits are it no longer needs perl, and it's less ugly,+  and the standalone OSX app can modify the wrapper script to point to+  wherever it's installed today (people like to move these things around I+  guess).+* Made the standalone OSX app set up autostarting when it's first run.+* Spent rather a long time collecting the licenses of all the software that+  will be bundled with the standalone OSX app. Ended up with a file+  containing 3954 lines of legalese. Happily, all the software appears+  redistributable, and free software; even the couple of OSX system libraries+  we're bundling are licensed under the APSL.
+ doc/design/assistant/blog/day_93__easy_install.mdwn view
@@ -0,0 +1,34 @@+I hear that people want the git-annex assistant to be easy to install+without messing about building it from source..++## on OSX++So Jimmy and I have been working all week on making an easily installed OSX+app of the assistant. This is a .dmz file that bundles all the dependencies+(git, etc) in, so it can be installed with one click.++It seems to basically work. You can get it [[here|install/OSX]].++Unfortunatly, the [[bugs/pasting_into_annex_on_OSX]] bug resurfaced while+testing this.. So I can't really recommend using it on real data yet.++Still, any testing you can do is gonna be really helpful. I'm squashing OSX+bugs right and left.++## on Linux++First of all, the git-annex assistant is now available in Debian unstable,+and in Arch Linux's AUR. Proper packages.++For all the other Linux distributions, I have a workaround. It's+a big hack, but it seems to work.. at least on Debian stable.++I've just put up a [[install/linux_standalone]] tarball, which has **no+library dependencies** apart from glibc, and doesn't even need git to be+installed on your system.++## on FreeBSD++The FreeBSD port has been updated to include the git-annex assistant too..++[[!meta title="day 94 easy install"]]
doc/design/assistant/cloud.mdwn view
@@ -28,6 +28,20 @@ or some other repo in the cloud she pushed to. Once both steps are done, the assistant will transfer the file from the cloud to Bob. +* dvcs-autosync uses jabber; all repos need to have the same jabber account+  configured, and send self-messages. An alternative would be to have+  different accounts that join a channel or message each other. Still needs+  account configuration.+* irc could be used. With a default irc network, and an agreed-upon channel,+  no configuration should be needed. IRC might be harder to get through+  some firewalls, and is prone to netsplits, etc. IRC networks have reasons+  to be wary of bots using them. Only basic notifications could be done over+  irc, as it has little security.+* When there's a ssh server involved, code could be run on it to notify+  logged-in clients. But this is not a general solution to this problem.+* pubsubhubbub does not seem like an option; its hubs want to pull down+  a feed over http.+ ## storing git repos in the cloud  Of course, one option is to just use github etc to store the git repo.
+ doc/design/assistant/comment_16_8e6788c817c60371d2a2f158e1a65f87._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="https://launchpad.net/~gdr-go2"+ nickname="gdr-go2"+ subject="Maybe a DEB?2"+ date="2012-09-27T09:44:14Z"+ content="""+Month 3 was all about easy setup, so I kind of expected to download a deb package and just install it, not to download a whole bunch of haskell libraries. Is there a chance that you will release some packages?+"""]]
+ doc/design/assistant/comment_17_97bdfacac5ac492281c9454ee4c0228e._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="http://joeyh.name/"+ ip="4.153.14.141"+ subject="comment 17"+ date="2012-09-27T18:44:11Z"+ content="""+@gdr A package with the assistant is available in Debian unstable.+"""]]
doc/design/assistant/polls/prioritizing_special_remotes.mdwn view
@@ -6,7 +6,7 @@ Help me prioritize my work: What special remote would you most like to use with the git-annex assistant? -[[!poll open=yes 14 "Amazon S3" 8 "Amazon Glacier" 6 "Box.com" 44 "My phone (or MP3 player)" 4 "Tahoe-LAFS" 3 "OpenStack SWIFT" 12 "Google Drive"]]+[[!poll open=yes 14 "Amazon S3 (done)" 9 "Amazon Glacier" 6 "Box.com" 49 "My phone (or MP3 player)" 7 "Tahoe-LAFS" 3 "OpenStack SWIFT" 14 "Google Drive"]]  This poll is ordered with the options I consider easiest to build listed first. Mostly because git-annex already supports them and they
doc/design/assistant/webapp.mdwn view
@@ -25,6 +25,8 @@   over http by the web app * Display the `inotify max_user_watches` exceeded message. **done** * Display something sane when kqueue runs out of file descriptors.+* allow renaming git remotes and/or setting git-annex repo descriptions+* allow removing git remotes  ## first start **done** 
+ doc/forum/Trouble_installing_from_cabal_on_debian-testing.mdwn view
@@ -0,0 +1,15 @@+I'm having trouble install from cabal on Debian-testing since the new beta released.++    % sudo aptitude remove --purge cabal-install+    % rm -rf $HOME/.cabal+    % sudo aptitude install cabal-install+    % cabal update+    % cabal install git-annex++The output all follows this general syntax:++    <package> depends on <anotherpackage> which failed to install++On the flip side, I upgrade my Debian to sid and it installed just fine through aptitude.++(Apologies for my English, and if this is simply a user error)
+ doc/forum/linux_standalone_tarballs.mdwn view
@@ -0,0 +1,1 @@+Just saw that there is now a linux standalone tarball, I've a SL5 (RHEL5) based machine which I can churn out git-annex binaries if there is interest.
doc/git-annex.mdwn view
@@ -258,10 +258,26 @@   With parameters, only the specified files are checked.    To check a remote to fsck, specify --from.-  +   To avoid expensive checksum calculations (and expensive transfers when-  fscking a remote), specify --fast+  fscking a remote), specify --fast. +  To start a new incremental fsck, specify --incremental. Then+  the next time you fsck, you can specify --more to skip over+  files that have already been checked, and continue where it left off.++  The --incremental-schedule option makes a new incremental fsck be+  started a configurable time after the last incremental fsck was started.+  Once the current incremental fsck has completely finished, it causes+  a new one to start.+ +  Maybe you'd like to run a fsck for 5 hours at night, picking up each+  night where it left off. You'd like this to continue until all files+  have been fscked. And once it's done, you'd like a new fsck pass to start,+  but no more often than once a month. Then put this in a nightly cron job:++	git annex fsck --incremental-schedule 30d --time-limit 5h+ * unused    Checks the annex for data that does not correspond to any files present@@ -510,6 +526,17 @@   Overrides the `annex.numcopies` setting, forcing git-annex to ensure the   specified number of copies exist. +* --time-limit=time++  Limits how long a git-annex command runs. The time can be something+  like "5h", or "30m" or even "45s" or "10d".++  Note that git-annex may continue running a little past the specified+  time limit, in order to finish processing a file.++  Also, note that if the time limit prevents git-annex from doing all it +  was asked to, it will exit with a special code, 101.+ * --trust=repository * --semitrust=repository * --untrust=repository@@ -583,6 +610,12 @@   of copies, or more. Note that it does not check remotes to verify that   the copies still exist. +* --copies=trustlevel:number++  Matches only files that git-annex believes have the specified number of+  copies, on remotes with the specified trust level. For example,+  "--copies=trusted:2"+ * --inbackend=name    Matches only files whose content is stored using the specified key-value@@ -755,7 +788,7 @@ * `remote.<name>.annex-bup-split-options`    Options to pass to bup split when storing content in this remote.-  For example, to limit the bandwidth to 100Kbye/s, set it to "--bwlimit 100k"+  For example, to limit the bandwidth to 100Kbyte/s, set it to "--bwlimit 100k"   (There is no corresponding option for bup join.)  * `annex.ssh-options`, `annex.rsync-options`, `annex.bup-split-options`
doc/index.mdwn view
@@ -5,8 +5,7 @@ [[!sidebar content=""" [[!img logo_small.png link=no]] -* **[[download]]**-* [[install]]+* **[[install]]** * [[assistant]] * [[tips]] * [[bugs]]
doc/install.mdwn view
@@ -1,85 +1,34 @@-## OS-specific instructions+## Pick your OS -* [[OSX]]-* [[Debian]]-* [[Ubuntu]]-* [[Fedora]]-* [[FreeBSD]]-* [[openSUSE]]-* [[ArchLinux]]-* [[NixOS]]-* [[Gentoo]]-* [[ScientificLinux5]] - This should cover RHEL5 clones such as CentOS5 and so on-* Windows: [[sorry, not possible yet|todo/windows_support]]+Quick commands given where possible, but see the individual pages for+details. +[[!table format=dsv header=no data="""+[[OSX]]              | [download git-annex.app](http://downloads.kitenet.net/git-annex/OSX/git-annex.dmg.bz2) **beta**+[[Linux|linux_standalone]] | [download prebuilt linux tarball](http://downloads.kitenet.net/git-annex/linux/)+[[Debian]]           | `apt-get install git-annex`+[[Ubuntu]]           | `apt-get install git-annex`+[[FreeBSD]]          | `pkg_add -r hs-git-annex`+[[ArchLinux]]        | `yaourt -Sy git-annex`+[[NixOS]]            | `nix-env -i git-annex`+[[Gentoo]]           | `emerge git-annex`+[[ScientificLinux5]] | (and other RHEL5 clones like CentOS5)+[[Fedora]]           | +[[openSUSE]]         | +Windows              | [[sorry, Windows not supported yet|todo/windows_support]]+"""]]+ ## Using cabal -As a haskell package, git-annex can be installed using cabal. For example:+As a haskell package, git-annex can be installed using cabal.+Start by installing the [Haskell Platform](http://hackage.haskell.org/platform/),+and then:  	cabal install git-annex --bindir=$HOME/bin -The above downloads the latest release. Alternatively, you can [[download]]-it yourself and [[manually_build_with_cabal|install/cabal]].--## Installation by hand--This is not recommended, it's easier to let cabal pull in the many haskell-libraries. To build and use git-annex by hand, you will need:+That installs the latest release. Alternatively, you can [[download]]+git-annex yourself and [[manually_build_with_cabal|install/cabal]]. -* Haskell stuff-  * [The Haskell Platform](http://haskell.org/platform/) (GHC 7.4 or newer)-  * [MissingH](http://github.com/jgoerzen/missingh/wiki)-  * [pcre-light](http://hackage.haskell.org/package/pcre-light)-  * [utf8-string](http://hackage.haskell.org/package/utf8-string)-  * [SHA](http://hackage.haskell.org/package/SHA)-  * [dataenc](http://hackage.haskell.org/package/dataenc)-  * [monad-control](http://hackage.haskell.org/package/monad-control)-  * [lifted-base](http://hackage.haskell.org/package/lifted-base)-  * [TestPack](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/testpack)-  * [QuickCheck 2](http://hackage.haskell.org/package/QuickCheck)-  * [HTTP](http://hackage.haskell.org/package/HTTP)-  * [json](http://hackage.haskell.org/package/json)-  * [IfElse](http://hackage.haskell.org/package/IfElse)-  * [bloomfilter](http://hackage.haskell.org/package/bloomfilter)-  * [edit-distance](http://hackage.haskell.org/package/edit-distance)-  * [hS3](http://hackage.haskell.org/package/hS3) (optional)-* Optional haskell stuff, used by the [[assistant]] and its webapp (edit Makefile to disable)-  * [stm](http://hackage.haskell.org/package/stm)-    (version 2.3 or newer)-  * [hinotify](http://hackage.haskell.org/package/hinotify)-    (Linux only)-  * [dbus](http://hackage.haskell.org/package/dbus)-  * [yesod](http://hackage.haskell.org/package/yesod)-  * [yesod-static](http://hackage.haskell.org/package/yesod-static)-  * [yesod-default](http://hackage.haskell.org/package/yesod-default)-  * [data-default](http://hackage.haskell.org/package/data-default)-  * [case-insensitive](http://hackage.haskell.org/package/case-insensitive)-  * [http-types](http://hackage.haskell.org/package/http-types)-  * [transformers](http://hackage.haskell.org/package/transformers)-  * [wai](http://hackage.haskell.org/package/wai)-  * [wai-logger](http://hackage.haskell.org/package/wai-logger)-  * [warp](http://hackage.haskell.org/package/warp)-  * [blaze-builder](http://hackage.haskell.org/package/blaze-builder)-  * [blaze-html](http://hackage.haskell.org/package/blaze-html)-  * [crypto-api](http://hackage.haskell.org/package/crypto-api)-  * [hamlet](http://hackage.haskell.org/package/hamlet)-  * [clientsession](http://hackage.haskell.org/package/clientsession)-  * [network-multicast](http://hackage.haskell.org/package/network-multicast)-  * [network-info](http://hackage.haskell.org/package/network-info)-* Shell commands-  * [git](http://git-scm.com/)-  * [uuid](http://www.ossp.org/pkg/lib/uuid/)-    (or `uuidgen` from util-linux)-  * [xargs](http://savannah.gnu.org/projects/findutils/)-  * [rsync](http://rsync.samba.org/)-  * [wget](http://www.gnu.org/software/wget/) or [curl](http://http://curl.haxx.se/) (optional, but recommended)-  * [sha1sum](ftp://ftp.gnu.org/gnu/coreutils/) (optional, but recommended;-    a sha1 command will also do)-  * [gpg](http://gnupg.org/) (optional; needed for encryption)-  * [lsof](ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/)-    (optional; recommended for watch mode)-  * multicast DNS support, provided on linux by [nss-mdns](http://www.0pointer.de/lennart/projects/nss-mdns/)-    (optional; recommended for the assistant to support pairing well)-  * [ikiwiki](http://ikiwiki.info) (optional; used to build the docs)+## Installation from scratch -Then just [[download]] git-annex and run: `make; make install`+This is not recommended, but if you really want to, see [[fromscratch]].
+ doc/install/Linux_standalone.mdwn view
@@ -0,0 +1,11 @@+If your Linux distribution does not have git-annex packaged up for you,+you can either build it [[fromscratch]], or you can use a handy+prebuilt tarball.++This tarball should work on most Linux systems. It does not depend+on anything except for glibc.++[download tarball](http://downloads.kitenet.net/git-annex/linux/)+ +Warning: This is a last resort. Most Linux users should instead+[[install]] git-annex from their distribution of choice.
doc/install/OSX.mdwn view
@@ -1,3 +1,23 @@+## git-annex.app++For easy installation, [Jimmy Tang](http://www.sgenomics.org/~jtang/)+builds a standalone git-annex.app of the git-annex assistant.++* [beta release of git-annex.app](http://downloads.kitenet.net/git-annex/OSX/git-annex.dmg.bz2)+* [daily build of git-annex.app](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++## using Brew++<pre>+sudo brew update+sudo brew install haskell-platform git ossp-uuid md5sha1sum coreutils pcre+cabal update+cabal install git-annex --bindir=$HOME/bin+</pre>++## using MacPorts+ Install the Haskell Platform from [[http://hackage.haskell.org/platform/mac.html]]. The version provided by Macports is too old to work with current versions of git-annex. Then execute@@ -10,6 +30,8 @@ sudo cabal update cabal install git-annex --bindir=$HOME/bin </pre>++## PATH setup  Do not forget to add to your PATH variable your ~/bin folder. In your .bashrc, for example: <pre>
− doc/install/OSX/comment_1_0a1760bf0db1f1ba89bdb4c62032f631._comment
@@ -1,13 +0,0 @@-[[!comment format=mdwn- username="http://www.schleptet.net/~cfm/"- ip="64.30.148.100"- subject="comment 1"- date="2011-08-30T14:31:36Z"- content="""-You can also use Homebrew instead of MacPorts.  Homebrew's `haskell-platform` is up-to-date, too:--    brew install haskell-platform git ossp-uuid md5sha1sum coreutils pcre-    ln -s /usr/local/include/pcre.h /usr/include/pcre.h--As of this writing, however, Homebrew's `md5sha1sum` has a broken mirror.  I wound up getting that from MacPorts anyway.-"""]]
doc/install/OSX/comment_2_25552ff2942048fafe97d653757f1ad6._comment view
@@ -4,4 +4,5 @@  date="2012-07-24T15:09:29Z"  content=""" I've moved some outdated comments about installing on OSX to [[old_comments]].+And also moved away some comments that helped build the instructions above. """]]
− doc/install/OSX/comment_3_733147cebe501c60f2141b711f1d7f24._comment
@@ -1,16 +0,0 @@-[[!comment format=mdwn- username="https://www.google.com/accounts/o8/id?id=AItOawnnIQkoUQo4RYzjUNyiB3v6yJ5aR41WG8k"- nickname="Markus"- subject="Updated install instructions with homebrew"- date="2012-08-07T06:46:47Z"- content="""-To install git annex with homebrew simply do:--    brew update-    brew install haskell-platform git ossp-uuid md5sha1sum coreutils pcre-    cabal install git-annex--Then link the binary to your `PATH` e.g. with--    ln -s ~/.cabal/bin/git-annex* /usr/local/bin/-"""]]
− doc/install/OSX/comment_4_d513e21512a9b207983d38abf348d00f._comment
@@ -1,16 +0,0 @@-[[!comment format=mdwn- username="https://www.google.com/accounts/o8/id?id=AItOawm_-2XlXNyd6cCLI4n_jaBNqVUOWwJquko"- nickname="David"- subject="installing via homebrew"- date="2012-09-05T11:11:55Z"- content="""-I had to:--    cabal update--before:--    cabal install git-annex---"""]]
+ doc/install/fromscratch.mdwn view
@@ -0,0 +1,60 @@+To install git-annex from scratch, you need a lot of stuff. Really+quite a lot.++* Haskell stuff+  * [The Haskell Platform](http://haskell.org/platform/) (GHC 7.4 or newer)+  * [MissingH](http://github.com/jgoerzen/missingh/wiki)+  * [pcre-light](http://hackage.haskell.org/package/pcre-light)+  * [utf8-string](http://hackage.haskell.org/package/utf8-string)+  * [SHA](http://hackage.haskell.org/package/SHA)+  * [dataenc](http://hackage.haskell.org/package/dataenc)+  * [monad-control](http://hackage.haskell.org/package/monad-control)+  * [lifted-base](http://hackage.haskell.org/package/lifted-base)+  * [TestPack](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/testpack)+  * [QuickCheck 2](http://hackage.haskell.org/package/QuickCheck)+  * [HTTP](http://hackage.haskell.org/package/HTTP)+  * [json](http://hackage.haskell.org/package/json)+  * [IfElse](http://hackage.haskell.org/package/IfElse)+  * [bloomfilter](http://hackage.haskell.org/package/bloomfilter)+  * [edit-distance](http://hackage.haskell.org/package/edit-distance)+  * [hS3](http://hackage.haskell.org/package/hS3) (optional)+* Optional haskell stuff, used by the [[assistant]] and its webapp (edit Makefile to disable)+  * [stm](http://hackage.haskell.org/package/stm)+    (version 2.3 or newer)+  * [hinotify](http://hackage.haskell.org/package/hinotify)+    (Linux only)+  * [dbus](http://hackage.haskell.org/package/dbus)+  * [yesod](http://hackage.haskell.org/package/yesod)+  * [yesod-static](http://hackage.haskell.org/package/yesod-static)+  * [yesod-default](http://hackage.haskell.org/package/yesod-default)+  * [data-default](http://hackage.haskell.org/package/data-default)+  * [case-insensitive](http://hackage.haskell.org/package/case-insensitive)+  * [http-types](http://hackage.haskell.org/package/http-types)+  * [transformers](http://hackage.haskell.org/package/transformers)+  * [wai](http://hackage.haskell.org/package/wai)+  * [wai-logger](http://hackage.haskell.org/package/wai-logger)+  * [warp](http://hackage.haskell.org/package/warp)+  * [blaze-builder](http://hackage.haskell.org/package/blaze-builder)+  * [blaze-html](http://hackage.haskell.org/package/blaze-html)+  * [crypto-api](http://hackage.haskell.org/package/crypto-api)+  * [hamlet](http://hackage.haskell.org/package/hamlet)+  * [clientsession](http://hackage.haskell.org/package/clientsession)+  * [network-multicast](http://hackage.haskell.org/package/network-multicast)+  * [network-info](http://hackage.haskell.org/package/network-info)+* Shell commands+  * [git](http://git-scm.com/)+  * [uuid](http://www.ossp.org/pkg/lib/uuid/)+    (or `uuidgen` from util-linux)+  * [xargs](http://savannah.gnu.org/projects/findutils/)+  * [rsync](http://rsync.samba.org/)+  * [wget](http://www.gnu.org/software/wget/) or [curl](http://http://curl.haxx.se/) (optional, but recommended)+  * [sha1sum](ftp://ftp.gnu.org/gnu/coreutils/) (optional, but recommended;+    a sha1 command will also do)+  * [gpg](http://gnupg.org/) (optional; needed for encryption)+  * [lsof](ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/)+    (optional; recommended for watch mode)+  * multicast DNS support, provided on linux by [nss-mdns](http://www.0pointer.de/lennart/projects/nss-mdns/)+    (optional; recommended for the assistant to support pairing well)+  * [ikiwiki](http://ikiwiki.info) (optional; used to build the docs)++Then just [[download]] git-annex and run: `make; make install`
doc/license.mdwn view
@@ -10,5 +10,5 @@  git-annex contains a variety of other code, artwork, etc copyright by others, under a variety of licences, including the [[LGPL]], BSD,-MIT, and Apache 2.0 license. For a detailed overview, and pointers to the-full licenses of these components, see the COPYRIGHT file in the source.+MIT, and Apache 2.0 licenses. For details, see+[this file](http://source.git-annex.branchable.com/?p=source.git;a=blob_plain;f=debian/copyright;hb=HEAD).
− doc/news/.version_3.20120924.mdwn.swp

binary file changed (4096 → absent bytes)

− doc/news/version_3.20120629.mdwn
@@ -1,12 +0,0 @@-git-annex 3.20120629 released with [[!toggle text="these changes"]]-[[!toggleable text="""-   * cabal: Only try to use inotify on Linux.-   * Version build dependency on STM, and allow building without it,-     which disables the watch command.-   * Avoid ugly failure mode when moving content from a local repository-     that is not available.-   * Got rid of the last place that did utf8 decoding.-   * Accept arbitrarily encoded repository filepaths etc when reading-     git config output. This fixes support for remotes with unusual characters-     in their names.-   * sync: Automatically resolves merge conflicts."""]]
doc/news/version_3.20120924.mdwn view
@@ -2,6 +2,8 @@ [[!toggleable text="""    * assistant: New command, a daemon which does everything watch does,      as well as automatically syncing file contents between repositories.+     See [[assistant]] for details and [[assistant/errata]] for known+     issues in this beta feature.    * webapp: An interface for managing and configuring the assistant.    * The default backend used when adding files to the annex is changed      from SHA256 to SHA256E, to simplify interoperability with OSX, media
+ doc/news/version_3.20121001.mdwn view
@@ -0,0 +1,27 @@+git-annex 3.20121001 released with [[!toggle text="these changes"]]+[[!toggleable text="""+   * fsck: Now has an incremental mode. Start a new incremental fsck pass+     with git annex fsck --incremental. Now the fsck can be interrupted+     as desired, and resumed with git annex fsck --more.+     Thanks, Justin Azoff+   * New --time-limit option, makes long git-annex commands stop after+     a specified amount of time.+   * fsck: New --incremental-schedule option which is nice for scheduling+     eg, monthly incremental fsck runs in cron jobs.+   * Fix fallback to ~/Desktop when xdg-user-dir is not available.+     Closes: #[688833](http://bugs.debian.org/688833)+   * S3: When using a shared cipher, S3 credentials are not stored encrypted+     in the git repository, as that would allow anyone with access to+     the repository access to the S3 account. Instead, they're stored+     in a 600 mode file in the local git repo.+   * webapp: Avoid crashing when ssh-keygen -F chokes on an invalid known\_hosts+     file.+   * Always do a system wide installation when DESTDIR is set. Closes: #[689052](http://bugs.debian.org/689052)+   * The Makefile now builds with the new yesod by default.+     Systems like Debian that have the old yesod 1.0.1 should set+     GIT\_ANNEX\_LOCAL\_FEATURES=-DWITH\_OLD\_YESOD+   * copy: Avoid updating the location log when no copy is performed.+   * configure: Test that uuid -m works, falling back to plain uuid if not.+   * Avoid building the webapp on Debian architectures that do not yet+     have template haskell and thus yesod. (Should be available for arm soonish+     I hope)."""]]
+ doc/not/comment_6_547fc59b19ad66d7280c53a7f923ea08._comment view
@@ -0,0 +1,13 @@+[[!comment format=mdwn+ username="https://www.google.com/accounts/o8/id?id=AItOawlatTbI0K-qydpeYHl37iseqPNvERcdIMk"+ nickname="Tiago"+ subject="comment 6"+ date="2012-09-27T10:17:18Z"+ content="""+Stefan: \"annex is for managing big binary files that not get modified most of the time and only added/synced or deleted.\"++While this is true,  the kickstarter title for assistant was \"Like dropbox\", and dropbox makes it transparent to edit files and they work with the filesystem.+So with assistant, lock/unlock should be automated and transparent to the user. Otherwise it's confusing and not simple at all to use, and at least OSX keeps giving errors because of the way it handles aliases.+So something like sharebox is essential to be included in assistant in my opinion.++"""]]
doc/special_remotes/S3.mdwn view
@@ -9,8 +9,10 @@ The standard environment variables `AWS_ACCESS_KEY_ID` and  `AWS_SECRET_ACCESS_KEY` are used to supply login credentials for Amazon. When encryption is enabled, they are stored in encrypted form-by `git annex initremote`, so you do not need to keep the environment-variables set after the initial initalization of the remote.+by `git annex initremote`. Without encryption, they are stored in a+file only you can read inside the local git repository. So you do not+need to keep the environment variables set after the initial+initalization of the remote.  A number of parameters can be passed to `git annex initremote` to configure the S3 remote.
+ doc/tips/setup_a_public_repository_on_a_web_site.mdwn view
@@ -0,0 +1,27 @@+Let's say you want to distribute some big files to the whole world.+You can of course, just drop them onto a website. But perhaps you'd like to+use git-annex to manage those files. And as an added bonus, why not let+anyone in the world clone your site and use `git-annex get`!++My site like this is [downloads.kitenet.net](http://downloads.kitenet.net).+Here's how I set it up. --[[Joey]]++1. Set up a web site. I used Apache, and configured it to follow symlinks.+   `Options FollowSymLinks`+2. Put some files on the website. Make sure it works.+4. `git init; git annex init`+3. We want users to be able to clone the git repository over http, because+   git-annex can download files from it over http as well. For this to+   work, `git update-server-info` needs to get run after commits. So+   put it in the git `post-update` hook.+5. `git annex add; git commit -m added`+6. Make sure users can still download files from the site directly.+7. Instruct advanced users to clone a http url that ends with the "/.git/"+   directory. For example, for downloads.kitenet.net, the clone url+   is `http://downloads.kitenet.net/.git/`++When users clone over http, and run git-annex, it will+automatically learn all about your repository and be able to download files+right out of it, also using http. ++Enjoy!
doc/todo/incremental_fsck.mdwn view
@@ -9,3 +9,11 @@ indicate the content has been fsked, and the mtime indicate the time of last fsck. Anything that dropped or put in content would need to clear the sticky bit. --[[Joey]] ++> Basic incremental fsck is done now.+> +> Some enhancements would include:+> +> * --max-age=30d  Once the incremental fsck completes and was started 30 days ago,+>   start a new one.+> * --time-limit --size-limit --file-limit: Limit how long the fsck runs.
+ doc/todo/wishlist:___96__git_annex_sync_-m__96__.mdwn view
@@ -0,0 +1,10 @@+Similar to how++    git commit -m 'foo'++works, if I run ++    git annex sync -m 'my hovercraft is full of eels'++git annex should use that commit message instead of the default ones. That way, I could use [[sync]] directly and not be forced to commit prior to syncing just to make sure I have a useful commit message.+
git-annex.1 view
@@ -234,8 +234,24 @@ To check a remote to fsck, specify \-\-from. .IP To avoid expensive checksum calculations (and expensive transfers when-fscking a remote), specify \-\-fast+fscking a remote), specify \-\-fast. .IP+To start a new incremental fsck, specify \-\-incremental. Then+the next time you fsck, you can specify \-\-more to skip over+files that have already been checked, and continue where it left off.+.IP+The \-\-incremental\-schedule option makes a new incremental fsck be+started a configurable time after the last incremental fsck was started.+Once the current incremental fsck has completely finished, it causes+a new one to start.+.IP+Maybe you'd like to run a fsck for 5 hours at night, picking up each+night where it left off. You'd like this to continue until all files+have been fscked. And once it's done, you'd like a new fsck pass to start,+but no more often than once a month. Then put this in a nightly cron job:+.IP+ git annex fsck \-\-incremental\-schedule 30d \-\-time\-limit 5h+.IP .IP "unused" Checks the annex for data that does not correspond to any files present in any tag or branch, and prints a numbered list of the data.@@ -453,6 +469,16 @@ Overrides the annex.numcopies setting, forcing git\-annex to ensure the specified number of copies exist. .IP+.IP "\-\-time\-limit=time"+Limits how long a git\-annex command runs. The time can be something+like "5h", or "30m" or even "45s" or "10d".+.IP+Note that git\-annex may continue running a little past the specified+time limit, in order to finish processing a file.+.IP+Also, note that if the time limit prevents git\-annex from doing all it +was asked to, it will exit with a special code, 101.+.IP .IP "\-\-trust=repository" .IP "\-\-semitrust=repository" .IP "\-\-untrust=repository"@@ -517,6 +543,11 @@ of copies, or more. Note that it does not check remotes to verify that the copies still exist. .IP+.IP "\-\-copies=trustlevel:number"+Matches only files that git\-annex believes have the specified number of+copies, on remotes with the specified trust level. For example,+"\-\-copies=trusted:2"+.IP .IP "\-\-inbackend=name" Matches only files whose content is stored using the specified key\-value backend.@@ -660,7 +691,7 @@ .IP .IP "remote.<name>.annex\-bup\-split\-options" Options to pass to bup split when storing content in this remote.-For example, to limit the bandwidth to 100Kbye/s, set it to "\-\-bwlimit 100k"+For example, to limit the bandwidth to 100Kbyte/s, set it to "\-\-bwlimit 100k" (There is no corresponding option for bup join.) .IP .IP "annex.ssh\-options, annex.rsync\-options, annex.bup\-split\-options"
git-annex.cabal view
@@ -1,5 +1,5 @@ Name: git-annex-Version: 3.20120924+Version: 3.20121001 Cabal-Version: >= 1.8 License: GPL Maintainer: Joey Hess <joey@kitenet.net>@@ -88,9 +88,6 @@   if flag(Pairing) && flag(Webapp)     Build-Depends: network-multicast, network-info     CPP-Options: -DWITH_PAIRING--  if os(darwin)-    CPP-Options: -DOSX  Test-Suite test   Type: exitcode-stdio-1.0
+ standalone/licences.gz view

binary file changed (absent → 55614 bytes)

+ standalone/linux/README view
@@ -0,0 +1,23 @@+To start the git-annex webapp, run the git-annex-webapp script in this+directory.++To enter an environment with git-annex in PATH, use runshell++This should work on any Linux system of the appropriate architecture.+More or less. There are no external dependencies, except for glibc.+Any recent-ish version of glibc should work (2.13 is ok; so is 2.11).+++How it works: This directory contains a lot of libraries and programs+that git-annex needs. But it's not a chroot. Instead, runshell sets+PATH and LD_LIBRARY_PATH to point to the stuff in this directory.++The glibc libs are not included. Instead, it runs with the host system's+glibc. We trust that glibc's excellent backwards and forward compatability+is good enough to run binaries that were linked for a newer or older+version. Of course, this could fail. Particularly if the binaries try to+use some new glibc feature. But hopefully not.++Why not bundle glibc too? I've not gotten it to work! The host system's +ld-linux.so will be used for sure, as that's hardcoded into the binaries.+When I tried including libraries from glibc in here, everything segfaulted.
+ standalone/linux/git-annex-webapp view
@@ -0,0 +1,25 @@+#!/bin/sh+base="$(dirname $0)"+if [ ! -d "$base" ]; then+	echo "** cannot find base directory (I seem to be $0)" >&2+	exit 1+fi+if [ ! -e "$base/runshell" ]; then+	echo "** cannot find $base/runshell" >&2+	exit 1+fi++# Get absolute path to base, to avoid breakage when things change directories.+orig="$(pwd)"+cd "$base"+base="$(pwd)"+cd "$orig"++# If this is a standalone app, set a variable that git-annex can use to+# install itself.+if [ -e "$base/bin/git-annex" ]; then+	GIT_ANNEX_APP_BASE="$base"+	export GIT_ANNEX_APP_BASE+fi++"$base/runshell" git-annex webapp "$@"
+ standalone/linux/glibc-libs view
@@ -0,0 +1,43 @@+libanl-.*.so+libutil-.*.so+libnss_hesiod-.*.so+libcrypt-.*.so+libnss_compat-.*.so+libm-.*.so+libr.so+libpcprofile.so+libnss_nis-.*.so+libSegFault.so+libpthread-.*.so+librt-.*.so+libnss_dns-.*.so+libdl-.*.so+libBrokenLocale-.*.so+libnss_nisplus-.*.so+libthread_db-1.0.so+libmemusage.so+libcidn-.*.so+libnss_files-.*.so+libnsl-.*.so+libc-.*.so+ld-.*.so+libnss_nis.so+libthread_db.so+libanl.so+libr.so+libnss_compat.so+libm.so+libnss_dns.so+libpthread.so+libc.so+librt.so+libcidn.so+libnss_nisplus.so+libnsl.so+libutil.so+libBrokenLocale.so+ld-linux.so+libnss_files.so+libdl.so+libnss_hesiod.so+libcrypt.so
+ standalone/linux/runshell view
@@ -0,0 +1,48 @@+#!/bin/sh+# Runs a shell command (or interactive shell) using the binaries and+# libraries bundled with this app.++set -e++base="$(dirname $0)"++if [ ! -d "$base" ]; then+	echo "** cannot find base directory (I seem to be $0)" >&2+	exit 1+fi++if [ ! -e "$base/bin/git-annex" ]; then+	echo "** base directory $base does not contain bin/git-annex" >&2+	exit 1+fi+if [ ! -e "$base/bin/git" ]; then+	echo "** base directory $base does not contain bin/git" >&2+	exit 1+fi++# Get absolute path to base, to avoid breakage when things change directories.+orig="$(pwd)"+cd "$base"+base="$(pwd)"+cd "$orig"++# Put our binaries first, to avoid issues with out of date or incompatable+# system binaries.+PATH=$base/bin:$PATH+export PATH++for lib in $(cat $base/libdirs); do+	LD_LIBRARY_PATH="$base/$lib:$LD_LIBRARY_PATH"+done+export LD_LIBRARY_PATH++GIT_EXEC_PATH=$base/git-core+export GIT_EXEC_PATH++if [ "$1" ]; then+	cmd="$1"+	shift 1+	exec "$cmd" "$@"+else+	$SHELL+fi
+ standalone/osx/git-annex.app/Contents/Info.plist view
@@ -0,0 +1,45 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">+<plist version="1.0">+<dict>+	<key>CFBundleDevelopmentRegion</key>+	<string>English</string>+	<key>CFBundleExecutable</key>+	<string>git-annex-webapp</string>+	<key>NSHumanReadableCopyright</key>+	<string>GPL 3</string>+	<key>CFBundleGetInfoString</key>+	<string>0.0.1</string>+	<key>CFBundleIconFile</key>+	<string>git-annex</string>+	<key>CFBundleIdentifier</key>+	<string>com.branchable.git-annex</string>+	<key>CFBundleInfoDictionaryVersion</key>+	<string>6.0</string>+	<key>CFBundleName</key>+	<string>GIT-ANNEX</string>+	<key>CFBundlePackageType</key>+	<string>APPL</string>+	<key>CFBundleShortVersionString</key>+	<string>0.0.1</string>+	<key>CFBundleSignature</key>+	<string>git-annex</string>+	<key>CFBundleVersion</key>+	<string>0.0.1</string>+	<key>NSAppleScriptEnabled</key>+	<true/>+	<key>CGDisableCoalescedUpdates</key>+	<true/>+	<key>LSMinimumSystemVersion</key>+	<string>10.5</string>+	<key>CFBundleDisplayName</key>+	<string>Start git-annex webapp</string>+	<key>LSMinimumSystemVersionByArchitecture</key>+	<dict>+		<key>i386</key>+		<string>10.5.0</string>+		<key>x86_64</key>+		<string>10.6.0</string>+	</dict>+</dict>+</plist>
+ standalone/osx/git-annex.app/Contents/MacOS/git-annex-webapp view
@@ -0,0 +1,25 @@+#!/bin/sh+base="$(dirname $0)"+if [ ! -d "$base" ]; then+	echo "** cannot find base directory (I seem to be $0)" >&2+	exit 1+fi+if [ ! -e "$base/runshell" ]; then+	echo "** cannot find $base/runshell" >&2+	exit 1+fi++# Get absolute path to base, to avoid breakage when things change directories.+orig="$(pwd)"+cd "$base"+base="$(pwd)"+cd "$orig"++# If this is a standalone app, set a variable that git-annex can use to+# install itself.+if [ -e "$base/bin/git-annex" ]; then+	GIT_ANNEX_APP_BASE="$base"+	export GIT_ANNEX_APP_BASE+fi++"$base/runshell" git-annex webapp "$@"
+ standalone/osx/git-annex.app/Contents/MacOS/runshell view
@@ -0,0 +1,53 @@+#!/bin/sh+# Runs a shell command (or interactive shell) using the binaries and+# libraries bundled with this app.++set -e++base="$(dirname $0)"++if [ ! -d "$base" ]; then+	echo "** cannot find base directory (I seem to be $0)" >&2+	exit 1+fi++if [ ! -e "$base/bin/git-annex" ]; then+	echo "** base directory $base does not contain bin/git-annex" >&2+	exit 1+fi+if [ ! -e "$base/bin/git" ]; then+	echo "** base directory $base does not contain bin/git" >&2+	exit 1+fi++# Get absolute path to base, to avoid breakage when things change directories.+orig="$(pwd)"+cd "$base"+base="$(pwd)"+cd "$orig"++# Put our binaries first, to avoid issues with out of date or incompatable+# system binaries.+PATH=$base/bin:$PATH+export PATH++# Using DYLD_FALLBACK_LIBRARY_PATH rather than DYLD_LIBRARY_PATH, so as+# not to force binaries to link against possibly the wrong versions of+# libraries found in the path. With DYLD_FALLBACK_LIBRARY_PATH, the+# system's versions of libraries will be used when possible, and otherwise+# it will fall back to using the libraries bundled with this app.+for lib in $(cat $base/libdirs); do+	DYLD_FALLBACK_LIBRARY_PATH="$base/$lib:$DYLD_FALLBACK_LIBRARY_PATH"+done+export DYLD_FALLBACK_LIBRARY_PATH++GIT_EXEC_PATH=$base/git-core+export GIT_EXEC_PATH++if [ "$1" ]; then+	cmd="$1"+	shift 1+	exec "$cmd" "$@"+else+	$SHELL+fi
+ standalone/osx/git-annex.app/Contents/Resources/git-annex.icns view

binary file changed (absent → 52194 bytes)

templates/actionbutton.hamlet view
@@ -1,2 +1,2 @@-<a class="#{buttonclass}" href="@{route}" onclick="(function( $ ) { $.post('@{route}'); })( jQuery ); return false;">+<a title="#{fromMaybe "" tooltip}" class="#{buttonclass}" href="@{route}" onclick="(function( $ ) { $.post('@{route}'); })( jQuery ); return false;">   <i class="#{iconclass}"></i> #{fromMaybe "" label}
+ templates/configurators/adds3.hamlet view
@@ -0,0 +1,38 @@+<div .span9 .hero-unit>+  <h2>+    Adding an Amazon S3 repository+  <p>+    <a href="http://aws.amazon.com/s3/">Amazon S3</a> is a cloud storage #+    provider. If you need a professional level of storage for your data, #+    this is a good choice. #+    <a href="http://aws.amazon.com/s3/pricing/">+      Pricing details, including one year Free Usage Tier promotion+  <p>+    <i .icon-warning-sign></i> Do keep in mind that all your data #+    will be synced to Amazon S3. You will be charged by Amazon for data #+    uploaded to S3, as well as data downloaded from S3, and a monthly fee #+    for data storage. #+  <p>+    All data will be encrypted before being sent to Amazon S3.+  <p>+    When you sign up to Amazon S3, they provide you with an Access #+    Key ID, and a Secret Access Key. You will need to enter both below. #+    These access keys will be stored in a file that only you can #+    access. #+    <a href="https://portal.aws.amazon.com/gp/aws/securityCredentials#id_block">+      Look up your access keys+  <p>+    <form .form-horizontal enctype=#{enctype}>+      <fieldset>+        ^{form}+        ^{authtoken}+        <div .form-actions>+          <button .btn .btn-primary type=submit onclick="$('#workingmodal').modal('show');">+            Add S3 repository+<div .modal .fade #workingmodal>+  <div .modal-header>+    <h3>+      Making repository ...+  <div .modal-body>+    <p>+      Setting up your Amazon S3 repository. This could take a minute.
+ templates/configurators/enables3.hamlet view
@@ -0,0 +1,30 @@+<div .span9 .hero-unit>+  <h2>+    Enabling #{description}+  <p>+    To use this Amazon S3 repository, you need an Access Key ID, and a #+    Secret Access Key. These access keys will be stored in a file that #+    only you can access.+  <p>+    If this repository uses your Amazon S3 account, you can #+    <a href="https://portal.aws.amazon.com/gp/aws/securityCredentials#id_block">+      look up your access keys. #+    If this repository uses someone else's Amazon S3 account, they #+    can generate access keys for you, using their #+    <a href="https://console.aws.amazon.com/iam/home">+      IAM Management Console.+  <p>+    <form .form-horizontal enctype=#{enctype}>+      <fieldset>+        ^{form}+        ^{authtoken}+        <div .form-actions>+          <button .btn .btn-primary type=submit onclick="$('#workingmodal').modal('show');">+            Enable S3 repository+<div .modal .fade #workingmodal>+  <div .modal-header>+    <h3>+      Enabling repository ...+  <div .modal-body>+    <p>+      Enabling this Amazon S3 repository. This could take a minute.
templates/configurators/repositories.hamlet view
@@ -49,6 +49,11 @@         Save photos and recordings from your phone.       <p>         Send selected files to your phone.+      +      <h3>+        <i .icon-plus-sign></i> Network Attached Storage+      <p>+        Connect to a local storage appliance (NAS).      <div .span6>       <h2>@@ -61,9 +66,15 @@         Works very well with git-annex.        <h3>-        <i .icon-plus-sign></i> Amazon S3+        <a href="@{AddS3R}">+          <i .icon-plus-sign></i> Amazon S3       <p>         Good choice for professional storage quality and low prices.+      +      <h3>+        <i .icon-plus-sign></i> Amazon Glacier+      <p>+        Low cost offline data archival.        <h3>         <i .icon-plus-sign></i> Box.com
templates/dashboard/transfers.hamlet view
@@ -1,4 +1,10 @@ <div .span9 ##{ident}>+  $maybe reldir <- relDir webapp+    <div .alert .alert-info>+      <p>+        git-annex is watching over your files in #+        <small><tt>#{reldir}</tt></small>, #+        and keeping them in sync with other repositories.   $if null transfers   $else     <h2>Transfers@@ -31,7 +37,7 @@                 <div .bar style="width: #{percent};">           <div .btn-group .span2>             $if isrunning info-              ^{actionButton (PauseTransferR transfer) Nothing "btn" "icon-pause"}+              ^{actionButton (PauseTransferR transfer) Nothing (Just "pause") "btn" "icon-pause"}             $else-              ^{actionButton (StartTransferR transfer) Nothing "btn" "icon-play"}-            ^{actionButton (CancelTransferR transfer) Nothing "btn" "icon-remove"}+              ^{actionButton (StartTransferR transfer) Nothing (Just "continue") "btn" "icon-play"}+            ^{actionButton (CancelTransferR transfer) Nothing (Just "cancel") "btn" "icon-remove"}
templates/documentation/about.hamlet view
@@ -10,8 +10,19 @@   <hr>     git-annex is © 2010-2012 Joey Hess. It is free software, licensed #     under the terms of the GNU General Public License, version 3 or above. #+    This webapp is licensed under the terms of the GNU Affero General #+    Public License, version 3 or above. #+    For full license information, see #+    $if builtinlicense+      <a href="@{LicenseR}">+        this page.+    $else+      <a href="http://git-annex.branchable.com/license">+        this page.     <p>-    Its development was made possible by #+    Development git-annex was made possible by #     <a href="http://git-annex.branchable.com/assistant/thanks/">       many excellent people-    . <i .icon-heart></i>+    . &hearts;+    <p>+    Version: #{packageversion}
+ templates/documentation/license.hamlet view
@@ -0,0 +1,2 @@+<pre>+  #{license}
templates/page.hamlet view
@@ -11,7 +11,7 @@       $maybe reldir <- relDir webapp         <ul .nav .pull-right>           <li>-            ^{actionButton FileBrowserR (Just "Files") "" "icon-folder-open icon-white"}+            ^{actionButton FileBrowserR (Just "Files") (Just "Click to open a file browser") "" "icon-folder-open icon-white"}           <li .dropdown #menu1>             <a .dropdown-toggle data-toggle="dropdown" href="#menu1">               Current Repository: #{reldir}
− ui-macos/git-annex.app/Contents/Info.plist
@@ -1,45 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">-<plist version="1.0">-<dict>-	<key>CFBundleDevelopmentRegion</key>-	<string>English</string>-	<key>CFBundleExecutable</key>-	<string>git-annex</string>-	<key>NSHumanReadableCopyright</key>-	<string>GPL 3</string>-	<key>CFBundleGetInfoString</key>-	<string>0.0.1</string>-	<key>CFBundleIconFile</key>-	<string>git-annex</string>-	<key>CFBundleIdentifier</key>-	<string>com.branchable.git-annex</string>-	<key>CFBundleInfoDictionaryVersion</key>-	<string>6.0</string>-	<key>CFBundleName</key>-	<string>GIT-ANNEX</string>-	<key>CFBundlePackageType</key>-	<string>APPL</string>-	<key>CFBundleShortVersionString</key>-	<string>0.0.1</string>-	<key>CFBundleSignature</key>-	<string>git-annex</string>-	<key>CFBundleVersion</key>-	<string>0.0.1</string>-	<key>NSAppleScriptEnabled</key>-	<true/>-	<key>CGDisableCoalescedUpdates</key>-	<true/>-	<key>LSMinimumSystemVersion</key>-	<string>10.5</string>-	<key>CFBundleDisplayName</key>-	<string>Start git-annex webapp</string>-	<key>LSMinimumSystemVersionByArchitecture</key>-	<dict>-		<key>i386</key>-		<string>10.5.0</string>-		<key>x86_64</key>-		<string>10.6.0</string>-	</dict>-</dict>-</plist>
− ui-macos/git-annex.app/Contents/MacOS/git-annex
@@ -1,5 +0,0 @@-#!/bin/sh-# The contents of this file are not installed; instead a script -# is generated containing the full path to the real git-annex-# executable.-git annex webapp
− ui-macos/git-annex.app/Contents/Resources/git-annex.icns

binary file changed (52194 → absent bytes)