packages feed

git-annex 6.20160318 → 6.20160412

raw patch · 135 files changed

+3172/−738 lines, 135 files

Files

Annex.hs view
@@ -136,6 +136,7 @@ 	, workers :: [Either AnnexState (Async AnnexState)] 	, concurrentjobs :: Maybe Int 	, keysdbhandle :: Maybe Keys.DbHandle+	, cachedcurrentbranch :: Maybe Git.Branch 	}  newState :: GitConfig -> Git.Repo -> AnnexState@@ -182,6 +183,7 @@ 	, workers = [] 	, concurrentjobs = Nothing 	, keysdbhandle = Nothing+	, cachedcurrentbranch = Nothing 	}  {- Makes an Annex state object for the specified git repo.
+ Annex/AdjustedBranch.hs view
@@ -0,0 +1,509 @@+{- adjusted branch+ -+ - Copyright 2016 Joey Hess <id@joeyh.name>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++{-# LANGUAGE BangPatterns #-}++module Annex.AdjustedBranch (+	Adjustment(..),+	OrigBranch,+	AdjBranch(..),+	originalToAdjusted,+	adjustedToOriginal,+	fromAdjustedBranch,+	getAdjustment,+	enterAdjustedBranch,+	adjustBranch,+	adjustToCrippledFileSystem,+	updateAdjustedBranch,+	propigateAdjustedCommits,+	checkAdjustedClone,+) where++import Annex.Common+import qualified Annex+import Git+import Git.Types+import qualified Git.Branch+import qualified Git.Ref+import qualified Git.Command+import qualified Git.Tree+import qualified Git.DiffTree+import qualified Git.Merge+import Git.Tree (TreeItem(..))+import Git.Sha+import Git.Env+import Git.Index+import Git.FilePath+import qualified Git.LockFile+import Annex.CatFile+import Annex.Link+import Annex.AutoMerge+import Annex.Content+import Annex.Perms+import Annex.GitOverlay+import Utility.Tmp+import qualified Database.Keys++import qualified Data.Map as M++data Adjustment+	= UnlockAdjustment+	| LockAdjustment+	| HideMissingAdjustment+	| ShowMissingAdjustment+	deriving (Show, Eq)++reverseAdjustment :: Adjustment -> Adjustment+reverseAdjustment UnlockAdjustment = LockAdjustment+reverseAdjustment LockAdjustment = UnlockAdjustment+reverseAdjustment HideMissingAdjustment = ShowMissingAdjustment+reverseAdjustment ShowMissingAdjustment = HideMissingAdjustment++{- How to perform various adjustments to a TreeItem. -}+adjustTreeItem :: Adjustment -> TreeItem -> Annex (Maybe TreeItem)+adjustTreeItem UnlockAdjustment ti@(TreeItem f m s)+	| toBlobType m == Just SymlinkBlob = do+		mk <- catKey s+		case mk of+			Just k -> do+				Database.Keys.addAssociatedFile k f+				Just . TreeItem f (fromBlobType FileBlob)+					<$> hashPointerFile k+			Nothing -> return (Just ti)+	| otherwise = return (Just ti)+adjustTreeItem LockAdjustment ti@(TreeItem f m s)+	| toBlobType m /= Just SymlinkBlob = do+		mk <- catKey s+		case mk of+			Just k -> do+				absf <- inRepo $ \r -> absPath $+					fromTopFilePath f r+				linktarget <- calcRepo $ gitAnnexLink absf k+				Just . TreeItem f (fromBlobType SymlinkBlob)+					<$> hashSymlink linktarget+			Nothing -> return (Just ti)+	| otherwise = return (Just ti)+adjustTreeItem HideMissingAdjustment ti@(TreeItem _ _ s) = do+	mk <- catKey s+	case mk of+		Just k -> ifM (inAnnex k)+			( return (Just ti)+			, return Nothing+			)+		Nothing -> return (Just ti)+adjustTreeItem ShowMissingAdjustment ti = return (Just ti)++type OrigBranch = Branch+newtype AdjBranch = AdjBranch { adjBranch :: Branch }++-- This is a hidden branch ref, that's used as the basis for the AdjBranch,+-- since pushes can overwrite the OrigBranch at any time. So, changes+-- are propigated from the AdjBranch to the head of the BasisBranch.+newtype BasisBranch = BasisBranch Ref++-- The basis for refs/heads/adjusted/master(unlocked) is+-- refs/basis/adjusted/master(unlocked).+basisBranch :: AdjBranch -> BasisBranch+basisBranch (AdjBranch adjbranch) = BasisBranch $+	Ref ("refs/basis/" ++ fromRef (Git.Ref.base adjbranch))++adjustedBranchPrefix :: String+adjustedBranchPrefix = "refs/heads/adjusted/"++serialize :: Adjustment -> String+serialize UnlockAdjustment = "unlocked"+serialize LockAdjustment = "locked"+serialize HideMissingAdjustment = "present"+serialize ShowMissingAdjustment = "showmissing"++deserialize :: String -> Maybe Adjustment+deserialize "unlocked" = Just UnlockAdjustment+deserialize "locked" = Just UnlockAdjustment+deserialize "present" = Just HideMissingAdjustment+deserialize _ = Nothing++originalToAdjusted :: OrigBranch -> Adjustment -> AdjBranch+originalToAdjusted orig adj = AdjBranch $ Ref $+	adjustedBranchPrefix ++ base ++ '(' : serialize adj ++ ")"+  where+	base = fromRef (Git.Ref.basename orig)++adjustedToOriginal :: Branch -> Maybe (Adjustment, OrigBranch)+adjustedToOriginal b+	| adjustedBranchPrefix `isPrefixOf` bs = do+		let (base, as) = separate (== '(') (drop prefixlen bs)+		adj <- deserialize (takeWhile (/= ')') as)+		Just (adj, Git.Ref.under "refs/heads" (Ref base))+	| otherwise = Nothing+  where+	bs = fromRef b+	prefixlen = length adjustedBranchPrefix++getAdjustment :: Branch -> Maybe Adjustment+getAdjustment = fmap fst . adjustedToOriginal++fromAdjustedBranch :: Branch -> OrigBranch+fromAdjustedBranch b = maybe b snd (adjustedToOriginal b)++originalBranch :: Annex (Maybe OrigBranch)+originalBranch = fmap fromAdjustedBranch <$> inRepo Git.Branch.current++{- Enter an adjusted version of current branch (or, if already in an+ - adjusted version of a branch, changes the adjustment of the original+ - branch).+ -+ - Can fail, if no branch is checked out, or perhaps if staged changes+ - conflict with the adjusted branch.+ -}+enterAdjustedBranch :: Adjustment -> Annex ()+enterAdjustedBranch adj = go =<< originalBranch+  where+	go (Just origbranch) = do+		AdjBranch b <- preventCommits $ const $ +			adjustBranch adj origbranch+		showOutput -- checkout can have output in large repos+		inRepo $ Git.Command.run+			[ Param "checkout"+			, Param $ fromRef $ Git.Ref.base b+			]+	go Nothing = error "not on any branch!"++adjustToCrippledFileSystem :: Annex ()+adjustToCrippledFileSystem = do+	warning "Entering an adjusted branch where files are unlocked as this filesystem does not support locked files."+	whenM (isNothing <$> originalBranch) $+		void $ inRepo $ Git.Branch.commitCommand Git.Branch.AutomaticCommit+			[ Param "--quiet"+			, Param "--allow-empty"+			, Param "-m"+			, Param "commit before entering adjusted unlocked branch"+			]+	enterAdjustedBranch UnlockAdjustment++setBasisBranch :: BasisBranch -> Ref -> Annex ()+setBasisBranch (BasisBranch basis) new = +	inRepo $ Git.Branch.update' basis new++setAdjustedBranch :: String -> AdjBranch -> Ref -> Annex ()+setAdjustedBranch msg (AdjBranch b) r = inRepo $ Git.Branch.update msg b r++adjustBranch :: Adjustment -> OrigBranch -> Annex AdjBranch+adjustBranch adj origbranch = do+	-- Start basis off with the current value of the origbranch.+	setBasisBranch basis origbranch+	sha <- adjustCommit adj basis+	setAdjustedBranch "entering adjusted branch" adjbranch sha+	return adjbranch+  where+	adjbranch = originalToAdjusted origbranch adj+	basis = basisBranch adjbranch++adjustCommit :: Adjustment -> BasisBranch -> Annex Sha+adjustCommit adj basis = do+	treesha <- adjustTree adj basis+	commitAdjustedTree treesha basis++adjustTree :: Adjustment -> BasisBranch -> Annex Sha+adjustTree adj (BasisBranch basis) = do+	let toadj = adjustTreeItem adj+	treesha <- Git.Tree.adjustTree toadj [] [] basis =<< Annex.gitRepo+	return treesha++type CommitsPrevented = Git.LockFile.LockHandle++{- Locks git's index file, preventing git from making a commit, merge, + - or otherwise changing the HEAD ref while the action is run.+ -+ - Throws an IO exception if the index file is already locked.+ -}+preventCommits :: (CommitsPrevented -> Annex a) -> Annex a+preventCommits = bracket setup cleanup+  where+	setup = do+		lck <- fromRepo indexFileLock+		liftIO $ Git.LockFile.openLock lck+	cleanup = liftIO . Git.LockFile.closeLock++{- Commits a given adjusted tree, with the provided parent ref.+ -+ - This should always yield the same value, even if performed in different + - clones of a repo, at different times. The commit message and other+ - metadata is based on the parent.+ -}+commitAdjustedTree :: Sha -> BasisBranch -> Annex Sha+commitAdjustedTree treesha parent@(BasisBranch b) =+	commitAdjustedTree' treesha parent [b]++commitAdjustedTree' :: Sha -> BasisBranch -> [Ref] -> Annex Sha+commitAdjustedTree' treesha (BasisBranch basis) parents =+	go =<< catCommit basis+  where+	go Nothing = inRepo mkcommit+	go (Just basiscommit) = inRepo $ commitWithMetaData+		(commitAuthorMetaData basiscommit)+		(commitCommitterMetaData basiscommit)+		mkcommit+	mkcommit = Git.Branch.commitTree Git.Branch.AutomaticCommit+		adjustedBranchCommitMessage parents treesha++adjustedBranchCommitMessage :: String+adjustedBranchCommitMessage = "git-annex adjusted branch"++{- Update the currently checked out adjusted branch, merging the provided+ - branch into it. Note that the provided branch should be a non-adjusted+ - branch. -}+updateAdjustedBranch :: Branch -> (OrigBranch, Adjustment) -> Git.Branch.CommitMode -> Annex Bool+updateAdjustedBranch tomerge (origbranch, adj) commitmode = catchBoolIO $+	join $ preventCommits go+  where+	adjbranch@(AdjBranch currbranch) = originalToAdjusted origbranch adj+	basis = basisBranch adjbranch++	go commitsprevented =+		ifM (inRepo $ Git.Branch.changed currbranch tomerge)+			( do+				(updatedorig, _) <- propigateAdjustedCommits'+					origbranch adj commitsprevented+				changestomerge updatedorig+			, nochangestomerge+			)++	nochangestomerge = return $ return True++	{- Since the adjusted branch changes files, merging tomerge+	 - directly into it would likely result in unncessary merge+	 - conflicts. To avoid those conflicts, instead merge tomerge into+	 - updatedorig. The result of the merge can the be+	 - adjusted to yield the final adjusted branch.+	 -+	 - In order to do a merge into a ref that is not checked out,+	 - set the work tree to a temp directory, and set GIT_DIR+	 - to another temp directory, in which HEAD contains the+	 - updatedorig sha. GIT_COMMON_DIR is set to point to the real+	 - git directory, and so git can read and write objects from there,+	 - but will use GIT_DIR for HEAD and index.+	 -+	 - (Doing the merge this way also lets it run even though the main+	 - index file is currently locked.)+	 -}+	changestomerge (Just updatedorig) = do+		misctmpdir <- fromRepo gitAnnexTmpMiscDir+		void $ createAnnexDirectory misctmpdir+		tmpwt <- fromRepo gitAnnexMergeDir+		withTmpDirIn misctmpdir "git" $ \tmpgit -> withWorkTreeRelated tmpgit $+			withemptydir tmpwt $ withWorkTree tmpwt $ do+				liftIO $ writeFile (tmpgit </> "HEAD") (fromRef updatedorig)+				showAction $ "Merging into " ++ fromRef (Git.Ref.base origbranch)+				-- The --no-ff is important; it makes git+				-- merge not care that the work tree is empty.+				merged <- inRepo (Git.Merge.mergeNonInteractive' [Param "--no-ff"] tomerge commitmode)+					<||> (resolveMerge (Just updatedorig) tomerge True <&&> commitResolvedMerge commitmode)+				if merged+					then do+						!mergecommit <- liftIO $ extractSha <$> readFile (tmpgit </> "HEAD")+						-- This is run after the commit lock is dropped.+						return $ postmerge mergecommit+					else return $ return False+	changestomerge Nothing = return $ return False+	+	withemptydir d a = bracketIO setup cleanup (const a)+	  where+		setup = do+			whenM (doesDirectoryExist d) $+				removeDirectoryRecursive d+			createDirectoryIfMissing True d+		cleanup _ = removeDirectoryRecursive d++	{- A merge commit has been made between the basisbranch and +	 - tomerge. Update the basisbranch and origbranch to point+	 - to that commit, adjust it to get the new adjusted branch,+	 - and check it out.+	 -+	 - But, there may be unstaged work tree changes that conflict, +	 - so the check out is done by making a normal merge of+	 - the new adjusted branch.+	 -}+	postmerge (Just mergecommit) = do+		setBasisBranch basis mergecommit+		inRepo $ Git.Branch.update' origbranch mergecommit+		adjtree <- adjustTree adj (BasisBranch mergecommit)+		adjmergecommit <- commitAdjustedTree adjtree (BasisBranch mergecommit)+		-- Make currbranch be the parent, so that merging+		-- this commit will be a fast-forward.+		adjmergecommitff <- commitAdjustedTree' adjtree (BasisBranch mergecommit) [currbranch]+		showAction "Merging into adjusted branch"+		ifM (autoMergeFrom adjmergecommitff (Just currbranch) commitmode)+			( reparent adjtree adjmergecommit =<< getcurrentcommit+			, return False+			)+	postmerge Nothing = return False++	-- Now that the merge into the adjusted branch is complete,+	-- take the tree from that merge, and attach it on top of the+	-- adjmergecommit, if it's different.+	reparent adjtree adjmergecommit (Just currentcommit) = do+		if (commitTree currentcommit /= adjtree)+			then do+				c <- inRepo $ Git.Branch.commitTree Git.Branch.AutomaticCommit+					("Merged " ++ fromRef tomerge) [adjmergecommit]+					(commitTree currentcommit)+				inRepo $ Git.Branch.update "updating adjusted branch" currbranch c+				propigateAdjustedCommits origbranch adj+			else inRepo $ Git.Branch.update "updating adjusted branch" currbranch adjmergecommit+		return True+	reparent _ _ Nothing = return False++	getcurrentcommit = do+		v <- inRepo Git.Branch.currentUnsafe+		case v of+			Nothing -> return Nothing+			Just c -> catCommit c++{- Check for any commits present on the adjusted branch that have not yet+ - been propigated to the basis branch, and propigate them to the basis+ - branch and from there on to the orig branch.+ -+ - After propigating the commits back to the basis banch,+ - rebase the adjusted branch on top of the updated basis branch.+ -}+propigateAdjustedCommits :: OrigBranch -> Adjustment -> Annex ()+propigateAdjustedCommits origbranch adj = +	preventCommits $ \commitsprevented ->+		join $ snd <$> propigateAdjustedCommits' origbranch adj commitsprevented+		+{- Returns sha of updated basis branch, and action which will rebase+ - the adjusted branch on top of the updated basis branch. -}+propigateAdjustedCommits'+	:: OrigBranch+	-> Adjustment+	-> CommitsPrevented+	-> Annex (Maybe Sha, Annex ())+propigateAdjustedCommits' origbranch adj _commitsprevented = do+	ov <- inRepo $ Git.Ref.sha basis+	case ov of+		Just origsha -> do+			cv <- catCommit currbranch+			case cv of+				Just currcommit -> do+					v <- newcommits >>= go origsha False+					case v of+						Left e -> do+							warning e+							return (Nothing, return ())+						Right newparent -> return+							( Just newparent+							, rebase currcommit newparent+							)+				Nothing -> return (Nothing, return ())+		Nothing -> return (Nothing, return ())+  where+	(BasisBranch basis) = basisBranch adjbranch+	adjbranch@(AdjBranch currbranch) = originalToAdjusted origbranch adj+	newcommits = inRepo $ Git.Branch.changedCommits basis currbranch+		-- Get commits oldest first, so they can be processed+		-- in order made.+		[Param "--reverse"]+	go parent _ [] = do+		setBasisBranch (BasisBranch basis) parent+		inRepo $ Git.Branch.update' origbranch parent+		return (Right parent)+	go parent pastadjcommit (sha:l) = do+		mc <- catCommit sha+		case mc of+			Just c+				| commitMessage c == adjustedBranchCommitMessage ->+					go parent True l+				| pastadjcommit -> do+					v <- reverseAdjustedCommit parent adj (sha, c) origbranch+					case v of+						Left e -> return (Left e)+						Right commit -> go commit pastadjcommit l+			_ -> go parent pastadjcommit l+	rebase currcommit newparent = do+		-- Reuse the current adjusted tree, and reparent it+		-- on top of the newparent.+		commitAdjustedTree (commitTree currcommit) (BasisBranch newparent)+			>>= inRepo . Git.Branch.update rebaseOnTopMsg currbranch++rebaseOnTopMsg :: String+rebaseOnTopMsg = "rebasing adjusted branch on top of updated original branch"++{- Reverses an adjusted commit, and commit with provided commitparent,+ - yielding a commit sha.+ -+ - Adjusts the tree of the commitparent, changing only the files that the+ - commit changed, and reverse adjusting those changes.+ -+ - The commit message, and the author and committer metadata are+ - copied over from the basiscommit. However, any gpg signature+ - will be lost, and any other headers are not copied either. -}+reverseAdjustedCommit :: Sha -> Adjustment -> (Sha, Commit) -> OrigBranch -> Annex (Either String Sha)+reverseAdjustedCommit commitparent adj (csha, basiscommit) origbranch+	| length (commitParent basiscommit) > 1 = return $+		Left $ "unable to propigate merge commit " ++ show csha ++ " back to " ++ show origbranch+	| otherwise = do+		treesha <- reverseAdjustedTree commitparent adj csha+		revadjcommit <- inRepo $ commitWithMetaData+			(commitAuthorMetaData basiscommit)+			(commitCommitterMetaData basiscommit) $+				Git.Branch.commitTree Git.Branch.AutomaticCommit+					(commitMessage basiscommit) [commitparent] treesha+		return (Right revadjcommit)++{- Adjusts the tree of the basis, changing only the files that the+ - commit changed, and reverse adjusting those changes.+ -+ - commitDiff does not support merge commits, so the csha must not be a+ - merge commit. -}+reverseAdjustedTree :: Sha -> Adjustment -> Sha -> Annex Sha+reverseAdjustedTree basis adj csha = do+	(diff, cleanup) <- inRepo (Git.DiffTree.commitDiff csha)+	let (adds, others) = partition (\dti -> Git.DiffTree.srcsha dti == nullSha) diff+	let (removes, changes) = partition (\dti -> Git.DiffTree.dstsha dti == nullSha) others+	adds' <- catMaybes <$>+		mapM (adjustTreeItem reverseadj) (map diffTreeToTreeItem adds)+	treesha <- Git.Tree.adjustTree+		(propchanges changes)+		adds'+		(map Git.DiffTree.file removes)+		basis+		=<< Annex.gitRepo+	void $ liftIO cleanup+	return treesha+  where+	reverseadj = reverseAdjustment adj+	propchanges changes ti@(TreeItem f _ _) =+		case M.lookup f m of+			Nothing -> return (Just ti) -- not changed+			Just change -> adjustTreeItem reverseadj change+	  where+		m = M.fromList $ map (\i@(TreeItem f' _ _) -> (f', i)) $+			map diffTreeToTreeItem changes++diffTreeToTreeItem :: Git.DiffTree.DiffTreeItem -> TreeItem+diffTreeToTreeItem dti = TreeItem+	(Git.DiffTree.file dti)+	(Git.DiffTree.dstmode dti)+	(Git.DiffTree.dstsha dti)++{- Cloning a repository that has an adjusted branch checked out will+ - result in the clone having the same adjusted branch checked out -- but+ - the origbranch won't exist in the clone, nor will the basis.+ - Create them. -}+checkAdjustedClone :: Annex ()+checkAdjustedClone = go =<< inRepo Git.Branch.current+  where+	go Nothing = return ()+	go (Just currbranch) = case adjustedToOriginal currbranch of+		Nothing -> return ()+		Just (adj, origbranch) -> do+			let remotebranch = Git.Ref.underBase "refs/remotes/origin" origbranch+			let basis@(BasisBranch bb) = basisBranch (originalToAdjusted origbranch adj)+			unlessM (inRepo $ Git.Ref.exists bb) $+				setBasisBranch basis remotebranch+			unlessM (inRepo $ Git.Ref.exists origbranch) $+				inRepo $ Git.Branch.update' origbranch remotebranch
Annex/AutoMerge.hs view
@@ -50,9 +50,9 @@ 		Just b -> go =<< inRepo (Git.Ref.sha b)   where 	go old = ifM isDirect-		( mergeDirect currbranch old branch (resolveMerge old branch) commitmode+		( mergeDirect currbranch old branch (resolveMerge old branch False) commitmode 		, inRepo (Git.Merge.mergeNonInteractive branch commitmode)-			<||> (resolveMerge old branch <&&> commitResolvedMerge commitmode)+			<||> (resolveMerge old branch False <&&> commitResolvedMerge commitmode) 		)  {- Resolves a conflicted merge. It's important that any conflicts be@@ -77,11 +77,16 @@  -  - In indirect mode, the merge is resolved in the work tree and files  - staged, to clean up from a conflicted merge that was run in the work- - tree.+ - tree.   -  - In direct mode, the work tree is not touched here; files are staged to  - the index, and written to the gitAnnexMergeDir, for later handling by  - the direct mode merge code.+ - + - This is complicated by needing to support merges run in an overlay+ - work tree, in which case the CWD won't be within the work tree.+ - In this mode, there is no need to update the work tree at all,+ - as the overlay work tree will get deleted.  -  - Unlocked files remain unlocked after merging, and locked files  - remain locked. When the merge conflict is between a locked and unlocked@@ -93,12 +98,16 @@  - A git merge can fail for other reasons, and this allows detecting  - such failures.  -}-resolveMerge :: Maybe Git.Ref -> Git.Ref -> Annex Bool-resolveMerge us them = do-	top <- fromRepo Git.repoPath+resolveMerge :: Maybe Git.Ref -> Git.Ref -> Bool -> Annex Bool+resolveMerge us them inoverlay = do+	top <- if inoverlay+		then pure "."+		else fromRepo Git.repoPath 	(fs, cleanup) <- inRepo (LsFiles.unmerged [top])-	srcmap <- inodeMap $ pure (map LsFiles.unmergedFile fs, return True)-	(mergedks, mergedfs) <- unzip <$> mapM (resolveMerge' srcmap us them) fs+	srcmap <- if inoverlay+		then pure M.empty+		else inodeMap $ pure (map LsFiles.unmergedFile fs, return True)+	(mergedks, mergedfs) <- unzip <$> mapM (resolveMerge' srcmap us them inoverlay) fs 	let mergedks' = concat mergedks 	let mergedfs' = catMaybes mergedfs 	let merged = not (null mergedfs')@@ -114,15 +123,15 @@  	when merged $ do 		Annex.Queue.flush-		unlessM isDirect $ do+		unlessM (pure inoverlay <||> isDirect) $ do 			unstagedmap <- inodeMap $ inRepo $ LsFiles.notInRepo False [top] 			cleanConflictCruft mergedks' mergedfs' unstagedmap 		showLongNote "Merge conflict was automatically resolved; you may want to examine the result." 	return merged -resolveMerge' :: InodeMap -> Maybe Git.Ref -> Git.Ref -> LsFiles.Unmerged -> Annex ([Key], Maybe FilePath)-resolveMerge' _ Nothing _ _ = return ([], Nothing)-resolveMerge' unstagedmap (Just us) them u = do+resolveMerge' :: InodeMap -> Maybe Git.Ref -> Git.Ref -> Bool -> LsFiles.Unmerged -> Annex ([Key], Maybe FilePath)+resolveMerge' _ Nothing _ _ _ = return ([], Nothing)+resolveMerge' unstagedmap (Just us) them inoverlay u = do 	kus <- getkey LsFiles.valUs 	kthem <- getkey LsFiles.valThem 	case (kus, kthem) of@@ -133,8 +142,9 @@ 				makeannexlink keyThem LsFiles.valThem 				-- cleanConflictCruft can't handle unlocked 				-- files, so delete here.-				unless (islocked LsFiles.valUs) $-					liftIO $ nukeFile file+				unless inoverlay $+					unless (islocked LsFiles.valUs) $+						liftIO $ nukeFile file 			| otherwise -> do 				-- Only resolve using symlink when both 				-- were locked, otherwise use unlocked@@ -170,23 +180,33 @@ 	  where 		dest = variantFile file key +	stagefile :: FilePath -> Annex FilePath+	stagefile f+		| inoverlay = (</> f) <$> fromRepo Git.repoPath+		| otherwise = pure f+ 	makesymlink key dest = do 		l <- calcRepo $ gitAnnexLink dest key-		replacewithsymlink dest l-		stageSymlink dest =<< hashSymlink l+		unless inoverlay $ replacewithsymlink dest l+		dest' <- stagefile dest+		stageSymlink dest' =<< hashSymlink l  	replacewithsymlink dest link = withworktree dest $ \f -> 		replaceFile f $ makeGitLink link  	makepointer key dest = do-		unlessM (reuseOldFile unstagedmap key file dest) $ do-			r <- linkFromAnnex key dest-			case r of-				LinkAnnexFailed -> liftIO $-					writeFile dest (formatPointer key)-				_ -> noop-		stagePointerFile dest =<< hashPointerFile key-		Database.Keys.addAssociatedFile key =<< inRepo (toTopFilePath dest)+		unless inoverlay $ +			unlessM (reuseOldFile unstagedmap key file dest) $ do+				r <- linkFromAnnex key dest+				case r of+					LinkAnnexFailed -> liftIO $+						writeFile dest (formatPointer key)+					_ -> noop+		dest' <- stagefile dest+		stagePointerFile dest' =<< hashPointerFile key+		unless inoverlay $+			Database.Keys.addAssociatedFile key+				=<< inRepo (toTopFilePath dest)  	withworktree f a = ifM isDirect 		( do@@ -202,7 +222,7 @@ 			=<< fromRepo (UpdateIndex.lsSubTree b item)  		-- Update the work tree to reflect the graft.-		case (selectwant (LsFiles.unmergedBlobType u), selectunwant (LsFiles.unmergedBlobType u)) of+		unless inoverlay $ case (selectwant (LsFiles.unmergedBlobType u), selectunwant (LsFiles.unmergedBlobType u)) of 			-- Symlinks are never left in work tree when 			-- there's a conflict with anything else. 			-- So, when grafting in a symlink, we must create it:
Annex/Branch.hs view
@@ -35,7 +35,7 @@ import Annex.Common import Annex.BranchState import Annex.Journal-import Annex.Index+import Annex.GitOverlay import qualified Git import qualified Git.Command import qualified Git.Ref
Annex/Content.hs view
@@ -594,14 +594,10 @@   where 	hardlink = do 		s <- getstat-#ifndef mingw32_HOST_OS 		if linkCount s > 1 			then copy s 			else liftIO (createLink src dest >> return True) 				`catchIO` const (copy s)-#else-		copy s-#endif 	copy = checkedCopyFile' key src dest 	getstat = liftIO $ getFileStatus src 
Annex/Direct.hs view
@@ -37,7 +37,7 @@ import Annex.ReplaceFile import Annex.VariantFile import Git.Index-import Annex.Index+import Annex.GitOverlay import Annex.LockFile import Annex.InodeSentinal @@ -204,6 +204,7 @@ 	-- has been updated, which would leave things in an inconsistent 	-- state if mergeDirectCleanup is interrupted. 	-- <http://marc.info/?l=git&m=140262402204212&w=2>+	liftIO $ print ("stagemerge in", d) 	merger <- ifM (coreSymlinks <$> Annex.getGitConfig) 		( return Git.Merge.stageMerge 		, return $ \ref -> Git.Merge.mergeNonInteractive ref commitmode@@ -225,7 +226,7 @@ 	let merge_msg = d </> "MERGE_MSG" 	let merge_mode = d </> "MERGE_MODE" 	ifM (pure allowff <&&> canff)-		( inRepo $ Git.Branch.update Git.Ref.headRef branch -- fast forward+		( inRepo $ Git.Branch.update "merge" Git.Ref.headRef branch -- fast forward 		, do 			msg <- liftIO $ 				catchDefaultIO ("merge " ++ fromRef branch) $@@ -462,7 +463,7 @@   where 	switch orighead = do 		let newhead = directBranch orighead-		maybe noop (inRepo . Git.Branch.update newhead)+		maybe noop (inRepo . Git.Branch.update "entering direct mode" newhead) 			=<< inRepo (Git.Ref.sha orighead) 		inRepo $ Git.Branch.checkout newhead @@ -475,7 +476,7 @@ 		case v of 			Just headsha 				| orighead /= currhead -> do-					inRepo $ Git.Branch.update orighead headsha+					inRepo $ Git.Branch.update "leaving direct mode" orighead headsha 					inRepo $ Git.Branch.checkout orighead 					inRepo $ Git.Branch.delete currhead 			_ -> inRepo $ Git.Branch.checkout orighead
+ Annex/GitOverlay.hs view
@@ -0,0 +1,71 @@+{- Temporarily changing the files git uses.+ -+ - Copyright 2014-2016 Joey Hess <id@joeyh.name>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Annex.GitOverlay where++import qualified Control.Exception as E++import Annex.Common+import Git+import Git.Types+import Git.Env+import qualified Annex++{- Runs an action using a different git index file. -}+withIndexFile :: FilePath -> Annex a -> Annex a+withIndexFile f = withAltRepo+	(\g -> addGitEnv g "GIT_INDEX_FILE" f)+	(\g g' -> g' { gitEnv = gitEnv g })++{- Runs an action using a different git work tree.+ -+ - Smudge and clean filters are disabled in this work tree. -}+withWorkTree :: FilePath -> Annex a -> Annex a+withWorkTree d = withAltRepo+	(\g -> return $ g { location = modlocation (location g), gitGlobalOpts = gitGlobalOpts g ++ disableSmudgeConfig })+	(\g g' -> g' { location = location g, gitGlobalOpts = gitGlobalOpts g })+  where+	modlocation l@(Local {}) = l { worktree = Just d }+	modlocation _ = error "withWorkTree of non-local git repo"+	disableSmudgeConfig = map Param+		[ "-c", "filter.annex.smudge="+		, "-c", "filter.annex.clean="+		]++{- Runs an action with the git index file and HEAD, and a few other+ - files that are related to the work tree coming from an overlay+ - directory other than the usual. This is done by pointing+ - GIT_COMMON_DIR at the regular git directory, and GIT_DIR at the+ - overlay directory. -}+withWorkTreeRelated :: FilePath -> Annex a -> Annex a+withWorkTreeRelated d = withAltRepo modrepo unmodrepo+  where+	modrepo g = do+		g' <- addGitEnv g "GIT_COMMON_DIR" =<< absPath (localGitDir g)+		g'' <- addGitEnv g' "GIT_DIR" d+		return (g'' { gitEnvOverridesGitDir = True })+	unmodrepo g g' = g'+		{ gitEnv = gitEnv g+		, gitEnvOverridesGitDir = gitEnvOverridesGitDir g+		}++withAltRepo +	:: (Repo -> IO Repo)+	-- ^ modify Repo+	-> (Repo -> Repo -> Repo)+	-- ^ undo modifications; first Repo is the original and second+	-- is the one after running the action.+	-> Annex a+	-> Annex a+withAltRepo modrepo unmodrepo a = do+	g <- gitRepo+	g' <- liftIO $ modrepo g+	r <- tryNonAsync $ do+		Annex.changeState $ \s -> s { Annex.repo = g' }+		a+	Annex.changeState $ \s -> s { Annex.repo = unmodrepo g (Annex.repo s) }+	either E.throw return r
− Annex/Index.hs
@@ -1,27 +0,0 @@-{- Using other git index files- -- - Copyright 2014 Joey Hess <id@joeyh.name>- -- - Licensed under the GNU GPL version 3 or higher.- -}--module Annex.Index (withIndexFile) where--import qualified Control.Exception as E--import Annex.Common-import Git.Types-import Git.Env-import qualified Annex--{- Runs an action using a different git index file. -}-withIndexFile :: FilePath -> Annex a -> Annex a-withIndexFile f a = do-	g <- gitRepo-	g' <- liftIO $ addGitEnv g "GIT_INDEX_FILE" f--	r <- tryNonAsync $ do-		Annex.changeState $ \s -> s { Annex.repo = g' }-		a-	Annex.changeState $ \s -> s { Annex.repo = (Annex.repo s) { gitEnv = gitEnv g} }-	either E.throw return r
Annex/Ingest.hs view
@@ -35,6 +35,8 @@ import qualified Annex import qualified Annex.Queue import qualified Database.Keys+import qualified Git+import qualified Git.Branch import Config import Utility.InodeCache import Annex.ReplaceFile@@ -43,6 +45,7 @@ import Utility.Touch import Git.FilePath import Annex.InodeSentinal+import Annex.AdjustedBranch  import Control.Exception (IOException) @@ -309,14 +312,31 @@ 	)  {- Whether a file should be added unlocked or not. Default is to not,- - unless symlinks are not supported. annex.addunlocked can override that. -}+ - unless symlinks are not supported. annex.addunlocked can override that.+ - Also, when in an adjusted unlocked branch, always add files unlocked.+ -} addUnlocked :: Annex Bool addUnlocked = isDirect <||> 	(versionSupportsUnlockedPointers <&&> 	 ((not . coreSymlinks <$> Annex.getGitConfig) <||>-	  (annexAddUnlocked <$> Annex.getGitConfig)+	  (annexAddUnlocked <$> Annex.getGitConfig) <||>+	  (maybe False (\b -> getAdjustment b == Just UnlockAdjustment) <$> cachedCurrentBranch) 	 ) 	)++cachedCurrentBranch :: Annex (Maybe Git.Branch)+cachedCurrentBranch = maybe cache (return . Just)+	=<< Annex.getState Annex.cachedcurrentbranch+  where+	cache :: Annex (Maybe Git.Branch)+	cache = do+		mb <- inRepo Git.Branch.currentUnsafe+		case mb of+			Nothing -> return Nothing+			Just b -> do+				Annex.changeState $ \s ->+					s { Annex.cachedcurrentbranch = Just b }+				return (Just b)  {- Adds a file to the work tree for the key, and stages it in the index.  - The content of the key may be provided in a temp file, which will be
Annex/Init.hs view
@@ -33,6 +33,7 @@ import Annex.Link import Config import Annex.Direct+import Annex.AdjustedBranch import Annex.Environment import Annex.Hook import Annex.InodeSentinal@@ -92,15 +93,19 @@ 	whenM versionSupportsUnlockedPointers $ do 		configureSmudgeFilter 		Database.Keys.scanAssociatedFiles-	ifM (crippledFileSystem <&&> (not <$> isBare) <&&> (not <$> versionSupportsUnlockedPointers))-		( do-			enableDirectMode-			setDirect True+	ifM (crippledFileSystem <&&> (not <$> isBare))+		( ifM versionSupportsUnlockedPointers+			( adjustToCrippledFileSystem+			, do+				enableDirectMode+				setDirect True+			) 		-- Handle case where this repo was cloned from a 		-- direct mode repo 		, unlessM isBare 			switchHEADBack 		)+	checkAdjustedClone 	createInodeSentinalFile False  uninitialize :: Annex ()
Annex/Link.hs view
@@ -157,10 +157,14 @@  -  - Unlocked files whose content is present are not detected by this. -} isPointerFile :: FilePath -> IO (Maybe Key)-isPointerFile f = catchDefaultIO Nothing $ do-	b <- L.take maxPointerSz <$> L.readFile f-	let !mk = parseLinkOrPointer' (decodeBS b)+isPointerFile f = catchDefaultIO Nothing $ bracket open close $ \h -> do+	b <- take (fromIntegral maxPointerSz) <$> hGetContents h+	-- strict so it reads before the file handle is closed+	let !mk = parseLinkOrPointer' b 	return mk+  where+	open = openBinaryFile f ReadMode+	close = hClose  {- Checks a symlink target or pointer file first line to see if it  - appears to point to annexed content.
Annex/Locations.hs view
@@ -291,7 +291,8 @@ gitAnnexFeedState :: Key -> Git.Repo -> FilePath gitAnnexFeedState k r = gitAnnexFeedStateDir r </> keyFile k -{- .git/annex/merge/ is used for direct mode merges. -}+{- .git/annex/merge/ is used as a empty work tree for direct mode merges and+ - merges in adjusted branches. -} gitAnnexMergeDir :: Git.Repo -> FilePath gitAnnexMergeDir r = addTrailingPathSeparator $ gitAnnexDir r </> "merge" 
Annex/Version.hs view
@@ -52,6 +52,9 @@ 	go (Just "6") = True 	go _ = False +versionSupportsAdjustedBranch :: Annex Bool+versionSupportsAdjustedBranch = versionSupportsUnlockedPointers+ setVersion :: Version -> Annex () setVersion = setConfig versionField 
Annex/View.hs view
@@ -23,7 +23,7 @@ import Git.Types import Git.FilePath import Annex.WorkTree-import Annex.Index+import Annex.GitOverlay import Annex.Link import Annex.CatFile import Logs.MetaData
Assistant/Sync.hs view
@@ -19,7 +19,6 @@ import qualified Command.Sync import Utility.Parallel import qualified Git-import qualified Git.Branch import qualified Git.Command import qualified Git.Ref import qualified Remote@@ -79,16 +78,16 @@ 		| Git.repoIsLocal r = True 		| Git.repoIsLocalUnknown r = True 		| otherwise = False-	sync (Just branch) = do-		(failedpull, diverged) <- manualPull (Just branch) gitremotes+	sync currentbranch@(Just _, _) = do+		(failedpull, diverged) <- manualPull currentbranch gitremotes 		now <- liftIO getCurrentTime 		failedpush <- pushToRemotes' now notifypushes gitremotes 		return (nub $ failedpull ++ failedpush, diverged) 	{- No local branch exists yet, but we can try pulling. -}-	sync Nothing = manualPull Nothing gitremotes+	sync (Nothing, _) = manualPull (Nothing, Nothing) gitremotes 	go = do 		(failed, diverged) <- sync-			=<< liftAnnex (inRepo Git.Branch.current)+			=<< liftAnnex (join Command.Sync.getCurrBranch) 		addScanRemotes diverged $ 			filter (not . remoteAnnexIgnore . Remote.gitconfig) 				nonxmppremotes@@ -133,7 +132,7 @@ 		Annex.Branch.commit "update" 		(,,) 			<$> gitRepo-			<*> inRepo Git.Branch.current+			<*> join Command.Sync.getCurrBranch 			<*> getUUID 	let (xmppremotes, normalremotes) = partition Remote.isXMPPRemote remotes 	ret <- go True branch g u normalremotes@@ -145,9 +144,9 @@ 			Pushing (getXMPPClientID r) (CanPush u shas) 	return ret   where-	go _ Nothing _ _ _ = return [] -- no branch, so nothing to do+	go _ (Nothing, _) _ _ _ = return [] -- no branch, so nothing to do 	go _ _ _ _ [] = return [] -- no remotes, so nothing to do-	go shouldretry (Just branch) g u rs =  do+	go shouldretry currbranch@(Just branch, _) g u rs =  do 		debug ["pushing to", show rs] 		(succeeded, failed) <- parallelPush g rs (push branch) 		updatemap succeeded []@@ -158,7 +157,7 @@ 						map Remote.uuid succeeded 				return failed 			else if shouldretry-				then retry branch g u failed+				then retry currbranch g u failed 				else fallback branch g u failed  	updatemap succeeded failed = changeFailedPushMap $ \m ->@@ -166,10 +165,10 @@ 			M.difference m (makemap succeeded) 	makemap l = M.fromList $ zip l (repeat now) -	retry branch g u rs = do+	retry currbranch g u rs = do 		debug ["trying manual pull to resolve failed pushes"]-		void $ manualPull (Just branch) rs-		go False (Just branch) g u rs+		void $ manualPull currbranch rs+		go False currbranch g u rs  	fallback branch g u rs = do 		debug ["fallback pushing to", show rs]@@ -227,7 +226,7 @@  - XMPP remotes. However, those pushes will run asynchronously, so their  - results are not included in the return data.  -}-manualPull :: Maybe Git.Ref -> [Remote] -> Assistant ([Remote], Bool)+manualPull :: Command.Sync.CurrBranch -> [Remote] -> Assistant ([Remote], Bool) manualPull currentbranch remotes = do 	g <- liftAnnex gitRepo 	let (xmppremotes, normalremotes) = partition Remote.isXMPPRemote remotes
Assistant/Threads/Committer.hs view
@@ -227,7 +227,7 @@ 		Right _ -> do 			ok <- Command.Sync.commitStaged Git.Branch.AutomaticCommit msg 			when ok $-				Command.Sync.updateSyncBranch =<< inRepo Git.Branch.current+				Command.Sync.updateSyncBranch =<< join Command.Sync.getCurrBranch 			return ok  {- OSX needs a short delay after a file is added before locking it down,
Assistant/Threads/Merger.hs view
@@ -17,7 +17,7 @@ import qualified Annex.Branch import qualified Git import qualified Git.Branch-import Annex.AutoMerge+import qualified Command.Sync import Annex.TaggedPush import Remote (remoteFromUUID) @@ -72,19 +72,21 @@ 			unlessM handleDesynced $ 				queueDeferredDownloads "retrying deferred download" Later 	| "/synced/" `isInfixOf` file =-		mergecurrent =<< liftAnnex (inRepo Git.Branch.current)+		mergecurrent =<< liftAnnex (join Command.Sync.getCurrBranch) 	| otherwise = noop   where 	changedbranch = fileToBranch file -	mergecurrent (Just current)-		| equivBranches changedbranch current =-			whenM (liftAnnex $ inRepo $ Git.Branch.changed current changedbranch) $ do+	mergecurrent currbranch@(Just b, _)+		| equivBranches changedbranch b =+			whenM (liftAnnex $ inRepo $ Git.Branch.changed b changedbranch) $ do 				debug 					[ "merging", Git.fromRef changedbranch-					, "into", Git.fromRef current+					, "into", Git.fromRef b 					]-				void $ liftAnnex $ autoMergeFrom changedbranch (Just current) Git.Branch.AutomaticCommit+				void $ liftAnnex $ Command.Sync.merge+					currbranch Git.Branch.AutomaticCommit+					changedbranch 	mergecurrent _ = noop  	handleDesynced = case fromTaggedBranch changedbranch of
Assistant/Threads/XMPPClient.hs view
@@ -25,6 +25,7 @@ import Assistant.XMPP.Git import Annex.UUID import Logs.UUID+import qualified Command.Sync  import Network.Protocol.XMPP import Control.Concurrent@@ -33,7 +34,6 @@ import qualified Data.Text as T import qualified Data.Set as S import qualified Data.Map as M-import qualified Git.Branch import Data.Time.Clock import Control.Concurrent.Async @@ -306,7 +306,7 @@ pull us = do 	rs <- filter matching . syncGitRemotes <$> getDaemonStatus 	debug $ "push notification for" : map (fromUUID . Remote.uuid ) rs-	pullone rs =<< liftAnnex (inRepo Git.Branch.current)+	pullone rs =<< liftAnnex (join Command.Sync.getCurrBranch)   where 	matching r = Remote.uuid r `S.member` s 	s = S.fromList us
Assistant/WebApp/Configurators/Local.hs view
@@ -20,7 +20,7 @@ import qualified Git import qualified Git.Config import qualified Git.Command-import qualified Git.Branch+import qualified Command.Sync import Config.Files import Utility.FreeDesktop import Utility.DiskFree@@ -200,7 +200,7 @@  - immediately pulling from it. Also spawns a sync to push to it as well. -} immediateSyncRemote :: Remote -> Assistant () immediateSyncRemote r = do-	currentbranch <- liftAnnex (inRepo Git.Branch.current)+	currentbranch <- liftAnnex $ join Command.Sync.getCurrBranch 	void $ manualPull currentbranch [r] 	syncRemote r 
Assistant/XMPP/Git.hs view
@@ -27,7 +27,6 @@ import Annex.CatFile import Config import Git-import qualified Git.Branch import qualified Types.Remote as Remote import qualified Remote as Remote import Remote.List@@ -292,16 +291,15 @@ {- Returns the ClientID that it pushed to. -} runPush :: (Remote -> Assistant ()) -> NetMessage -> Assistant (Maybe ClientID) runPush checkcloudrepos (Pushing cid (PushRequest theiruuid)) =-	go =<< liftAnnex (inRepo Git.Branch.current)+	go =<< liftAnnex (join Command.Sync.getCurrBranch)   where-	go Nothing = return Nothing-	go (Just branch) = do+	go (Just branch, _) = do 		rs <- xmppRemotes cid theiruuid 		liftAnnex $ Annex.Branch.commit "update" 		(g, u) <- liftAnnex $ (,) 			<$> gitRepo 			<*> getUUID-		liftIO $ Command.Sync.updateBranch (Command.Sync.syncBranch branch) g+		liftIO $ Command.Sync.updateBranch (Command.Sync.syncBranch branch) branch g 		selfjid <- ((T.unpack <$>) . xmppClientID) <$> getDaemonStatus 		if null rs 			then return Nothing@@ -311,6 +309,7 @@ 						xmppPush cid (taggedPush u selfjid branch r) 					checkcloudrepos r 				return $ Just cid+	go _ = return Nothing runPush checkcloudrepos (Pushing cid (StartingPush theiruuid)) = do 	rs <- xmppRemotes cid theiruuid 	if null rs
Build/mdwn2man view
@@ -53,6 +53,7 @@ 	else { 		$inNAME=0; 	}+	s/\\"/\\\\"/g; # hack for git-annex-shell's quotes around SSH_ORIGINAL_COMMAND  	print $_; }
CHANGELOG view
@@ -1,3 +1,27 @@+git-annex (6.20160412) unstable; urgency=medium++  * adjust --unlock: Enters an adjusted branch in which all annexed files+    are unlocked. The v6 equivilant of direct mode, but much cleaner!+  * Upgrading a direct mode repository to v6 has changed to enter+    an adjusted unlocked branch. This makes the direct mode to v6 upgrade+    able to be performed in one clone of a repository without affecting+    other clones, which can continue using v5 and direct mode.+  * init --version=6: Automatically enter the adjusted unlocked branch+    when filesystem doesn't support symlinks.+  * ddar remote: fix ssh calls+    Thanks, Robie Basak+  * log: Display time with time zone.+  * log --raw-date: Use to display seconds from unix epoch.+  * v6: Close pointer file handles more quickly, to avoid problems on Windows.+  * sync: Show output of git commit.+  * annex.thin and annex.hardlink are now supported on Windows.+  * unannex --fast now makes hard links on Windows.+  * Fix bug in annex.largefiles mimetype= matching when git-annex+    is run in a subdirectory of the repository.+  * Fix build with ghc v7.11. Thanks, Gabor Greif.++ -- Joey Hess <id@joeyh.name>  Tue, 12 Apr 2016 14:53:22 -0400+ git-annex (6.20160318) unstable; urgency=medium    * metadata: Added -r to remove all current values of a field.
CmdLine/GitAnnex.hs view
@@ -38,6 +38,7 @@ import qualified Command.ReadPresentKey import qualified Command.CheckPresentKey import qualified Command.ReKey+import qualified Command.Adjust import qualified Command.MetaData import qualified Command.View import qualified Command.VAdd@@ -174,6 +175,7 @@ 	, Command.ReadPresentKey.cmd 	, Command.CheckPresentKey.cmd 	, Command.ReKey.cmd+	, Command.Adjust.cmd 	, Command.MetaData.cmd 	, Command.View.cmd 	, Command.VAdd.cmd
+ Command/Adjust.hs view
@@ -0,0 +1,41 @@+{- git-annex command+ -+ - Copyright 2016 Joey Hess <id@joeyh.name>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Command.Adjust where++import Command+import Annex.AdjustedBranch+import Annex.Version++cmd :: Command+cmd = notBareRepo $ notDirect $ noDaemonRunning $+	command "adjust" SectionSetup "enter adjusted branch"+		paramNothing (seek <$$> optParser)++optParser :: CmdParamsDesc -> Parser Adjustment+optParser _ = +	flag' UnlockAdjustment+		( long "unlock"+		<> help "unlock annexed files"+		)+	{- Not ready yet+	<|> flag' HideMissingAdjustment+		( long "hide-missing"+		<> help "omit annexed files whose content is not present"+		)+	-}++seek :: Adjustment -> CommandSeek+seek = commandAction . start++start :: Adjustment -> CommandStart+start adj = do+	unlessM versionSupportsAdjustedBranch $+		error "Adjusted branches are only supported in v6 or newer repositories."+	showStart "adjust" ""+	enterAdjustedBranch adj+	next $ next $ return True
Command/Log.hs view
@@ -44,6 +44,7 @@  data LogOptions = LogOptions 	{ logFiles :: CmdParams+	, rawDateOption :: Bool 	, gourceOption :: Bool 	, passthruOptions :: [CommandParam] 	}@@ -52,6 +53,10 @@ optParser desc = LogOptions 	<$> cmdParams desc 	<*> switch+		( long "raw-date"+		<> help "display seconds from unix epoch"+		)+	<*> switch 		( long "gource" 		<> help "format output for gource" 		)@@ -86,14 +91,15 @@ 	-> Key 	-> CommandStart start m zone o file key = do-	showLog output =<< readLog <$> getLog key (passthruOptions o)-	-- getLog produces a zombie; reap it-	liftIO reapZombies+	(ls, cleanup) <- getLog key (passthruOptions o)+	showLog output (readLog ls)+	void $ liftIO cleanup 	stop   where 	output-		| (gourceOption o) = gourceOutput lookupdescription file-		| otherwise = normalOutput lookupdescription file zone+		| rawDateOption o = normalOutput lookupdescription file show+		| gourceOption o = gourceOutput lookupdescription file+		| otherwise = normalOutput lookupdescription file (showTimeStamp zone) 	lookupdescription u = fromMaybe (fromUUID u) $ M.lookup u m  showLog :: Outputter -> [RefChange] -> Annex ()@@ -109,11 +115,11 @@ 	get ref = map toUUID . Logs.Presence.getLog . L.unpack <$> 		catObject ref -normalOutput :: (UUID -> String) -> FilePath -> TimeZone -> Outputter-normalOutput lookupdescription file zone present ts us =+normalOutput :: (UUID -> String) -> FilePath -> (POSIXTime -> String) -> Outputter+normalOutput lookupdescription file formattime present ts us = 	liftIO $ mapM_ (putStrLn . format) us   where-	time = showTimeStamp zone ts+	time = formattime ts 	addel = if present then "+" else "-" 	format u = unwords [ addel, time, file, "|",  		fromUUID u ++ " -- " ++ lookupdescription u ]@@ -150,13 +156,13 @@  - once the location log file is gone avoids it checking all the way back  - to commit 0 to see if it used to exist, so generally speeds things up a  - *lot* for newish files. -}-getLog :: Key -> [CommandParam] -> Annex [String]+getLog :: Key -> [CommandParam] -> Annex ([String], IO Bool) getLog key os = do 	top <- fromRepo Git.repoPath 	p <- liftIO $ relPathCwdToFile top 	config <- Annex.getGitConfig 	let logfile = p </> locationLogFile config key-	inRepo $ pipeNullSplitZombie $+	inRepo $ pipeNullSplit $ 		[ Param "log" 		, Param "-z" 		, Param "--pretty=format:%ct"@@ -196,4 +202,5 @@ #endif  showTimeStamp :: TimeZone -> POSIXTime -> String-showTimeStamp zone = show . utcToLocalTime zone . posixSecondsToUTCTime+showTimeStamp zone = formatTime defaultTimeLocale rfc822DateFormat +	. utcToZonedTime zone . posixSecondsToUTCTime
Command/Merge.hs view
@@ -9,8 +9,7 @@  import Command import qualified Annex.Branch-import qualified Git.Branch-import Command.Sync (prepMerge, mergeLocal)+import Command.Sync (prepMerge, mergeLocal, getCurrBranch)  cmd :: Command cmd = command "merge" SectionMaintenance@@ -34,4 +33,4 @@ mergeSynced :: CommandStart mergeSynced = do 	prepMerge-	mergeLocal =<< inRepo Git.Branch.current+	mergeLocal =<< join getCurrBranch
Command/ResolveMerge.hs view
@@ -29,7 +29,7 @@ 	let merge_head = d </> "MERGE_HEAD" 	them <- fromMaybe (error nomergehead) . extractSha 		<$> liftIO (readFile merge_head)-	ifM (resolveMerge (Just us) them)+	ifM (resolveMerge (Just us) them False) 		( do 			void $ commitResolvedMerge Git.Branch.ManualCommit 			next $ next $ return True
Command/Sync.hs view
@@ -1,13 +1,16 @@ {- git-annex command  -  - Copyright 2011 Joachim Breitner <mail@joachim-breitner.de>- - Copyright 2011-2014 Joey Hess <id@joeyh.name>+ - Copyright 2011-2016 Joey Hess <id@joeyh.name>  -  - Licensed under the GNU GPL version 3 or higher.  -}  module Command.Sync ( 	cmd,+	CurrBranch,+	getCurrBranch,+	merge, 	prepMerge, 	mergeLocal, 	mergeRemote,@@ -43,6 +46,7 @@ import Annex.UUID import Logs.UUID import Annex.AutoMerge+import Annex.AdjustedBranch import Annex.Ssh import Annex.BloomFilter import Utility.Bloom@@ -95,20 +99,7 @@ seek o = allowConcurrentOutput $ do 	prepMerge -	-- There may not be a branch checked out until after the commit,-	-- or perhaps after it gets merged from the remote, or perhaps-	-- never.-	-- So only look it up once it's needed, and once there is a-	-- branch, cache it.-	mvar <- liftIO newEmptyMVar-	let getbranch = ifM (liftIO $ isEmptyMVar mvar)-		( do-			branch <- inRepo Git.Branch.current-			when (isJust branch) $-				liftIO $ putMVar mvar branch-			return branch-		, liftIO $ readMVar mvar-		)+	getbranch <- getCurrBranch  	let withbranch a = a =<< getbranch  	remotes <- syncRemotes (syncWith o)@@ -140,15 +131,50 @@ 	-- Pushes to remotes can run concurrently. 	mapM_ (commandAction . withbranch . pushRemote o) gitremotes +type CurrBranch = (Maybe Git.Branch, Maybe Adjustment)++{- There may not be a branch checked out until after the commit,+ - or perhaps after it gets merged from the remote, or perhaps+ - never.+ -+ - So only look it up once it's needed, and once there is a+ - branch, cache it.+ -+ - When on an adjusted branch, gets the original branch, and the adjustment.+ -}+getCurrBranch :: Annex (Annex CurrBranch)+getCurrBranch = do+	mvar <- liftIO newEmptyMVar+	return $ ifM (liftIO $ isEmptyMVar mvar)+		( do+			currbranch <- inRepo Git.Branch.current+			case currbranch of+				Nothing -> return (Nothing, Nothing)+				Just b -> do+					let v = case adjustedToOriginal b of+						Nothing -> (Just b, Nothing)+						Just (adj, origbranch) ->+							(Just origbranch, Just adj)+					liftIO $ putMVar mvar v+					return v+		, liftIO $ readMVar mvar+		)+ {- Merging may delete the current directory, so go to the top  - of the repo. This also means that sync always acts on all files in the  - repository, not just on a subdirectory. -} prepMerge :: Annex () prepMerge = Annex.changeDirectory =<< fromRepo Git.repoPath -syncBranch :: Git.Ref -> Git.Ref-syncBranch = Git.Ref.under "refs/heads/synced" . fromDirectBranch+merge :: CurrBranch -> Git.Branch.CommitMode -> Git.Branch -> Annex Bool+merge (Just b, Just adj) commitmode tomerge =+	updateAdjustedBranch tomerge (b, adj) commitmode+merge (b, _) commitmode tomerge =+	autoMergeFrom tomerge b commitmode +syncBranch :: Git.Branch -> Git.Branch+syncBranch = Git.Ref.under "refs/heads/synced" . fromDirectBranch . fromAdjustedBranch+ remoteBranch :: Remote -> Git.Ref -> Git.Ref remoteBranch remote = Git.Ref.underBase $ "refs/remotes/" ++ Remote.name remote @@ -188,7 +214,8 @@ 			void preCommitDirect 			commitStaged Git.Branch.ManualCommit commitmessage 		, do-			inRepo $ Git.Branch.commitQuiet Git.Branch.ManualCommit+			showOutput+			void $ inRepo $ Git.Branch.commitCommand Git.Branch.ManualCommit 				[ Param "-a" 				, Param "-m" 				, Param commitmessage@@ -216,50 +243,55 @@ 	void $ inRepo $ Git.Branch.commit commitmode False commitmessage branch parents 	return True -mergeLocal :: Maybe Git.Ref -> CommandStart-mergeLocal Nothing = stop-mergeLocal (Just branch) = go =<< needmerge+mergeLocal :: CurrBranch -> CommandStart+mergeLocal currbranch@(Just branch, madj) = go =<< needmerge   where 	syncbranch = syncBranch branch 	needmerge = ifM isBareRepo 		( return False 		, ifM (inRepo $ Git.Ref.exists syncbranch)-			( inRepo $ Git.Branch.changed branch syncbranch+			( inRepo $ Git.Branch.changed branch' syncbranch 			, return False 			) 		) 	go False = stop 	go True = do 		showStart "merge" $ Git.Ref.describe syncbranch-		next $ next $ autoMergeFrom syncbranch (Just branch) Git.Branch.ManualCommit+		next $ next $ merge currbranch Git.Branch.ManualCommit syncbranch+	branch' = maybe branch (adjBranch . originalToAdjusted branch) madj+mergeLocal (Nothing, _) = stop -pushLocal :: Maybe Git.Ref -> CommandStart+pushLocal :: CurrBranch -> CommandStart pushLocal b = do 	updateSyncBranch b 	stop -updateSyncBranch :: Maybe Git.Ref -> Annex ()-updateSyncBranch Nothing = noop-updateSyncBranch (Just branch) = do+updateSyncBranch :: CurrBranch -> Annex ()+updateSyncBranch (Nothing, _) = noop+updateSyncBranch (Just branch, madj) = do+	-- When in an adjusted branch, propigate any changes made to it+	-- back to the original branch.+	maybe noop (propigateAdjustedCommits branch) madj 	-- Update the sync branch to match the new state of the branch-	inRepo $ updateBranch $ syncBranch branch+	inRepo $ updateBranch (syncBranch branch) branch 	-- In direct mode, we're operating on some special direct mode-	-- branch, rather than the intended branch, so update the indended+	-- branch, rather than the intended branch, so update the intended 	-- branch. 	whenM isDirect $-		inRepo $ updateBranch $ fromDirectBranch branch+		inRepo $ updateBranch (fromDirectBranch branch) branch -updateBranch :: Git.Ref -> Git.Repo -> IO ()-updateBranch syncbranch g = +updateBranch :: Git.Branch -> Git.Branch -> Git.Repo -> IO ()+updateBranch syncbranch updateto g =  	unlessM go $ error $ "failed to update " ++ Git.fromRef syncbranch   where 	go = Git.Command.runBool 		[ Param "branch" 		, Param "-f" 		, Param $ Git.fromRef $ Git.Ref.base syncbranch+		, Param $ Git.fromRef $ updateto 		] g -pullRemote :: SyncOptions -> Remote -> Maybe Git.Ref -> CommandStart+pullRemote :: SyncOptions -> Remote -> CurrBranch -> CommandStart pullRemote o remote branch = stopUnless (pure $ pullOption o) $ do 	showStart "pull" (Remote.name remote) 	next $ do@@ -276,26 +308,27 @@  - were committed (or pushed changes, if this is a bare remote),  - while the synced/master may have changes that some  - other remote synced to this remote. So, merge them both. -}-mergeRemote :: Remote -> Maybe Git.Ref -> CommandCleanup-mergeRemote remote b = ifM isBareRepo+mergeRemote :: Remote -> CurrBranch -> CommandCleanup+mergeRemote remote currbranch = ifM isBareRepo 	( return True-	, case b of-		Nothing -> do+	, case currbranch of+		(Nothing, _) -> do 			branch <- inRepo Git.Branch.currentUnsafe-			and <$> mapM (merge Nothing) (branchlist branch)-		Just thisbranch -> do-			inRepo $ updateBranch $ syncBranch thisbranch-			and <$> (mapM (merge (Just thisbranch)) =<< tomerge (branchlist b))+			mergelisted (pure (branchlist branch))+		(Just branch, _) -> do+			inRepo $ updateBranch (syncBranch branch) branch+			mergelisted (tomerge (branchlist (Just branch))) 	)   where-	merge thisbranch br = autoMergeFrom (remoteBranch remote br) thisbranch Git.Branch.ManualCommit+	mergelisted getlist = and <$> +		(mapM (merge currbranch Git.Branch.ManualCommit . remoteBranch remote) =<< getlist) 	tomerge = filterM (changed remote) 	branchlist Nothing = [] 	branchlist (Just branch) = [branch, syncBranch branch] -pushRemote :: SyncOptions -> Remote -> Maybe Git.Ref -> CommandStart-pushRemote _o _remote Nothing = stop-pushRemote o remote (Just branch) = stopUnless (pure (pushOption o) <&&> needpush) $ do+pushRemote :: SyncOptions -> Remote -> CurrBranch -> CommandStart+pushRemote _o _remote (Nothing, _) = stop+pushRemote o remote (Just branch, _) = stopUnless (pure (pushOption o) <&&> needpush) $ do 	showStart "push" (Remote.name remote) 	next $ next $ do 		showOutput@@ -339,16 +372,16 @@  - The sync push will fail to overwrite if receive.denyNonFastforwards is  - set on the remote.  -}-pushBranch :: Remote -> Git.Ref -> Git.Repo -> IO Bool+pushBranch :: Remote -> Git.Branch -> Git.Repo -> IO Bool pushBranch remote branch g = tryIO (directpush g) `after` syncpush g   where 	syncpush = Git.Command.runBool $ pushparams 		[ Git.Branch.forcePush $ refspec Annex.Branch.name-		, refspec branch+		, refspec $ fromAdjustedBranch branch 		] 	directpush = Git.Command.runQuiet $ pushparams 		[ Git.fromRef $ Git.Ref.base $ Annex.Branch.name-		, Git.fromRef $ Git.Ref.base $ fromDirectBranch branch+		, Git.fromRef $ Git.Ref.base $ fromDirectBranch $ fromAdjustedBranch branch 		] 	pushparams branches = 		[ Param "push"
Command/Unannex.hs view
@@ -5,8 +5,6 @@  - Licensed under the GNU GPL version 3 or higher.  -} -{-# LANGUAGE CPP #-}- module Command.Unannex where  import Command@@ -107,15 +105,11 @@ 	copyfrom src =  		thawContent file `after` liftIO (copyFileExternal CopyAllMetaData src file) 	hardlinkfrom src =-#ifndef mingw32_HOST_OS 		-- creating a hard link could fall; fall back to copying 		ifM (liftIO $ catchBoolIO $ createLink src file >> return True) 			( return True 			, copyfrom src 			)-#else-		copyfrom src-#endif  performDirect :: FilePath -> Key -> CommandPerform performDirect file key = do
Command/Upgrade.hs view
@@ -9,6 +9,8 @@  import Command import Upgrade+import Annex.Version+import Annex.Init  cmd :: Command cmd = dontCheck repoExists $ -- because an old version may not seem to exist@@ -22,5 +24,7 @@ start :: CommandStart start = do 	showStart "upgrade" "."+	whenM (isNothing <$> getVersion) $ do+		initialize Nothing Nothing 	r <- upgrade False 	next $ next $ return r
Git/Branch.hs view
@@ -48,15 +48,25 @@ changed :: Branch -> Branch -> Repo -> IO Bool changed origbranch newbranch repo 	| origbranch == newbranch = return False-	| otherwise = not . null <$> diffs+	| otherwise = not . null+		<$> changed' origbranch newbranch [Param "-n1"] repo   where-	diffs = pipeReadStrict++changed' :: Branch -> Branch -> [CommandParam] -> Repo -> IO String+changed' origbranch newbranch extraps repo = pipeReadStrict ps repo+  where+	ps = 		[ Param "log" 		, Param (fromRef origbranch ++ ".." ++ fromRef newbranch)-		, Param "-n1" 		, Param "--pretty=%H"-		] repo+		] ++ extraps +{- Lists commits that are in the second branch and not in the first branch. -}+changedCommits :: Branch -> Branch -> [CommandParam] -> Repo -> IO [Sha]+changedCommits origbranch newbranch extraps repo = +	catMaybes . map extractSha . lines+		<$> changed' origbranch newbranch extraps repo+	 {- Check if it's possible to fast-forward from the old  - ref to the new ref.  -@@ -90,7 +100,7 @@   where 	no_ff = return False 	do_ff to = do-		update branch to repo+		update' branch to repo 		return True 	findbest c [] = return $ Just c 	findbest c (r:rs)@@ -121,10 +131,6 @@ commitCommand :: CommitMode -> [CommandParam] -> Repo -> IO Bool commitCommand = commitCommand' runBool -{- Commit will fail when the tree is clean. This suppresses that error. -}-commitQuiet :: CommitMode -> [CommandParam] -> Repo -> IO ()-commitQuiet commitmode ps = void . tryIO . commitCommand' runQuiet commitmode ps- commitCommand' :: ([CommandParam] -> Repo -> IO a) -> CommitMode -> [CommandParam] -> Repo -> IO a commitCommand' runner commitmode ps = runner $ 	Param "commit" : applyCommitMode commitmode ps@@ -145,7 +151,7 @@ 	ifM (cancommit tree) 		( do 			sha <- commitTree commitmode message parentrefs tree repo-			update branch sha repo+			update' branch sha repo 			return $ Just sha 		, return Nothing 		)@@ -174,12 +180,21 @@ forcePush :: String -> String forcePush b = "+" ++ b -{- Updates a branch (or other ref) to a new Sha. -}-update :: Branch -> Sha -> Repo -> IO ()-update branch sha = run +{- Updates a branch (or other ref) to a new Sha or branch Ref. -}+update :: String -> Branch -> Ref -> Repo -> IO ()+update message branch r = run 	[ Param "update-ref"+	, Param "-m"+	, Param message 	, Param $ fromRef branch-	, Param $ fromRef sha+	, Param $ fromRef r+	]++update' :: Branch -> Ref -> Repo -> IO ()+update' branch r = run+	[ Param "update-ref"+	, Param $ fromRef branch+	, Param $ fromRef r 	]  {- Checks out a branch, creating it if necessary. -}
Git/CatFile.hs view
@@ -125,15 +125,17 @@ parseCommit :: L.ByteString -> Maybe Commit parseCommit b = Commit 	<$> (extractSha . L8.unpack =<< field "tree")+	<*> Just (maybe [] (mapMaybe (extractSha . L8.unpack)) (fields "parent")) 	<*> (parsemetadata <$> field "author") 	<*> (parsemetadata <$> field "committer") 	<*> Just (L8.unpack $ L.intercalate (L.singleton nl) message)   where-	field n = M.lookup (fromString n) fields-	fields = M.fromList ((map breakfield) header)+	field n = headMaybe =<< fields n+	fields n = M.lookup (fromString n) fieldmap+	fieldmap = M.fromListWith (++) ((map breakfield) header) 	breakfield l = 		let (k, sp_v) = L.break (== sp) l-		in (k, L.drop 1 sp_v)+		in (k, [L.drop 1 sp_v]) 	(header, message) = separate L.null ls 	ls = L.split nl b 
Git/Command.hs view
@@ -17,9 +17,11 @@ {- Constructs a git command line operating on the specified repo. -} gitCommandLine :: [CommandParam] -> Repo -> [CommandParam] gitCommandLine params r@(Repo { location = l@(Local { } ) }) =-	setdir : settree ++ gitGlobalOpts r ++ params+	setdir ++ settree ++ gitGlobalOpts r ++ params   where-	setdir = Param $ "--git-dir=" ++ gitdir l+	setdir+		| gitEnvOverridesGitDir r = []+		| otherwise = [Param $ "--git-dir=" ++ gitdir l] 	settree = case worktree l of 		Nothing -> [] 		Just t -> [Param $ "--work-tree=" ++ t]
Git/Construct.hs view
@@ -236,6 +236,7 @@ 	, remotes = [] 	, remoteName = Nothing 	, gitEnv = Nothing+	, gitEnvOverridesGitDir = False 	, gitGlobalOpts = [] 	} 
Git/DiffTree.hs view
@@ -14,6 +14,7 @@ 	diffWorkTree, 	diffFiles, 	diffLog,+	commitDiff, ) where  import Numeric@@ -72,16 +73,23 @@ diffFiles = getdiff (Param "diff-files")  {- Runs git log in --raw mode to get the changes that were made in- - a particular commit. The output format is adjusted to be the same- - as diff-tree --raw._-}+ - a particular commit to particular files. The output format+ - is adjusted to be the same as diff-tree --raw._-} diffLog :: [CommandParam] -> Repo -> IO ([DiffTreeItem], IO Bool) diffLog params = getdiff (Param "log") 	(Param "-n1" : Param "--abbrev=40" : Param "--pretty=format:" : params) +{- Uses git show to get the changes made by a commit.+ -+ - Does not support merge commits, and will fail on them. -}+commitDiff :: Sha -> Repo -> IO ([DiffTreeItem], IO Bool)+commitDiff ref = getdiff (Param "show")+	[ Param "--abbrev=40", Param "--pretty=", Param "--raw", Param (fromRef ref) ]+ getdiff :: CommandParam -> [CommandParam] -> Repo -> IO ([DiffTreeItem], IO Bool) getdiff command params repo = do 	(diff, cleanup) <- pipeNullSplit ps repo-	return (parseDiffRaw diff, cleanup)+	return (fromMaybe (error $ "git " ++ show (toCommand ps) ++ " parse failed") (parseDiffRaw diff), cleanup)   where 	ps =  		command :@@ -92,23 +100,24 @@ 		params  {- Parses --raw output used by diff-tree and git-log. -}-parseDiffRaw :: [String] -> [DiffTreeItem]+parseDiffRaw :: [String] -> Maybe [DiffTreeItem] parseDiffRaw l = go l []   where-	go [] c = c-	go (info:f:rest) c = go rest (mk info f : c)-	go (s:[]) _ = error $ "diff-tree parse error " ++ s+	go [] c = Just c+	go (info:f:rest) c = case mk info f of+		Nothing -> Nothing+		Just i -> go rest (i:c)+	go (_:[]) _ = Nothing -	mk info f = DiffTreeItem -		{ srcmode = readmode srcm-		, dstmode = readmode dstm-		, srcsha = fromMaybe (error "bad srcsha") $ extractSha ssha-		, dstsha = fromMaybe (error "bad dstsha") $ extractSha dsha-		, status = s-		, file = asTopFilePath $ fromInternalGitPath $ Git.Filename.decode f-		}+	mk info f = DiffTreeItem+		<$> readmode srcm+		<*> readmode dstm+		<*> extractSha ssha+		<*> extractSha dsha+		<*> pure s+		<*> pure (asTopFilePath $ fromInternalGitPath $ Git.Filename.decode f) 	  where-		readmode = fst . Prelude.head . readOct+		readmode = fst <$$> headMaybe . readOct  		-- info = :<srcmode> SP <dstmode> SP <srcsha> SP <dstsha> SP <status> 		-- All fields are fixed, so we can pull them out of
Git/FilePath.hs view
@@ -31,7 +31,7 @@  {- A FilePath, relative to the top of the git repository. -} newtype TopFilePath = TopFilePath { getTopFilePath :: FilePath }-	deriving (Show, Eq)+	deriving (Show, Eq, Ord)  {- Path to a TopFilePath, within the provided git repo. -} fromTopFilePath :: TopFilePath -> Git.Repo -> FilePath
+ Git/LockFile.hs view
@@ -0,0 +1,78 @@+{- git lock files+ -+ - Copyright 2016 Joey Hess <id@joeyh.name>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++{-# LANGUAGE CPP #-}++module Git.LockFile where++import Common++#ifndef mingw32_HOST_OS+import System.Posix.Types+#else+import System.Win32.Types+import System.Win32.File+#endif++#ifndef mingw32_HOST_OS+data LockHandle = LockHandle FilePath Fd+#else+data LockHandle = LockHandle FilePath HANDLE+#endif++{- Uses the same exclusive locking that git does.+ - Throws an IO exception if the file is already locked.+ -+ - Note that git's locking method suffers from the problem that+ - a dangling lock can be left if a process is terminated at the wrong+ - time.+ -}+openLock :: FilePath -> IO LockHandle+openLock lck = openLock' lck `catchNonAsync` lckerr+  where+	lckerr e = do+		-- Same error message displayed by git.+		whenM (doesFileExist lck) $+			hPutStrLn stderr $ unlines+				[ "fatal: Unable to create '" ++ lck ++ "': " ++ show e+				, ""+				, "If no other git process is currently running, this probably means a"+				, "git process crashed in this repository earlier. Make sure no other git"+				, "process is running and remove the file manually to continue."+				]+		throwM e++openLock' :: FilePath -> IO LockHandle+openLock' lck = do+#ifndef mingw32_HOST_OS+	-- On unix, git simply uses O_EXCL+	h <- openFd lck ReadWrite (Just 0O666)+		(defaultFileFlags { exclusive = True })+	setFdOption h CloseOnExec True+#else+	-- It's not entirely clear how git manages locking on Windows,+	-- since it's buried in the portability layer, and different+	-- versions of git for windows use different portability layers.+	-- But, we can be fairly sure that holding the lock file open on+	-- windows is enough to prevent another process from opening it.+	--+	-- So, all that's needed is a way to open the file, that fails+	-- if the file already exists. Using CreateFile with CREATE_NEW +	-- accomplishes that.+	h <- createFile lck gENERIC_WRITE fILE_SHARE_NONE Nothing+		cREATE_NEW fILE_ATTRIBUTE_NORMAL Nothing+#endif+	return (LockHandle lck h)++closeLock :: LockHandle -> IO ()+closeLock (LockHandle lck h) = do+#ifndef mingw32_HOST_OS+	closeFd h+#else+	closeHandle h+#endif+	removeFile lck
Git/Merge.hs view
@@ -15,12 +15,15 @@  {- Avoids recent git's interactive merge. -} mergeNonInteractive :: Ref -> CommitMode -> Repo -> IO Bool-mergeNonInteractive branch commitmode+mergeNonInteractive = mergeNonInteractive' []++mergeNonInteractive' :: [CommandParam] -> Ref -> CommitMode -> Repo -> IO Bool+mergeNonInteractive' extraparams branch commitmode 	| older "1.7.7.6" = merge [Param $ fromRef branch] 	| otherwise = merge $ [Param "--no-edit", Param $ fromRef branch]   where-	merge ps = runBool $ cp ++ [Param "merge"] ++ ps-	cp+	merge ps = runBool $ sp ++ [Param "merge"] ++ ps ++ extraparams+	sp 		| commitmode == AutomaticCommit = 			[Param "-c", Param "commit.gpgsign=false"] 		| otherwise = []
Git/Ref.hs view
@@ -18,6 +18,12 @@ headRef :: Ref headRef = Ref "HEAD" +headFile :: Repo -> FilePath+headFile r = localGitDir r </> "HEAD"++setHeadRef :: Ref -> Repo -> IO ()+setHeadRef ref r = writeFile (headFile r) ("ref: " ++ fromRef ref)+ {- Converts a fully qualified git ref into a user-visible string. -} describe :: Ref -> String describe = fromRef . base@@ -31,11 +37,14 @@ 		| prefix `isPrefixOf` s = drop (length prefix) s 		| otherwise = s +{- Gets the basename of any qualified ref. -}+basename :: Ref -> Ref+basename = Ref . reverse . takeWhile (/= '/') . reverse . fromRef+ {- Given a directory and any ref, takes the basename of the ref and puts  - it under the directory. -} under :: String -> Ref -> Ref-under dir r = Ref $ dir ++ "/" ++-	(reverse $ takeWhile (/= '/') $ reverse $ fromRef r)+under dir r = Ref $ dir ++ "/" ++ fromRef (basename r)  {- Given a directory such as "refs/remotes/origin", and a ref such as  - refs/heads/master, yields a version of that ref under the directory,
Git/Tree.hs view
@@ -5,7 +5,7 @@  - Licensed under the GNU GPL version 3 or higher.  -} -{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE BangPatterns, TypeSynonymInstances, FlexibleInstances #-}  module Git.Tree ( 	Tree(..),@@ -28,6 +28,8 @@ import Numeric import System.Posix.Types import Control.Monad.IO.Class+import qualified Data.Set as S+import qualified Data.Map as M  newtype Tree = Tree [TreeContent] 	deriving (Show)@@ -38,7 +40,7 @@ 	| RecordedSubTree TopFilePath Sha [TreeContent] 	-- A subtree that has not yet been recorded in git. 	| NewSubTree TopFilePath [TreeContent]-	deriving (Show)+	deriving (Show, Eq, Ord)  {- Gets the Tree for a Ref. -} getTree :: Ref -> Repo -> IO Tree@@ -107,74 +109,154 @@ 	]  data TreeItem = TreeItem TopFilePath FileMode Sha-	deriving (Eq)+	deriving (Show, Eq) +treeItemToTreeContent :: TreeItem -> TreeContent+treeItemToTreeContent (TreeItem f m s) = TreeBlob f m s++treeItemsToTree :: [TreeItem] -> Tree+treeItemsToTree = go M.empty+  where+	go m [] = Tree $ filter (notElem '/' . gitPath) (M.elems m)+	go m (i:is)+		| '/' `notElem` p =+			go (M.insert p (treeItemToTreeContent i) m) is+		| otherwise = case M.lookup idir m of+			Just (NewSubTree d l) ->+				go (addsubtree idir m (NewSubTree d (c:l))) is+			_ ->+				go (addsubtree idir m (NewSubTree (asTopFilePath idir) [c])) is+	  where+		p = gitPath i+		idir = takeDirectory p+		c = treeItemToTreeContent i++	addsubtree d m t+		| elem '/' d = +			let m' = M.insert d t m+			in case M.lookup parent m' of+				Just (NewSubTree d' l) ->+					let l' = filter (\ti -> gitPath ti /= d) l+					in addsubtree parent m' (NewSubTree d' (t:l'))+				_ -> addsubtree parent m' (NewSubTree (asTopFilePath parent) [t])+		| otherwise = M.insert d t m+	  where+		parent = takeDirectory d+ {- Applies an adjustment to items in a tree.  -- - While less flexible than using getTree and recordTree, this avoids- - buffering the whole tree in memory.+ - While less flexible than using getTree and recordTree,+ - this avoids buffering the whole tree in memory.  -}-adjustTree :: (MonadIO m, MonadMask m) => (TreeItem -> m (Maybe TreeItem)) -> Ref -> Repo -> m Sha-adjustTree adjust r repo = withMkTreeHandle repo $ \h -> do-	(l, cleanup) <- liftIO $ lsTreeWithObjects r repo-	(l', _, _) <- go h False [] topTree l-	sha <- liftIO $ mkTree h l'-	void $ liftIO cleanup-	return sha+adjustTree+	:: (Functor m, MonadIO m, MonadMask m)+	=> (TreeItem -> m (Maybe TreeItem))+	-- ^ Adjust an item in the tree. Nothing deletes the item.+	-- Cannot move the item to a different tree.+	-> [TreeItem]+	-- ^ New items to add to the tree.+	-> [TopFilePath]+	-- ^ Files to remove from the tree.+	-> Ref+	-> Repo+	-> m Sha+adjustTree adjusttreeitem addtreeitems removefiles r repo =+	withMkTreeHandle repo $ \h -> do+		(l, cleanup) <- liftIO $ lsTreeWithObjects r repo+		(l', _, _) <- go h False [] inTopTree l+		l'' <- adjustlist h inTopTree (const True) l'+		sha <- liftIO $ mkTree h l''+		void $ liftIO cleanup+		return sha   where 	go _ wasmodified c _ [] = return (c, wasmodified, []) 	go h wasmodified c intree (i:is)-		| intree i =-			case readObjectType (LsTree.typeobj i) of-				Just BlobObject -> do-					let ti = TreeItem (LsTree.file i) (LsTree.mode i) (LsTree.sha i)-					v <- adjust ti-					case v of-						Nothing -> go h True c intree is-						Just ti'@(TreeItem f m s) ->-							let !modified = wasmodified || ti' /= ti-							    blob = TreeBlob f m s-							in go h modified (blob:c) intree is-				Just TreeObject -> do-					(sl, modified, is') <- go h False [] (subTree i) is-					subtree <- if modified-						then liftIO $ recordSubTree h $ NewSubTree (LsTree.file i) sl-						else return $ RecordedSubTree (LsTree.file i) (LsTree.sha i) [] -					let !modified' = modified || wasmodified-					go h modified' (subtree : c) intree is'-				_ -> error ("unexpected object type \"" ++ LsTree.typeobj i ++ "\"")+		| intree i = case readObjectType (LsTree.typeobj i) of+			Just BlobObject -> do+				let ti = TreeItem (LsTree.file i) (LsTree.mode i) (LsTree.sha i)+				v <- adjusttreeitem ti+				case v of+					Nothing -> go h True c intree is+					Just ti'@(TreeItem f m s) ->+						let !modified = wasmodified || ti' /= ti+						    blob = TreeBlob f m s+						in go h modified (blob:c) intree is+			Just TreeObject -> do+				(sl, modified, is') <- go h False [] (beneathSubTree i) is+				sl' <- adjustlist h (inTree i) (beneathSubTree i) sl+				subtree <- if modified || sl' /= sl+					then liftIO $ recordSubTree h $ NewSubTree (LsTree.file i) sl'+					else return $ RecordedSubTree (LsTree.file i) (LsTree.sha i) [] +				let !modified' = modified || wasmodified+				go h modified' (subtree : c) intree is'+			_ -> error ("unexpected object type \"" ++ LsTree.typeobj i ++ "\"") 		| otherwise = return (c, wasmodified, i:is) +	adjustlist h ishere underhere l = do+		let (addhere, rest) = partition ishere addtreeitems+		let l' = filter (not . removed) $+			map treeItemToTreeContent addhere ++ l+		let inl i = any (\t -> beneathSubTree t i) l'+		let (Tree addunderhere) = treeItemsToTree $+			filter (\i -> underhere i && not (inl i)) rest+		addunderhere' <- liftIO $ mapM (recordSubTree h) addunderhere+		return (addunderhere'++l')++	removeset = S.fromList removefiles+	removed (TreeBlob f _ _) = S.member f removeset+	removed _ = False+ {- Assumes the list is ordered, with tree objects coming right before their  - contents. -} extractTree :: [LsTree.TreeItem] -> Either String Tree-extractTree l = case go [] topTree l of+extractTree l = case go [] inTopTree l of 	Right (t, []) -> Right (Tree t) 	Right _ -> parseerr "unexpected tree form" 	Left e -> parseerr e   where 	go t _ [] = Right (t, []) 	go t intree (i:is)-		| intree i = -			case readObjectType (LsTree.typeobj i) of-				Just BlobObject ->-					let b = TreeBlob (LsTree.file i) (LsTree.mode i) (LsTree.sha i)-					in go (b:t) intree is-				Just TreeObject -> case go [] (subTree i) is of-					Right (subtree, is') ->-						let st = RecordedSubTree (LsTree.file i) (LsTree.sha i) subtree-						in go (st:t) intree is'-					Left e -> Left e-				_ -> parseerr ("unexpected object type \"" ++ LsTree.typeobj i ++ "\"")+		| intree i = case readObjectType (LsTree.typeobj i) of+			Just BlobObject ->+				let b = TreeBlob (LsTree.file i) (LsTree.mode i) (LsTree.sha i)+				in go (b:t) intree is+			Just TreeObject -> case go [] (beneathSubTree i) is of+				Right (subtree, is') ->+					let st = RecordedSubTree (LsTree.file i) (LsTree.sha i) subtree+					in go (st:t) intree is'+				Left e -> Left e+			_ -> parseerr ("unexpected object type \"" ++ LsTree.typeobj i ++ "\"") 		| otherwise = Right (t, i:is) 	parseerr = Left -type InTree = LsTree.TreeItem -> Bool+class GitPath t where+	gitPath :: t -> FilePath -topTree :: InTree-topTree = notElem '/' . getTopFilePath . LsTree.file+instance GitPath FilePath where+	gitPath = id -subTree :: LsTree.TreeItem -> InTree-subTree t =-	let prefix = getTopFilePath (LsTree.file t) ++ "/"-	in (\i -> prefix `isPrefixOf` getTopFilePath (LsTree.file i))+instance GitPath TopFilePath where+	gitPath = getTopFilePath++instance GitPath TreeItem where+	gitPath (TreeItem f _ _) = gitPath f++instance GitPath LsTree.TreeItem where+	gitPath = gitPath . LsTree.file++instance GitPath TreeContent where+	gitPath (TreeBlob f _ _) = gitPath f+	gitPath (RecordedSubTree f _ _) = gitPath f+	gitPath (NewSubTree f _) = gitPath f++inTopTree :: GitPath t => t -> Bool+inTopTree = inTree "."++inTree :: (GitPath t, GitPath f) => t -> f -> Bool+inTree t f = gitPath t == takeDirectory (gitPath f)++beneathSubTree :: (GitPath t, GitPath f) => t -> f -> Bool+beneathSubTree t f = prefix `isPrefixOf` gitPath f+  where+	tp = gitPath t+	prefix = if null tp then tp else tp ++ "/"
Git/Types.hs view
@@ -39,6 +39,7 @@ 	, remoteName :: Maybe RemoteName 	-- alternate environment to use when running git commands 	, gitEnv :: Maybe [(String, String)]+	, gitEnvOverridesGitDir :: Bool 	-- global options to pass to git when running git commands 	, gitGlobalOpts :: [CommandParam] 	} deriving (Show, Eq, Ord)@@ -105,6 +106,7 @@  data Commit = Commit 	{ commitTree :: Sha+	, commitParent :: [Sha] 	, commitAuthorMetaData :: CommitMetaData 	, commitCommitterMetaData :: CommitMetaData 	, commitMessage :: String
Limit.hs view
@@ -104,7 +104,7 @@  	cglob = compileGlob glob CaseSensative -- memoized 	go (MatchingKey _) = pure False 	go (MatchingFile fi) = liftIO $ catchBoolIO $-		matchGlob cglob <$> magicFile magic (matchFile fi)+		matchGlob cglob <$> magicFile magic (currFile fi) 	go (MatchingInfo _ _ _ mimeval) = matchGlob cglob <$> getInfo mimeval matchMagic Nothing _ = Left "unable to load magic database; \"mimetype\" cannot be used" #endif
Remote/Bup.hs view
@@ -132,10 +132,10 @@ 	let params = bupSplitParams r buprepo k [] 	showOutput -- make way for bup output 	let cmd = proc "bup" (toCommand params)-	runner <- ifM commandProgressDisabled-		( return feedWithQuietOutput-		, return (withHandle StdinHandle)-		)+	quiet <- commandProgressDisabled+	let runner = if quiet+			then feedWithQuietOutput+			else withHandle StdinHandle 	liftIO $ runner createProcessSuccess cmd $ \h -> do 		meteredWrite p h b 		return True
Remote/Ddar.hs view
@@ -122,8 +122,8 @@ ddarRemoteCall ddarrepo cmd params 	| ddarLocal ddarrepo = return ("ddar", localParams) 	| otherwise = do-		os <- sshOptions (host, Nothing) (ddarRepoConfig ddarrepo) remoteParams-		return ("ssh", os)+		os <- sshOptions (host, Nothing) (ddarRepoConfig ddarrepo) []+		return ("ssh", os ++ remoteParams)   where 	(host, ddarrepo') = splitRemoteDdarRepo ddarrepo 	localParams = Param [cmd] : Param (ddarRepoLocation ddarrepo) : params@@ -158,8 +158,8 @@ 			Left _ -> Right False 			Right status -> Right $ isDirectory status 	| otherwise = do-		ps <- sshOptions (host, Nothing) (ddarRepoConfig ddarrepo) params-		exitCode <- liftIO $ safeSystem "ssh" ps+		ps <- sshOptions (host, Nothing) (ddarRepoConfig ddarrepo) []+		exitCode <- liftIO $ safeSystem "ssh" (ps ++ params) 		case exitCode of 			ExitSuccess -> return $ Right True 			ExitFailure 1 -> return $ Right False
Remote/Git.hs view
@@ -695,7 +695,6 @@ mkCopier remotewanthardlink rsyncparams = do 	let copier = \src dest p check -> unVerified $ 		rsyncOrCopyFile rsyncparams src dest p <&&> check-#ifndef mingw32_HOST_OS 	localwanthardlink <- wantHardLink 	let linker = \src dest -> createLink src dest >> return True 	ifM (pure (remotewanthardlink || localwanthardlink) <&&> not <$> isDirect)@@ -706,6 +705,3 @@ 				) 		, return copier 		)-#else-	return $ if remotewanthardlink then copier else copier-#endif
Test.hs view
@@ -231,6 +231,7 @@ 	, testCase "sync" test_sync 	, testCase "union merge regression" test_union_merge_regression 	, testCase "conflict resolution" test_conflict_resolution+	, testCase "conflict resolution (adjusted branch)" test_conflict_resolution_adjusted_branch 	, testCase "conflict resolution movein regression" test_conflict_resolution_movein_regression 	, testCase "conflict resolution (mixed directory and file)" test_mixed_conflict_resolution 	, testCase "conflict resolution symlink bit" test_conflict_resolution_symlink_bit@@ -1045,6 +1046,41 @@ 			git_annex "get" v @? "get failed" 			git_annex_expectoutput "find" v v +{- Conflict resolution while in an adjusted branch. -}+test_conflict_resolution_adjusted_branch :: Assertion+test_conflict_resolution_adjusted_branch = +	withtmpclonerepo $ \r1 ->+		withtmpclonerepo $ \r2 -> do+			indir r1 $ do+				disconnectOrigin+				writeFile conflictor "conflictor1"+				add_annex conflictor @? "add conflicter failed"+				git_annex "sync" [] @? "sync failed in r1"+			indir r2 $ do+				disconnectOrigin+				writeFile conflictor "conflictor2"+				add_annex conflictor @? "add conflicter failed"+				git_annex "sync" [] @? "sync failed in r2"+				-- need v6 to use adjust+				git_annex "upgrade" [] @? "upgrade failed"+				git_annex "adjust" ["--unlock"] @? "adjust failed"+			pair r1 r2+			forM_ [r1,r2,r1] $ \r -> indir r $+				git_annex "sync" [] @? "sync failed"+			checkmerge "r1" r1+			checkmerge "r2" r2+  where+	conflictor = "conflictor"+	variantprefix = conflictor ++ ".variant"+	checkmerge what d = do+		l <- getDirectoryContents d+		let v = filter (variantprefix `isPrefixOf`) l+		length v == 2+			@? (what ++ " not exactly 2 variant files in: " ++ show l)+		conflictor `notElem` l @? ("conflictor still present after conflict resolution")+		indir d $ do+			git_annex "get" v @? "get failed"+			git_annex_expectoutput "find" v v  {- Check merge conflict resolution when one side is an annexed  - file, and the other is a directory. -}@@ -1385,7 +1421,7 @@  test_upgrade :: Assertion test_upgrade = intmpclonerepo $-	git_annex "upgrade" [] @? "upgrade from same version failed"+	git_annex "upgrade" [] @? "upgrade failed"  test_whereis :: Assertion test_whereis = intmpclonerepo $ do
Upgrade/V5.hs view
@@ -1,6 +1,6 @@ {- git-annex v5 -> v6 upgrade support  -- - Copyright 2015 Joey Hess <id@joeyh.name>+ - Copyright 2015-2016 Joey Hess <id@joeyh.name>  -  - Licensed under the GNU GPL version 3 or higher.  -}@@ -23,7 +23,9 @@ import Git.FilePath import Git.FileMode import Git.Config+import Git.Ref import Utility.InodeCache+import Annex.AdjustedBranch  upgrade :: Bool -> Annex Bool upgrade automatic = do@@ -37,19 +39,27 @@ 		setConfig (annexConfig "thin") (boolConfig True) 		Annex.changeGitConfig $ \c -> c { annexThin = True } 		{- Since upgrade from direct mode changes how files-		 - are represented in git, commit any changes in the-		 - work tree first. -}+		 - are represented in git, by checking out an adjusted+		 - branch, commit any changes in the work tree first. -} 		whenM stageDirect $ do 			unless automatic $ 				showAction "committing first" 			upgradeDirectCommit automatic 				"commit before upgrade to annex.version 6" 		setDirect False+		cur <- fromMaybe (error "Somehow no branch is checked out")+			<$> inRepo Git.Branch.current 		upgradeDirectWorkTree 		removeDirectCruft-		showLongNote "Upgraded repository out of direct mode."-		showLongNote "Changes have been staged for all annexed files in this repository; you should run `git commit` to commit these changes."-		showLongNote "Any other clones of this repository that use direct mode need to be upgraded now, too."+		{- Create adjusted branch where all files are unlocked.+		 - This should have the same content for each file as+		 - have been staged in upgradeDirectWorkTree. -}+		AdjBranch b <- adjustBranch UnlockAdjustment cur+		{- Since the work tree was already set up by+		 - upgradeDirectWorkTree, and contains unlocked file+		 - contents too, don't use git checkout to check out the+		 - adjust branch. Instead, update HEAD manually. -}+		inRepo $ setHeadRef b 	configureSmudgeFilter 	-- Inode sentinal file was only used in direct mode and when 	-- locking down files as they were added. In v6, it's used more
Utility/CopyFile.hs view
@@ -49,13 +49,9 @@ {- Create a hard link if the filesystem allows it, and fall back to copying  - the file. -} createLinkOrCopy :: FilePath -> FilePath -> IO Bool-#ifndef mingw32_HOST_OS createLinkOrCopy src dest = go `catchIO` const fallback   where 	go = do 		createLink src dest 		return True 	fallback = copyFileExternal CopyAllMetaData src dest-#else-createLinkOrCopy = copyFileExternal CopyAllMetaData-#endif
Utility/PosixFiles.hs view
@@ -1,6 +1,6 @@ {- POSIX files (and compatablity wrappers).  -- - This is like System.PosixCompat.Files, except with a fixed rename.+ - This is like System.PosixCompat.Files, but with a few fixes.  -  - Copyright 2014 Joey Hess <id@joeyh.name>  -@@ -21,6 +21,7 @@ import System.Posix.Files (rename) #else import qualified System.Win32.File as Win32+import qualified System.Win32.HardLink as Win32 #endif  {- System.PosixCompat.Files.rename on Windows calls renameFile,@@ -31,4 +32,11 @@ #ifdef mingw32_HOST_OS rename :: FilePath -> FilePath -> IO () rename src dest = Win32.moveFileEx src dest Win32.mOVEFILE_REPLACE_EXISTING+#endif++{- System.PosixCompat.Files.createLink throws an error, but windows+ - does support hard links. -}+#ifdef mingw32_HOST_OS+createLink :: FilePath -> FilePath -> IO ()+createLink = Win32.createHardLink #endif
Utility/UserInfo.hs view
@@ -17,9 +17,7 @@ import Utility.Env  import System.PosixCompat-#ifndef mingw32_HOST_OS import Control.Applicative-#endif import Prelude  {- Current user's home directory.
debian/changelog view
@@ -1,3 +1,27 @@+git-annex (6.20160412) unstable; urgency=medium++  * adjust --unlock: Enters an adjusted branch in which all annexed files+    are unlocked. The v6 equivilant of direct mode, but much cleaner!+  * Upgrading a direct mode repository to v6 has changed to enter+    an adjusted unlocked branch. This makes the direct mode to v6 upgrade+    able to be performed in one clone of a repository without affecting+    other clones, which can continue using v5 and direct mode.+  * init --version=6: Automatically enter the adjusted unlocked branch+    when filesystem doesn't support symlinks.+  * ddar remote: fix ssh calls+    Thanks, Robie Basak+  * log: Display time with time zone.+  * log --raw-date: Use to display seconds from unix epoch.+  * v6: Close pointer file handles more quickly, to avoid problems on Windows.+  * sync: Show output of git commit.+  * annex.thin and annex.hardlink are now supported on Windows.+  * unannex --fast now makes hard links on Windows.+  * Fix bug in annex.largefiles mimetype= matching when git-annex+    is run in a subdirectory of the repository.+  * Fix build with ghc v7.11. Thanks, Gabor Greif.++ -- Joey Hess <id@joeyh.name>  Tue, 12 Apr 2016 14:53:22 -0400+ git-annex (6.20160318) unstable; urgency=medium    * metadata: Added -r to remove all current values of a field.
debian/control view
@@ -31,7 +31,7 @@ 	libghc-stm-dev (>= 2.3), 	libghc-dbus-dev (>= 0.10.7) [linux-any], 	libghc-fdo-notify-dev (>= 0.3) [linux-any],-	libghc-yesod-dev (>= 1.2.6.1)       [i386 amd64 arm64 armhf kfreebsd-amd64 kfreebsd-i386 mips mips64el mipsel powerpc ppc64el s390x]+	libghc-yesod-dev (>= 1.2.6.1)       [i386 amd64 arm64 armhf kfreebsd-amd64 kfreebsd-i386 mips mips64el mipsel powerpc ppc64el s390x], 	libghc-yesod-core-dev (>= 1.2.19)   [i386 amd64 arm64 armhf kfreebsd-i386 kfreebsd-amd64 mips mips64el mipsel powerpc ppc64el s390x], 	libghc-yesod-form-dev (>= 1.3.15)   [i386 amd64 arm64 armhf kfreebsd-i386 kfreebsd-amd64 mips mips64el mipsel powerpc ppc64el s390x], 	libghc-yesod-static-dev (>= 1.2.4)  [i386 amd64 arm64 armhf kfreebsd-i386 kfreebsd-amd64 mips mips64el mipsel powerpc ppc64el s390x],@@ -42,7 +42,7 @@ 	libghc-warp-tls-dev                 [i386 amd64 arm64 armhf kfreebsd-i386 kfreebsd-amd64 mips mips64el mipsel powerpc ppc64el s390x], 	libghc-wai-dev                      [i386 amd64 arm64 armhf kfreebsd-i386 kfreebsd-amd64 mips mips64el mipsel powerpc ppc64el s390x], 	libghc-wai-extra-dev                [i386 amd64 arm64 armhf kfreebsd-i386 kfreebsd-amd64 mips mips64el mipsel powerpc ppc64el s390x],-	libghc-dav-dev (>= 1.0)+	libghc-dav-dev (>= 1.0), 	libghc-persistent-dev, 	libghc-persistent-template-dev, 	libghc-persistent-sqlite-dev,
+ doc/bugs/Android__58___Cannot_create_repo_on_external_sd_card.mdwn view
@@ -0,0 +1,62 @@+I am using the latest daily build for Android 5.0++My version is Android 5.0.1 Lollipop. And I'm using a Samsung Galaxy S4 unrooted.++Trying to create a repositpory in the folder /storage/extSdCard/Music gives me a webpage with a red error badge that says:++    "Internal Server Error"+    +    git init failed++    Output:+    /storage/extSdCard/Music/.git: Permission denied++I'm pretty sure this is because of Android's crappy permission system on sd cards. But when I install the app, it tells me it is asking for+read write access to the sd card. So this consideration must have happened.++++### Please describe the problem.++I am using the latest daily build for Android 5.0++My version is Android 5.0.1 Lollipop. And I'm using a Samsung Galaxy S4 unrooted.++Trying to create a repositpory in the folder /storage/extSdCard/Music gives me a webpage with a red error badge that says:++    "Internal Server Error"+    +    git init failed++    Output:+    /storage/extSdCard/Music/.git: Permission denied++I'm pretty sure this is because of Android's crappy permission system on sd cards. But when I install the app, it tells me it is asking for+read write access to the sd card. So this consideration must have happened.++### What steps will reproduce the problem?++1. Install the Android 5.0 daily build on an Android 5.0.1 phone.+2. Try to create a repo on an external sd card.++### What version of git-annex are you using? On what operating system?++Latest daily build of Android 5.0 git annex on Android 5.0.1++### Please provide any additional information below.++When I run adb shell I see the following permissions on the file in question:++    drwxrwx--- root     sdcard_r          2016-04-02 14:11 Music++Additional info. The terminal emulator shows this output:++    Falling back to hardcoded app location: cannot find expected files in /data/app/ga.androidterm-2/lib+    git annex webapp+    WARNING: linker: git-annex has text relocations. This is wasting memory and prevents security hardening. Please fix.++I have tried moving the app to the sd card, but it will not work if I do that.++### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)++Yes! It's by far one of my favorite apps! it works very well on my laptop, on my home file server, and on my internal storage on my Android phone :)
+ doc/bugs/Android_chroot_stuck_in_Cabal_hell.mdwn view
@@ -0,0 +1,20 @@+### Please describe the problem.+I'm trying to get an Android development environment set up, but I am running into conflicting library versions inside of the chroot. The package installation script now finishes, but I run into a link-time error during `cabal configure` because it is pulling in two different versions of the unix package for some reason. Please let me know if there is any information I can get from my build environment that would help diagnosing the issue.++### What steps will reproduce the problem?+Run `buildchroot`, `install-haskell-packages`, `make android`++### What version of git-annex are you using? On what operating system?+Attempting to build from source, cross-compiling for Android on Debian Jessie.++### Please provide any additional information below.++[[!format sh """+Linking ./dist/setup/setup ...+/usr/lib/ghc/unix-2.6.0.1/libHSunix-2.6.0.1.a(execvpe.o): In function `pPrPr_disableITimers':+(.text+0x300): multiple definition of `pPrPr_disableITimers'+/home/builder/.cabal/lib/i386-linux-ghc-7.6.3/unix-2.7.1.0/libHSunix-2.7.1.0.a(ghcrts.o):ghcrts.c:(.text+0x0): first defined here+collect2: error: ld returned 1 exit status+Makefile:225: recipe for target 'android' failed+make: *** [android] Error 1+"""]]
+ doc/bugs/Cannot_add_gcrypt_remote_in_webapp__58___gcrypt_backend.mdwn view
@@ -0,0 +1,15 @@+### Please describe the problem.++I have a repository that is encrypted using GPG. It is supposed to sync a folder between two laptops. (Note: this is a DIFFERENT repository than the one in my other bug report https://git-annex.branchable.com/bugs/Packfile_does_not_match_digest__58___gcrypt_with_assistant/ but the setup is the same)++I set everything up on laptop1. This time, I decided to wait for the syncing to finish, between laptop1 and laptop2 in order to prevent corruption. After laptop1 had finished syncing, I went to laptop2 and setup the repository.++- I created a local repository on laptop2.+- I told the webapp to combine repositories.++Then I got++"+Internal Server Error+Cannot find configuration for the gcrypt remote at ssh://denisa@vps.ip/backup/annex/denisa/Studium+"
+ doc/bugs/OSX_case_insensitive_filesystem.mdwn view
@@ -0,0 +1,56 @@+### Please describe the problem.++I copied one entire folder from my OSX local machine to a linux server.+That folder was version controlled by git with git annex big files.+On the linux machine the symlinks were broken.++In particular, on my local machine, a file like:+```+file.vcf.gz.tbi -> ../../.git/annex/objects/J4/Pg/SHA256E-s572463--85b357849ddad75fc1138b27d6af62cf410876e329ff035f21a631bd53146224.gz.tbi/SHA256E-s572463--85b357849ddad75fc1138b27d6af62cf410876e329ff035f21a631bd53146224.gz.tbi+```++but the file resides in:++```+../../.git/annex/objects/j4/Pg/SHA256E-s572463--85b357849ddad75fc1138b27d6af62cf410876e329ff035f21a631bd53146224.gz.tbi/SHA256E-s572463--85b357849ddad75fc1138b27d6af62cf410876e329ff035f21a631bd53146224.gz.tbi+```++Notice the difference between `J4` and `j4`. This is not a problem on my OSX but becomes one on a linux machine.++### What steps will reproduce the problem?++on local machine:+```rsync -aztv folder/ remote-machine:folder/```++on server:+```find . -type l -exec sh -c "file -b {} | grep -q ^broken" \; -print```+listed every symlink as broken.++### What version of git-annex are you using? On what operating system?++git annex version 6.20160318++my special remote is rsync.net++OSX 10.11.4++Not sure of which option were used when creating ther file system, but I suspect a HFS+ case insensitive.++### Please provide any additional information below.++I wanted to do this full copy because the transfer speed from the special remote was too slow.+Since then I got decent speeds, and if I do `git annex get .` on the server, all is fine.+So, my "problem" is solved but I'm still wondering why the discrepant folder capitalization.++[[!format sh """+# If you can, paste a complete transcript of the problem occurring here.+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log+++# End of transcript or log.+"""]]++### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)++Sure, it works marvels :-) Also what I was trying to do is perhaps not by the book...+
+ doc/bugs/Packfile_does_not_match_digest__58___gcrypt_with_assistant.mdwn view
@@ -0,0 +1,24 @@+### Please describe the problem.+I tried to sync a folder between two laptops, using the webapp and GPG encryption. I started by seting up the repository on laptop1, and then, while all the files were uploading, I went over to laptop2 and set things up there as well.++At first, everything looked fine, laptop1 was uploading and laptop2 was downloading. Then, laptop2 reported "Failed to sync with VPS, and the log file showed a gcrypt error: "Packfile long-hash does not match digest!"++### What version of git-annex are you using? On what operating system?++++Laptop1 is running wheezy with git annex version 6.20160307+gitgb095561-1~ndall+1 from neurodebian.++VPS is running wheezy++Laptop2 is runing jessie with git annex version 6.20160307+gitgb095561-1~ndall+1 from neurodebian.++### Please provide any additional information below.++http://denisa.hobbs.cz/laptop1.daemon.log+http://denisa.hobbs.cz/laptop2.daemon.log++### Have you had any luck using git-annex before?++If I could get this syncing to work, then that would be great! I don't want to use unison, because that wouldn't be encrypted... So this would be wonderful.+
− doc/bugs/Selfsigned_certificates_with_jabber_fail_miserably..mdwn
@@ -1,26 +0,0 @@-### Please describe the problem.-Entering a jabber address which's server got a selfsigned certificate, the process just fails, without asking for acceptance for that certificate. This is quite a showstopper.-(for example: jabber.ccc.de)---### What steps will reproduce the problem?-Try with an account from e.g. jabber.ccc.de---### What version of git-annex are you using? On what operating system?-Arch Linux, aur/git-annex-standalone 4.20130709-1 --### Please provide any additional information below.-There is no logoutput to add... I'm sorry.--[[!format sh """-# If you can, paste a complete transcript of the problem occurring here.-# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log---# End of transcript or log.-"""]]--[[!meta title="XMPP does not work with jabber.ccc.de"]]--[[!tag moreinfo]]
+ doc/bugs/Selfsigned_certificates_with_jabber_fail_miserably.mdwn view
@@ -0,0 +1,26 @@+### Please describe the problem.+Entering a jabber address which's server got a selfsigned certificate, the process just fails, without asking for acceptance for that certificate. This is quite a showstopper.+(for example: jabber.ccc.de)+++### What steps will reproduce the problem?+Try with an account from e.g. jabber.ccc.de+++### What version of git-annex are you using? On what operating system?+Arch Linux, aur/git-annex-standalone 4.20130709-1 ++### Please provide any additional information below.+There is no logoutput to add... I'm sorry.++[[!format sh """+# If you can, paste a complete transcript of the problem occurring here.+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log+++# End of transcript or log.+"""]]++[[!meta title="XMPP does not work with jabber.ccc.de"]]++[[!tag moreinfo]]
+ doc/bugs/Windows__58___git_annex_get_failed.mdwn view
@@ -0,0 +1,90 @@+### Please describe the problem.+I'm using git-annex v6 in windows and seems `git annex get` fails.+Deleting the pointer files and doing a hard reset seems to fix the problem.+Another bug report named "v6 repo can not restore files with executable permission" seems to point to the same problem but a little different.++[[!retitle "git annex get fails sometimes in v6 repository on Windows"]]++### What steps will reproduce the problem?+I have a repo in D:\annex with a file `test`+Now I create another repo:++	$ cd H:\annex++	$ git init+	Initialized empty Git repository in H:/annex/.git/++	$ git annex init "portable drive"+	init portable drive+	  Detected a filesystem without fifo support.++	  Disabling ssh connection caching.++	  Detected a crippled filesystem.++	  Enabling direct mode.+	ok+	(recording state in git...)++	$ git annex upgrade+	upgrade . (v5 to v6...)+	  Upgraded repository out of direct mode.++	  Changes have been staged for all annexed files in this repository; you should run `git commit` to commit these changes.++	  Any other clones of this repository that use direct mode need to be upgraded now, too.+	ok++	$ git remote add laptop D:/annex++	$ git annex sync+	commit  ok+	pull laptop+	warning: no common commits+	remote: Counting objects: 21, done.+	remote: Compressing objects: 100% (15/15), done.+	remote: Total 21 (delta 3), reused 0 (delta 0)+	Unpacking objects: 100% (21/21), done.+	From D:/annex+	 * [new branch]      git-annex  -> laptop/git-annex+	 * [new branch]      master     -> laptop/master+	 * [new branch]      synced/git-annex -> laptop/synced/git-annex+	 * [new branch]      synced/master -> laptop/synced/master+++	Already up-to-date.+	ok+	(merging laptop/git-annex laptop/synced/git-annex into git-annex...)+	(recording state in git...)+	push laptop+	Counting objects: 8, done.+	Delta compression using up to 8 threads.+	Compressing objects: 100% (6/6), done.+	Writing objects: 100% (8/8), 928 bytes | 0 bytes/s, done.+	Total 8 (delta 0), reused 0 (delta 0)+	To D:/annex+	   c1aee82..980dc01  git-annex -> synced/git-annex+	ok++	$ git annex get .+	get test (from laptop...)+	SHA256E-s14488367--4391729b982439764813156e1bfc12e9626ae89452ab812f5180c376fbd57fc0+		 14,488,367 100%   63.24MB/s    0:00:00 (xfr#1, to-chk=0/1)+	(checksum...)+	git-annex: DeleteFile ".\\test": permission denied (The process cannot access the file because it is being used by another process.)+	failed+	git-annex: get: 1 failed++It seems to try to delete the pointer file, but finds the file in use. Maybe fsck is using it?++	$ cat test+	/annex/objects/SHA256E-s14488367--4391729b982439764813156e1bfc12e9626ae89452ab812f5180c376fbd57fc0++	$ git annex lock+	lock test git-annex: content not present; cannot lock++And `git annex unlock` will do nothing.++If you can't reproduce the problem, I'll run the tests for you.+### What version of git-annex are you using? On what operating system?+Latest compile from source, Windows 8.1
− doc/bugs/box.com_never_stops_syncing..mdwn
@@ -1,74 +0,0 @@-### Please describe the problem.-Git-annex will constantly sync most(if not all) my files to box.com--### What steps will reproduce the problem?-1 - Use git-annex instead of Dropbox at work-2 - Boot computer.-3 - Watch it sync everything to box.com (even files i believe it has transferred each and every day for the last few months)--### What version of git-annex are you using? On what operating system?-git-annex version: 4.20130827--But i have never seen it work satisfactory in any version.--Also, i have seen this is 10+ different clean git-annexes. So it isn't annex specific. --### Please provide any additional information below.--I am going to add more debug to this bug constantly. (I intend to do a full 'git annex copy --to box.com --not --in box.com' daily, and see if the same files are transfered again and again)---For now, i see a few different issues already:---[[!format sh """-# If you can, paste a complete transcript of the problem occurring here.-# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log---tou@DSK1049:~/work-annex$ git annex copy --to box.com --not --in box.com 2>&1 | tee ../work-annex-copy-to-box.com-not-in-box.com-run1.log-[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","show-ref","git-annex"]-[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","show-ref","--hash","refs/heads/git-annex"]-[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..dbe8b1cfa5f84126c45a39fdc7c7f26e272c71cc","--oneline","-n1"]-[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..45e279375897a2cd7f5b893402e0ec25c1b23436","--oneline","-n1"]-[2013-09-11 09:24:54 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..c4921be4434f751493fce1c932ac759214abacd4","--oneline","-n1"]-[2013-09-11 09:24:54 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..d591398dc1cac824a5fc5bdacdcb82301a9b15a3","--oneline","-n1"]-[2013-09-11 09:24:54 CEST] chat: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","cat-file","--batch"]-[2013-09-11 09:24:54 CEST] read: git ["config","--null","--list"]-[2013-09-11 09:24:54 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","ls-files","--cached","-z","--"]-[2013-09-11 09:24:54 CEST] chat: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","cat-file","--batch"]-copy Documents/Gamle catillo overførsler/Rapport b-bm.odt (gpg) (checking box.com...) ok-copy Documents/Gamle catillo overførsler/Rapport brandt skorstensfejeren.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/4a5/18e/GPGHMACSHA1--5f8660edac93899cf9adc5fadcc480ddc2992bb1/GPGHMACSHA1--5f8660edac93899cf9adc5fadcc480ddc2992bb1.chunkcount) failed-copy Documents/Gamle catillo overførsler/Rapport teamkoege.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/98d/ae7/GPGHMACSHA1--5253241407527aa6c980f1174fdbc32713c54c44/GPGHMACSHA1--5253241407527aa6c980f1174fdbc32713c54c44.chunkcount) failed-copy Documents/Gamle catillo overførsler/Rapport vikarborsen.odt (checking box.com...) ok-copy Documents/Gamle catillo overførsler/Rapport-terrariemesteren.odt (checking box.com...) ok-copy Documents/Gamle catillo overførsler/catillo-efhandel.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/9d9/aea/GPGHMACSHA1--1516eac1ec7b4ceaa840faebabde1f50f5db0a52/GPGHMACSHA1--1516eac1ec7b4ceaa840faebabde1f50f5db0a52.chunkcount) failed-copy Documents/Nøgeordsanalyse catillo104.xlsx (checking box.com...) (ResponseTimeout) failed-copy Documents/Søgeordsliste.txt (checking box.com...) ok-copy Documents/catillo guide.odt (checking box.com...) ok-copy Documents/guide bruger oprettelse.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/49e/175/GPGHMACSHA1--2b47737f8de7faac7704eaa322785edad63a921c/GPGHMACSHA1--2b47737f8de7faac7704eaa322785edad63a921c.chunkcount) failed-copy Documents/guide skift backup bånd.odt (checking box.com...) ok-copy Documents/lilletest.csv (checking box.com...) (failed to read https://www.box.com/dav/work-annex/915/373/GPGHMACSHA1--49ba3d5f63c012ae2cd2c0fc3e729178b1023c33/GPGHMACSHA1--49ba3d5f63c012ae2cd2c0fc3e729178b1023c33.chunkcount) failed-copy Dropbox/adams-scraper/CommonFunctions.py (checking box.com...) (ResponseTimeout) failed-copy Dropbox/adams-scraper/__pycache__/CommonFunctions.cpython-33.pyc (checking box.com...) (to box.com...) [2013-09-11 09:28:30 CEST] chat: gpg ["--batch","--no-tty","--use-agent","--quiet","--trust-model","always","--batch","--passphrase-fd","14","--symmetric","--force-mdc"]--100%          0.0 B/s 0sResponseTimeout-ResponseTimeout-failed                  ---# End of transcript or log.-"""]]--More to come(full log)--> This is [[fixed|done]] in git; when built with a new enough-> version of the haskell DAV library, git-annex disables the default 5-> second timeout.-> -> It'll still be present in the Debian stable backports, which are-> built with an old version of DAV. Not much I can do about that;-> backporting DAV would be difficult.-> -> The daily builds are updated to use the new version.-> --[[Joey]]
+ doc/bugs/box.com_never_stops_syncing.mdwn view
@@ -0,0 +1,74 @@+### Please describe the problem.+Git-annex will constantly sync most(if not all) my files to box.com++### What steps will reproduce the problem?+1 - Use git-annex instead of Dropbox at work+2 - Boot computer.+3 - Watch it sync everything to box.com (even files i believe it has transferred each and every day for the last few months)++### What version of git-annex are you using? On what operating system?+git-annex version: 4.20130827++But i have never seen it work satisfactory in any version.++Also, i have seen this is 10+ different clean git-annexes. So it isn't annex specific. ++### Please provide any additional information below.++I am going to add more debug to this bug constantly. (I intend to do a full 'git annex copy --to box.com --not --in box.com' daily, and see if the same files are transfered again and again)+++For now, i see a few different issues already:+++[[!format sh """+# If you can, paste a complete transcript of the problem occurring here.+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log+++tou@DSK1049:~/work-annex$ git annex copy --to box.com --not --in box.com 2>&1 | tee ../work-annex-copy-to-box.com-not-in-box.com-run1.log+[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","show-ref","git-annex"]+[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","show-ref","--hash","refs/heads/git-annex"]+[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..dbe8b1cfa5f84126c45a39fdc7c7f26e272c71cc","--oneline","-n1"]+[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..45e279375897a2cd7f5b893402e0ec25c1b23436","--oneline","-n1"]+[2013-09-11 09:24:54 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..c4921be4434f751493fce1c932ac759214abacd4","--oneline","-n1"]+[2013-09-11 09:24:54 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..d591398dc1cac824a5fc5bdacdcb82301a9b15a3","--oneline","-n1"]+[2013-09-11 09:24:54 CEST] chat: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","cat-file","--batch"]+[2013-09-11 09:24:54 CEST] read: git ["config","--null","--list"]+[2013-09-11 09:24:54 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","ls-files","--cached","-z","--"]+[2013-09-11 09:24:54 CEST] chat: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","cat-file","--batch"]+copy Documents/Gamle catillo overførsler/Rapport b-bm.odt (gpg) (checking box.com...) ok+copy Documents/Gamle catillo overførsler/Rapport brandt skorstensfejeren.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/4a5/18e/GPGHMACSHA1--5f8660edac93899cf9adc5fadcc480ddc2992bb1/GPGHMACSHA1--5f8660edac93899cf9adc5fadcc480ddc2992bb1.chunkcount) failed+copy Documents/Gamle catillo overførsler/Rapport teamkoege.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/98d/ae7/GPGHMACSHA1--5253241407527aa6c980f1174fdbc32713c54c44/GPGHMACSHA1--5253241407527aa6c980f1174fdbc32713c54c44.chunkcount) failed+copy Documents/Gamle catillo overførsler/Rapport vikarborsen.odt (checking box.com...) ok+copy Documents/Gamle catillo overførsler/Rapport-terrariemesteren.odt (checking box.com...) ok+copy Documents/Gamle catillo overførsler/catillo-efhandel.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/9d9/aea/GPGHMACSHA1--1516eac1ec7b4ceaa840faebabde1f50f5db0a52/GPGHMACSHA1--1516eac1ec7b4ceaa840faebabde1f50f5db0a52.chunkcount) failed+copy Documents/Nøgeordsanalyse catillo104.xlsx (checking box.com...) (ResponseTimeout) failed+copy Documents/Søgeordsliste.txt (checking box.com...) ok+copy Documents/catillo guide.odt (checking box.com...) ok+copy Documents/guide bruger oprettelse.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/49e/175/GPGHMACSHA1--2b47737f8de7faac7704eaa322785edad63a921c/GPGHMACSHA1--2b47737f8de7faac7704eaa322785edad63a921c.chunkcount) failed+copy Documents/guide skift backup bånd.odt (checking box.com...) ok+copy Documents/lilletest.csv (checking box.com...) (failed to read https://www.box.com/dav/work-annex/915/373/GPGHMACSHA1--49ba3d5f63c012ae2cd2c0fc3e729178b1023c33/GPGHMACSHA1--49ba3d5f63c012ae2cd2c0fc3e729178b1023c33.chunkcount) failed+copy Dropbox/adams-scraper/CommonFunctions.py (checking box.com...) (ResponseTimeout) failed+copy Dropbox/adams-scraper/__pycache__/CommonFunctions.cpython-33.pyc (checking box.com...) (to box.com...) [2013-09-11 09:28:30 CEST] chat: gpg ["--batch","--no-tty","--use-agent","--quiet","--trust-model","always","--batch","--passphrase-fd","14","--symmetric","--force-mdc"]++100%          0.0 B/s 0sResponseTimeout+ResponseTimeout+failed                  +++# End of transcript or log.+"""]]++More to come(full log)++> This is [[fixed|done]] in git; when built with a new enough+> version of the haskell DAV library, git-annex disables the default 5+> second timeout.+> +> It'll still be present in the Debian stable backports, which are+> built with an old version of DAV. Not much I can do about that;+> backporting DAV would be difficult.+> +> The daily builds are updated to use the new version.+> --[[Joey]]
doc/bugs/direct_cripple_mode_crippled_my_other_non-crippled_repos.mdwn view
@@ -29,12 +29,12 @@ * [convmv](http://tracker.debian.org/convmv) can massively re-encode filenames and may also be able to fix all the issues above, but i didn't test that * [rename](http://tracker.debian.org/rename) can massively rename files according to certain patterns, I have used: -    rename 's/\?//' *-    rename 's/://' *-    rename 's/\\//' *-    rename 's/"//' *-    rename 's/*//' *-    git add -A .+      rename 's/\?//' *+      rename 's/://' *+      rename 's/\\//' *+      rename 's/"//' *+      rename 's/*//' *+      git add -A .  Similar issues: 
+ doc/bugs/easy_feature_request__58___enable_lan_sync_on_android.mdwn view
@@ -0,0 +1,1 @@+It would be nice to allow LAN sync on the android client.  This would allow for easily syncing files when in an out-of-service area, or rapidly syncing to a device with a better network connection.
+ doc/bugs/git-annex_smudge_fails_on_git_add.mdwn view
@@ -0,0 +1,57 @@+### Please describe the problem.++I want to be able to use "normal" git commands so I'm trying a v6 repo. +I have attempted to set up `.gitattributes` to only annex non-text mime types.  When I attempt to add something that would go into the annex, the `git-annex smudge` command fails.++++### What steps will reproduce the problem?++See transcript below+++### What version of git-annex are you using? On what operating system?++debian jessie; built from github using stack;installed to ~/.local/bin++[[!format sh """+git-annex version: 6.20160308-ge51f555+build flags: Assistant Webapp Pairing Testsuite S3(multipartupload)(storageclasses) WebDAV Inotify DBus DesktopNotif+y XMPP ConcurrentOutput TorrentParser MagicMime Feeds Quvi                                                         +key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_51+2 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 SHA1E SHA1 MD5E MD5 WORM URL         +remote types: git gcrypt S3 bup directory rsync web bittorrent webdav tahoe glacier ddar hook external+local repository version: 6+supported repository versions: 5 6+upgrade supported from repository versions: 0 1 2 4 5+"""]]++### Please provide any additional information below.++.gitattributes is:+[[!format sh """+* annex.largefiles=(not(mimetype=text/*))+"""]]++[[!format sh """+# If you can, paste a complete transcript of the problem occurring here.+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log++renn:/tmp/gat$ git init && git annex init --version=6                                                      +Initialized empty Git repository in /tmp/gat/.git/+init  ok+(recording state in git...)+renn:/tmp/gat$ cp ../tga/.gitattributes .+renn:/tmp/gat$ git add .gitattributes +renn:/tmp/gat$ cp ../tga/pkdconvweb.mov .+renn:/tmp/gat$ git add pkdconvweb.mov +error: cannot feed the input to external filter git-annex smudge --clean %f+error: external filter git-annex smudge --clean %f failed+++# End of transcript or log.+"""]]++### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)++No, I'm a first-time user.  Thanks for this neat piece of software.
doc/bugs/git_security_fix.mdwn view
@@ -6,13 +6,15 @@ status of autobuilds:  * Linux is fixed (all builds)-* OSX pending (host is moving)-* Windows waiting on updated release of git for Windows+* OSX is fixed+* Windows does not bundle git * Android is fixed (git build is untested)  status of released builds:  * Linux is fixed (all builds)-* OSX is vulnerable-* Windows is vulnerable+* OSX is fixed (yosemite only; old builds vulnerable so removed)+* Windows does not bundle git * Android is fixed (git build is untested)++[[done]] --[[Joey]]
+ doc/bugs/gitlab_configuration_out_of_date.mdwn view
@@ -0,0 +1,17 @@+### Please describe the problem.+The webapp configuration for enabling a new gitlab remote is out of date and no longer functions.++### What steps will reproduce the problem?+Attempt to use the webapp to create a new gitlab remote.+- The url linked to add a public key is invalid+- Pressing the confirmation button reloads the same page.  The remote is never enabled.++### What version of git-annex are you using? On what operating system?+6.20160229-g37a89cc on linux x86 fedora 18++### Please provide any additional information below.++### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)++Git-annex is a miracle to find.  I intend to stick with it, migrate my life to it, and perhaps learn haskell some day to contribute.+
+ doc/bugs/largefiles_not_working_when_set_in_.gitattributes.mdwn view
@@ -0,0 +1,77 @@+### Please describe the problem.+annex.largefiles saved in .gitattributes does not work when running 'git annex add' from a subdirectory++I set annex.largefiles to include any files larger than 50k or any files that are executable. This works if I'm adding a files from top level directory. But if I'm adding files from a sub-directory it does not work.++### What steps will reproduce the problem?+see log below++### What version of git-annex are you using? On what operating system?+ubuntu 15.10++git-annex version: 6.20160318-gd594fc0+build flags: Assistant Webapp Pairing Testsuite S3(multipartupload)(storageclasses) WebDAV Inotify DBus DesktopNotify XMPP ConcurrentOutput TorrentParser MagicMime Feeds Quvi+key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 SHA1E SHA1 MD5E MD5 WORM URL+remote types: git gcrypt S3 bup directory rsync web bittorrent webdav tahoe glacier ddar hook external+++### Please provide any additional information below.++[[!format sh """+# If you can, paste a complete transcript of the problem occurring here.+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log++vagrant@u240:/tmp/annex/$ git init+Initialized empty Git repository in /tmp/annex/.git/+vagrant@u240:/tmp/annex/$ git annex init+init  ok+(recording state in git...)+vagrant@u240:/tmp/annex/$ mkdir sub-dir+vagrant@u240:/tmp/annex/$ cp /bin/tempfile .+‘/bin/tempfile’ -> ‘./tempfile’+vagrant@u240:/tmp/annex/$ cp /bin/tempfile sub-dir/+‘/bin/tempfile’ -> ‘sub-dir/tempfile’+vagrant@u240:/tmp/annex/$ file --mime-type tempfile +tempfile: application/x-executable+vagrant@u240:/tmp/annex/$ cat .gitattributes +* annex.largefiles=((largerthan=50kb)or(mimetype=application/x-executable))+vagrant@u240:/tmp/annex/$ ls -l tempfile+-rwxr-xr-x 1 vagrant vagrant 10352 Apr  6 15:19 tempfile+# the file is 10k in size and I can annex it from top level directory+vagrant@u240:/tmp/annex/$ git annex add tempfile sub-dir/tempfile+add tempfile ok+add sub-dir/tempfile ok+(recording state in git...)+vagrant@u240:/tmp/annex/$ cp /bin/tempfile tempfile2+‘/bin/tempfile’ -> ‘tempfile2’+vagrant@u240:/tmp/annex/$ cp /bin/tempfile sub-dir/tempfile2+‘/bin/tempfile’ -> ‘sub-dir/tempfile2’+vagrant@u240:/tmp/annex/$ cd sub-dir/+# same file but I can not annex it if running from a sub-directory+vagrant@u240:/tmp/annex/sub-dir/$ git annex add ../tempfile2 tempfile2+add ../tempfile2 ok+add tempfile2 (non-large file; adding content to git repository) ok+(recording state in git...)+vagrant@u240:/tmp/annex/sub-dir/$ cd ..+vagrant@u240:/tmp/annex/$ ls -lR+.:+total 12+drwxrwxr-x 2 vagrant vagrant 4096 Apr  6 15:21 sub-dir/+lrwxrwxrwx 1 vagrant vagrant  186 Apr  6 15:19 tempfile -> .git/annex/objects/xj/kJ/SHA256E-s10352--93a1f74ec1714ef2107989076140b4eaae220f7b2cde834c16a7ad654d12b0f5/SHA256E-s10352--93a1f74ec1714ef2107989076140b4eaae220f7b2cde834c16a7ad654d12b0f5+lrwxrwxrwx 1 vagrant vagrant  186 Apr  6 15:20 tempfile2 -> .git/annex/objects/xj/kJ/SHA256E-s10352--93a1f74ec1714ef2107989076140b4eaae220f7b2cde834c16a7ad654d12b0f5/SHA256E-s10352--93a1f74ec1714ef2107989076140b4eaae220f7b2cde834c16a7ad654d12b0f5++./sub-dir:+total 16+lrwxrwxrwx 1 vagrant vagrant   189 Apr  6 15:20 tempfile -> ../.git/annex/objects/xj/kJ/SHA256E-s10352--93a1f74ec1714ef2107989076140b4eaae220f7b2cde834c16a7ad654d12b0f5/SHA256E-s10352--93a1f74ec1714ef2107989076140b4eaae220f7b2cde834c16a7ad654d12b0f5+-rwxr-xr-x 1 vagrant vagrant 10352 Apr  6 15:21 tempfile2+++# End of transcript or log.+"""]]++### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)+++> Thanks for reporting. This was a dumb bug; it used the wrong path to the+> file for mimetype=, which was relative to the top of the repository.+> [[fixed|done]] --[[Joey]]
+ doc/bugs/remotes_disappeared.mdwn view
@@ -0,0 +1,300 @@+### Please describe the problem.++Some remotes disappeared from `git annex info` after synchronising with a new repo.++### What steps will reproduce the problem?++1. have a nice repository full of remotes and special remotes+2. create a new repository with `git init; git annex init; git reinit <some UUID from a previously lost repository>`+3. sync the two repositories++Expected the result: restore the lost repository the its previous state.++Actual result: previous state available, but lost track of other repositories.++I suspect there may be a relation to an old "forget history" transition at play here, as the last commit on the git-annex branch is:++```+commit 266099a48af81eab71d27741b43776372aa519c4+Merge: 13ed0a6 05681b9+Author: Antoine Beaupré <anarcat@debian.org>+Date:   Wed Mar 30 12:49:55 2016 -0400++    continuing transition ["forget git history","forget dead remotes","forget git history","forget dead remotes","forget git history","forget git history","forget dead remotes","forget git history","forget dead remotes","forget git history","forget dead remotes","forget git history","forget dead remotes"]+```++So in short, some remotes that i never marked as dead seem to be caught in the whirlpool of `forget` transitions.++### What version of git-annex are you using? On what operating system?++ 5.20151208-1~bpo8+1 on debian jessie.++### Please provide any additional information below.++So here's what i could salvage from my terminal history. Note that window resizing may have truncated some lines. Apologies for the mess...++    [1077]anarcat@angela:cb39412b-d221-4846-a9dd-cdbabd9958f1$ sudo mkdir Music+    [1078]anarcat@angela:cb39412b-d221-4846-a9dd-cdbabd9958f1$ sudo chown anarcat Music+    [1079]anarcat@angela:cb39412b-d221-4846-a9dd-cdbabd9958f1$ cd Music/+    [1082]anarcat@angela:Music$ git init+    Dépôt Git vide initialisé dans /media/anarcat/cb39412b-d221-4846-a9dd-cdbabd9958f1/Music/.gi+    [1083]anarcat@angela:Music$ git annex init+    init  ok+    (recording state in git...)+    [1084]anarcat@angela:Music130$ git annex reinit 6f812272-18c8-4346-b68a-f57ae50f657e+    reinit 6f812272-18c8-4346-b68a-f57ae50f657e ok+    [1086]anarcat@angela:Music$ git remote add origin ~/mp3+    [1087]anarcat@angela:Music$ git remote update # 12:44+    Récupération de origin+    warning: no common commits+    remote: Décompte des objets: 819312, fait.+    remote: Compression des objets: 100% (368189/368189), fait.+    Réception d'objets: 100% (819312/819312), 64.97 MiB | 5.19 MiB/s, fait.+    remote: Total 819312 (delta 653024), reused 588679 (delta 449859)+    Depuis /home/anarcat/mp3+     * [nouvelle branche] git-annex  -> origin/git-annex+     * [nouvelle branche] master     -> origin/master+     * [nouvelle branche] synced/git-annex -> origin/synced/git-annex+     * [nouvelle branche] synced/master -> origin/synced/master+     * [nouvelle étiquette] bak        -> bak+    [1089]anarcat@angela:Music$ git annex merge+    merge git-annex (merging origin/git-annex origin/synced/git-annex into git-annex...)+    (recording state in git...)+    [1092]anarcat@angela:Music$ git co master+    Extraction des fichiers: 100% (22187/22187), fait.+    La branche master est paramétrée pour suivre la branche distante master depuis origin.+    Déjà sur 'master'+    [1099]anarcat@angela:Music130$ date; time git annex get --quiet --in here; date+    mercredi 30 mars 2016, 12:53:29 (UTC-0400)+    sha256sum: .git/annex/tmp/SHA256E-s4476433--bb954dfe81f3d0906a18e53d02040d1d8f8e78917552e0033b056bbf885710d9.mp3: Aucun fichier ou dossier de ce type+      sha256sum failed+    git-annex: .git/annex/tmp/SHA256E-s4476433--bb954dfe81f3d0906a18e53d02040d1d8f8e78917552e0033b056bbf885710d9.mp3: openBinaryFile: does not exist (No such file or directory)+    git-annex: get: 1 failed+    Command exited with non-zero status 1+    156.09user 39.26system 36:44.62elapsed 8%CPU (0avgtext+0avgdata 44900maxresident)k+    8775224inputs+5811728outputs (51major+281689minor)pagefaults 0swaps+    mercredi 30 mars 2016, 13:30:36 (UTC-0400)++... in the last step, the external device disappeared and the transfer failed.++After reconnecting the device, I tried to synchronise its content with the content of another device, but that device is gone!++[[!format sh """+[1013]anarcat@angela:Music1$ git annex info --fast # first notice how the remotes are not the same on the two repositories+repository mode: indirect+trusted repositories: 0+semitrusted repositories: 5+        00000000-0000-0000-0000-000000000001 -- web+        00000000-0000-0000-0000-000000000002 -- bittorrent+        0f9185ea-8462-4230-8cae-462a1ad0df36 -- origin+        45124790-dbb7-4e2e-bc0a-acfb618a01e0 -- anarcat@angela:/media/anarcat/cb39412b-d221-4846-a9dd-cdbabd9958f1/Music+        6f812272-18c8-4346-b68a-f57ae50f657e -- here+untrusted repositories: 0+transfers in progress: none+available local disk space: 4.68 gigabytes (+1 megabyte reserved)+[1014]anarcat@angela:Music$ cd ~/mp3+[1015]anarcat@angela:mp3$ git annex info --fast # here there is a lot more remotes!+repository mode: indirect+trusted repositories: 4+        22921df6-ff75-491c-b5d9-5a2aab33a689 -- anarcat@marcos:/media/anarcat/79884590-6445-4a6f-ae12-050b9a7c1912/mp3+        b7802161-c984-4c9f-8d05-787a29c41cfe -- anarcat@marcos:/srv/mp3 [marcos]+        c2ca4a13-9a5f-461b-a44b-53255ed3e2f9 -- anarcat@desktop008:/srv/musique/anarcat/mp3 [markov]+        f8818d12-9882-4ca5-bc0f-04e987888a8d -- anarcat@marcos:/media/anarcat/green_crypt/mp3/+semitrusted repositories: 8+        00000000-0000-0000-0000-000000000001 -- web+        00000000-0000-0000-0000-000000000002 -- bittorrent+        0f9185ea-8462-4230-8cae-462a1ad0df36 -- anarcat@angela:~/mp3 [here]+        3f6d8082-6f4b-4faa-a3d9-bd5db1891077 -- anarcat@lab-sc.no-ip.org:mp3+        4249a4ea-343a-43a8-9bba-457d2ff87c7d -- rachel@topcrapn:~/Musique/MUSIC/anarcat+        487dda55-d164-4bf1-9d85-66caaa9c0743 -- 300GB hard drive labeled VHS [VHS]+        6f812272-18c8-4346-b68a-f57ae50f657e -- htcones+        f867da6f-78cb-49be-a0db-d1c8e5f53664 -- n900+untrusted repositories: 0+transfers in progress: none+available local disk space: 13.51 gigabytes (+1 megabyte reserved)+[1016]anarcat@angela:mp3$ cd -+/media/anarcat/cb39412b-d221-4846-a9dd-cdbabd9958f1/Music+[1017]anarcat@angela:Music$ git annex find --in f867da6f-78cb-49be-a0db-d1c8e5f53664 --not --in here # trying to sync with the n900 remote+git-annex: there is no available git remote named "f867da6f-78cb-49be-a0db-d1c8e5f53664"+[1018]anarcat@angela:Music1$ git annex sync # maybe some data is missing?+commit  ok+pull origin+ok+push origin+Décompte des objets: 6368, fait.+Delta compression using up to 2 threads.+Compression des objets: 100% (6361/6361), fait.+Écriture des objets: 100% (6368/6368), 693.21 KiB | 565.00 KiB/s, fait.+Total 6368 (delta 5030), reused 11 (delta 3)+To /home/anarcat/mp3+   05681b9..266099a  git-annex -> synced/git-annex+ok+[1019]anarcat@angela:Music$ git annex find --in f867da6f-78cb-49be-a0db-d1c8e5f53664 --not --in here # trying again+git-annex: there is no available git remote named "f867da6f-78cb-49be-a0db-d1c8e5f53664"+[1020]anarcat@angela:Music1$ git annex find --in n900 --not --in here # of course, n900 is not a git remote locally+git-annex: there is no available git remote named "n900"+[1021]anarcat@angela:Music1$ git annex info --fast # and it's still not there+repository mode: indirect+trusted repositories: 0+semitrusted repositories: 5+        00000000-0000-0000-0000-000000000001 -- web+        00000000-0000-0000-0000-000000000002 -- bittorrent+        0f9185ea-8462-4230-8cae-462a1ad0df36 -- origin+        45124790-dbb7-4e2e-bc0a-acfb618a01e0 -- anarcat@angela:/media/anarcat/cb39412b-d221-+        6f812272-18c8-4346-b68a-f57ae50f657e -- here+untrusted repositories: 0+transfers in progress: none+available local disk space: 4.68 gigabytes (+1 megabyte reserved)+[1022]anarcat@angela:Music$ cd -+/home/anarcat/mp3+[1023]anarcat@angela:mp3$ git annex info --fast # worse: it's gone from my main repo!!+repository mode: indirect+trusted repositories: 2+        b7802161-c984-4c9f-8d05-787a29c41cfe -- marcos+        c2ca4a13-9a5f-461b-a44b-53255ed3e2f9 -- markov+semitrusted repositories: 6+        00000000-0000-0000-0000-000000000001 -- web+        00000000-0000-0000-0000-000000000002 -- bittorrent+        0f9185ea-8462-4230-8cae-462a1ad0df36 -- here+        45124790-dbb7-4e2e-bc0a-acfb618a01e0 -- anarcat@angela:/media/anarcat/cb39412b-d221-4846-a9dd-cdbabd9958f1/Music+        487dda55-d164-4bf1-9d85-66caaa9c0743 -- VHS+        6f812272-18c8-4346-b68a-f57ae50f657e -- htcones+untrusted repositories: 0+transfers in progress: none+available local disk space: 13.74 gigabytes (+1 megabyte rese+"""]]++In my opinion, git-annex shouldn't have lost the following repositories:++        22921df6-ff75-491c-b5d9-5a2aab33a689 -- anarcat@marcos:/media/anarcat/79884590-6445-4a6f-ae12-050b9a7c1912/mp3+        f8818d12-9882-4ca5-bc0f-04e987888a8d -- anarcat@marcos:/media/anarcat/green_crypt/mp3/+        3f6d8082-6f4b-4faa-a3d9-bd5db1891077 -- anarcat@lab-sc.no-ip.org:mp3+        4249a4ea-343a-43a8-9bba-457d2ff87c7d -- rachel@topcrapn:~/Musique/MUSIC/anarcat+        f867da6f-78cb-49be-a0db-d1c8e5f53664 -- n900++Those are repositories that are in the git-annex history, but that don't have git remotes associated with them, for various reasons. I do *not* believe I have marked any of those as "dead" except maybe 3f6d8082-6f4b-4faa-a3d9-bd5db1891077. f8818d12-9882-4ca5-bc0f-04e987888a8d was used during the weekend to do my backups, so it's definitely not dead.++It is also interesting to note that even though `git annex info` doesn't know about the remotes, there is still tracking information about all of them (except the 3f one):++[[!format txt """+$ git cat-file -p git-annex:001/694/SHA256E-s6732474--e084001bc23a90bfd65d9a3fa20b7bf878be6a49fce7e5a9846efeeba8815516.mp3.log+1376877225.866849s 1 b7802161-c984-4c9f-8d05-787a29c41cfe+1378838314.653241s 1 c2ca4a13-9a5f-461b-a44b-53255ed3e2f9+1379790798.215871s 1 0f9185ea-8462-4230-8cae-462a1ad0df36+1391065040.28672s 1 22921df6-ff75-491c-b5d9-5a2aab33a689+1397893686.079999s 1 487dda55-d164-4bf1-9d85-66caaa9c0743+1398657510.376249s 1 4249a4ea-343a-43a8-9bba-457d2ff87c7d+1407479149.838437s 1 f8818d12-9882-4ca5-bc0f-04e987888a8d+1407479149.929843s 1 f8818d12-9882-4ca5-bc0f-04e987888a8d+1407510928.457047s 1 487dda55-d164-4bf1-9d85-66caaa9c0743+1424134721.290026s 1 b7802161-c984-4c9f-8d05-787a29c41cfe+1424227570.153123s 1 487dda55-d164-4bf1-9d85-66caaa9c0743+1445468844.056214s 1 f867da6f-78cb-49be-a0db-d1c8e5f53664+1458775384.454193s 0 6f812272-18c8-4346-b68a-f57ae50f657e+"""]]++it's a mystery to me why that stuff disappeared from `git-annex info`. it's especially confusing since some commands seem to recognize there *was* a remote there:++    $ git annex enableremote f867da6f-78cb-49be-a0db-d1c8e5f53664+    git-annex: Unknown special remote.+            f867da6f-78cb-49be-a0db-d1c8e5f53664 -- n900++Notice how `n900` was shown here: that metadata obviously *is* somewhere! The uuid.log file is obviously damaged:++    [1036]anarcat@angela:mp31$ git cat-file -p git-annex:uuid.log+    45124790-dbb7-4e2e-bc0a-acfb618a01e0 anarcat@angela:/media/anarcat/cb39412b-d221-4846-a9dd-cdbabd9958f1/Music timestamp=1459356223.537195s++... and it clearly looks like the file was damaged on that new repo:++[[!format txt """+*   266099a N (synced/git-annex, git-annex) continuing transition ["forget git history","forget dead remotes","forget git history","forget dead remotes","forget git history","forget git history","forget dead remotes","forget git history","forget dead remotes","forget git history","forget dead remotes","forget git history","forget dead remotes"] (il y a 75 minutes) <Antoine Beaupré>+|\+* | 298cc10 N (htcones/synced/git-annex) continuing transition ["forget git history","forget dead remotes","forget git history","forget dead remotes","forget git history","forget git history","forget dead remotes","forget git history","forget dead remotes","forget git history","forget dead remotes","forget git history","forget dead remotes"] (il y a 13 jours) <Antoine Beaupré>| |+| | diff --git a/uuid.log b/uuid.log+| | index 656b369..a730ad0 100644+| | --- a/uuid.log+| | +++ b/uuid.log+| | @@ -1,14 +1,9 @@+| |  0f9185ea-8462-4230-8cae-462a1ad0df36 anarcat@angela:~/mp3 timestamp=1376882226.164478s+| |  22921df6-ff75-491c-b5d9-5a2aab33a689 anarcat@marcos:/media/anarcat/79884590-6445-4a6f-ae12-050b9a7c1912/mp3 timestamp=1397741440.125973s+| | -2fec390f-f21b-4293-be50-f219be10ea02 anarcat@marcos:/media/anarcat/Nokia N900/.sounds/mp3-test timestamp=1444709804.587901s+| |  3f6d8082-6f4b-4faa-a3d9-bd5db1891077 anarcat@lab-sc.no-ip.org:mp3 timestamp=1397882243.602438s+| | -3f6d8082-6f4b-4faa-a3d9-bd5db1891077 anarcat@serveur-maison:~/mp3 timestamp=1397870776.162703s+| |  4249a4ea-343a-43a8-9bba-457d2ff87c7d rachel@topcrapn:~/Musique/MUSIC/anarcat timestamp=1398631775.545666s+| |  487dda55-d164-4bf1-9d85-66caaa9c0743 300GB hard drive labeled VHS timestamp=1397880144.616515s+| | -509d1cd7-ecd1-4e2f-803d-575d9c56a5bc anarcat@angela:/media/anarcat/Nokia N900/.sounds/mp3 timestamp=1444483581.960103s+| |  b7802161-c984-4c9f-8d05-787a29c41cfe anarcat@marcos:/srv/mp3 timestamp=1376874943.951103s+| |  c2ca4a13-9a5f-461b-a44b-53255ed3e2f9 anarcat@desktop008:/srv/musique/anarcat/mp3 timestamp=1410989161.237514s+| | -c2ca4a13-9a5f-461b-a44b-53255ed3e2f9 anarcat@desktop008:/srv/musique/anarcat/musique/mp3 timestamp=1384884883.106166s+| | -f641e18f-7cb1-49ba-abe1-7544b435b67f anarcat@marcos:/media/anarcat/Nokia N900/.sounds/mp3-init timestamp=1444708760.468268s+| |  f867da6f-78cb-49be-a0db-d1c8e5f53664 n900 timestamp=1445438785.796624s+| |  f8818d12-9882-4ca5-bc0f-04e987888a8d anarcat@marcos:/media/anarcat/green_crypt/mp3/ timestamp=1407470841.967597s+"""]]++So i guess i could manually edit that uuid.log file to restore my metadata, but i'm puzzled as to where my data went or how!++### Workaround++The workaround is to, of course, restore a known sane `uuid.log`:++[[!format sh """+[1048]anarcat@angela:~128$ git clone -b git-annex mp3 mp3.annex+Clonage dans 'mp3.annex'...+fait.+Extraction des fichiers: 100% (32234/32234), fait.+[1049]anarcat@angela:~$ cd mp3.annex/+[1067]anarcat@angela:mp3.annex$ git co dfe1b77 uuid.log+[1068]anarcat@angela:mp3.annex$ git status+Sur la branche git-annex+Votre branche est à jour avec 'origin/git-annex'.+Modifications qui seront validées :+  (utilisez "git reset HEAD <fichier>..." pour désindexer)++        modifié :         uuid.log++[1069]anarcat@angela:mp3.annex$ git commit -m"restore broken uuid.log"+[git-annex 9628f3b] restore broken uuid.log+ 1 file changed, 14 insertions(+), 1 deletion(-)+ rewrite uuid.log (100%)+[1070]anarcat@angela:mp3.annex$ git push+Décompte des objets: 2, fait.+Delta compression using up to 2 threads.+Compression des objets: 100% (2/2), fait.+Écriture des objets: 100% (2/2), 262 bytes | 0 bytes/s, fait.+Total 2 (delta 1), reused 0 (delta 0)+To /home/anarcat/mp3+   266099a..9628f3b  git-annex -> git-annex+[1071]anarcat@angela:mp3.annex$ cd -+/home/anarcat+[1072]anarcat@angela:~$ git ^C+[1072]anarcat@angela:~130$ cd -+/home/anarcat/mp3.annex+[1072]anarcat@angela:mp3.annex$ cd ../mp3+[1073]anarcat@angela:mp3$ git annex merge+merge git-annex ok+[1074]anarcat@angela:mp3$ git annex info --fast+repository mode: indirect+trusted repositories: 4+        22921df6-ff75-491c-b5d9-5a2aab33a689 -- anarcat@marcos:/media/anarcat/79884590-6445-4a6f-ae12-050b9a7c1912/mp3+        b7802161-c984-4c9f-8d05-787a29c41cfe -- anarcat@marcos:/srv/mp3 [marcos]+        c2ca4a13-9a5f-461b-a44b-53255ed3e2f9 -- anarcat@desktop008:/srv/musique/anarcat/mp3 [markov]+        f8818d12-9882-4ca5-bc0f-04e987888a8d -- anarcat@marcos:/media/anarcat/green_crypt/mp3/+semitrusted repositories: 8+        00000000-0000-0000-0000-000000000001 -- web+        00000000-0000-0000-0000-000000000002 -- bittorrent+        0f9185ea-8462-4230-8cae-462a1ad0df36 -- anarcat@angela:~/mp3 [here]+        3f6d8082-6f4b-4faa-a3d9-bd5db1891077 -- anarcat@lab-sc.no-ip.org:mp3+        4249a4ea-343a-43a8-9bba-457d2ff87c7d -- rachel@topcrapn:~/Musique/MUSIC/anarcat+        487dda55-d164-4bf1-9d85-66caaa9c0743 -- 300GB hard drive labeled VHS [VHS]+        6f812272-18c8-4346-b68a-f57ae50f657e -- htcones+        f867da6f-78cb-49be-a0db-d1c8e5f53664 -- n900+untrusted repositories: 0+transfers in progress: none+available local disk space: 13.44 gigabytes (+1 megabyte reserved)+"""]]++But it seems to me there is a weird interaction between transitions and fresh new git repo syncs... that could be fixed...++### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)++Yes! Git-annex works generally well and, even though i often report bugs here, i am still quite happy with it. :) --[[anarcat]]
+ doc/bugs/startup_scan_extremely_slow___40__v6_repo__41__.mdwn view
@@ -0,0 +1,69 @@+### Please describe the problem.++When the assistant starts it takes several hours to do the startup scan, even when there are no files to add.++The repo contains many small files but it is configured to add the smaller ones via gitattributes. In particular there are: 91949 files added to git repo and 1029 annexed.+This is my gitattributes++    * annex.largefiles=(largerthan=500kb)++annex.addunlocked is set to true++### What steps will reproduce the problem?++Create a repo with ~90000 files smaller than 500k and ~1000 files larger (in my case ranging from 500k to 32M). Set addunlocked to true and annex.largefiles to largerthan=500kb. Start the assistant and let it finish adding the files. Restart the assistant.++### What version of git-annex are you using? On what operating system?++git-annex version: 6.20160318+build flags: Assistant Webapp Pairing Testsuite S3(multipartupload)(storageclasses) WebDAV Inotify DBus DesktopNotify XMPP ConcurrentOutput TorrentParser MagicMime Feeds Quvi+key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 SHA1E SHA1 MD5E MD5 WORM URL+remote types: git gcrypt S3 bup directory rsync web bittorrent webdav tahoe glacier ddar hook external+local repository version: 6++I'm running it on Arch Linux (packaged version)++### Please provide any additional information below.++[[!format sh """++[2016-03-29 22:08:26.356586] main: starting assistant version 6.20160318++  No known network monitor available through dbus; falling back to polling+(scanning...) [2016-03-29 22:08:41.426049] Watcher: Performing startup scan+[2016-03-29 23:05:40.533113] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 00:10:07.085051] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 01:23:29.784236] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 02:43:02.048312] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 03:37:53.273057] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 04:04:56.875573] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 04:31:14.370618] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 04:56:12.467889] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 05:21:09.021728] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 05:43:11.111616] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 06:14:38.096425] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 06:49:54.730879] Committer: Committing changes to git+(recording state in git...)+[2016-03-30 07:26:47.721929] Committer: Committing changes to git+(recording state in git...)+++# End of transcript or log.+"""]]++At this point I stopped the assistant that was still doing the startup scan...++### Have you had any luck using git-annex before?++Sure!
+ doc/bugs/v6_repo_can_not_restore_files_with_executable_permission.mdwn view
@@ -0,0 +1,92 @@+### Please describe the problem.+If a file is executable, the content of the file remains to be an SHA hash in a newly cloned repository. Neither 'git annex sync --content' or 'git annex get' can bring the file back.+The only way to bring the file back is to remove the file and do a 'git checkout' or 'git reset HEAD --hard'++If the file is not an executable (a tarball for example), it works as expected.++If I did not clone the repo but created a new repo and then manually added a remote it also worked as expected.++### What steps will reproduce the problem?+See log below.++### What version of git-annex are you using? On what operating system?+6.20160318-gd594fc0 on Ubuntu 15.10++### Please provide any additional information below.++[[!format sh """+# If you can, paste a complete transcript of the problem occurring here.+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log++vagrant@vm:/tmp/$ cd annex/+vagrant@vm:/tmp/annex/$ mkdir repo1+vagrant@vm:/tmp/annex/$ cd repo1/+vagrant@vm:/tmp/annex/repo1/$ git init+Initialized empty Git repository in /tmp/annex/repo1/.git/+vagrant@vm:/tmp/annex/repo1/$ git annex init --version=6+init  ok+(recording state in git...)+vagrant@vm:/tmp/annex/repo1/$ cp /bin/ls .+‘/bin/ls’ -> ‘./ls’+vagrant@vm:/tmp/annex/repo1/$ git add ls+vagrant@vm:/tmp/annex/repo1/$ git ci -am 'added ls binary'+(recording state in git...)+[master (root-commit) 7889519] added ls binary+ 1 file changed, 1 insertion(+)+ create mode 100755 ls+vagrant@vm:/tmp/annex/repo1/$ ls -l+total 116+-rwxr-xr-x 1 vagrant vagrant 118272 Apr  1 12:56 ls+vagrant@vm:/tmp/annex/repo1/$ cd ..+vagrant@vm:/tmp/annex/$ git clone repo1 repo2+Cloning into 'repo2'...+done.+vagrant@vm:/tmp/annex/$ cd repo2+vagrant@vm:/tmp/annex/repo2/$ git annex init --version=6+init  (merging origin/git-annex into git-annex...)+(recording state in git...)+(scanning for unlocked files...)+ok+(recording state in git...)+vagrant@vm:/tmp/annex/repo2/$ ls -l+total 4+-rwxrwxr-x 1 vagrant vagrant 97 Apr  1 12:57 ls+vagrant@vm:/tmp/annex/repo2/$ git annex sync --content+commit  ok+pull origin +ok+get ls (from origin...) (checksum...) ok+pull origin +ok+(recording state in git...)+push origin +Counting objects: 11, done.+Delta compression using up to 8 threads.+Compressing objects: 100% (9/9), done.+Writing objects: 100% (11/11), 1.10 KiB | 0 bytes/s, done.+Total 11 (delta 1), reused 0 (delta 0)+To /tmp/annex/repo1+ * [new branch]      git-annex -> synced/git-annex+ * [new branch]      master -> synced/master+ok+vagrant@vm:/tmp/annex/repo2/$ ls -l+total 4+-rwxrwxr-x 1 vagrant vagrant 97 Apr  1 12:57 ls+vagrant@vm:/tmp/annex/repo2/$ cat ls+/annex/objects/SHA256E-s118272--0b786b336b0391b56dabb7b078a23ec4295115628cfd4b635f4d8ae5ae0cfafc+vagrant@vm:/tmp/annex/repo2/$ git annex get ls+vagrant@vm:/tmp/annex/repo2/$ cat ls+/annex/objects/SHA256E-s118272--0b786b336b0391b56dabb7b078a23ec4295115628cfd4b635f4d8ae5ae0cfafc+vagrant@vm:/tmp/annex/repo2/$ rm ls+vagrant@vm:/tmp/annex/repo2/$ git checkout ls+vagrant@vm:/tmp/annex/repo2/$ ls -l +total 116+-rwxrwxr-x 1 vagrant vagrant 118272 Apr  1 12:59 ls+++# End of transcript or log.+"""]]++### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)++
doc/design/adjusted_branches.mdwn view
@@ -9,7 +9,7 @@ Both of these could be met by making `git-annex sync` maintain an adjusted version of the original branch, eg `adjusted/master`. -There would be a filter function. For #1 above it would simply convert all+There would be a adjustment function. For #1 above it would simply convert all annex symlinks to annex file pointers. For #2 above it would omit files whose content is not currently in the annex. Sometimes, both #1 and #2 would be wanted.@@ -20,7 +20,7 @@  [[!toc]] -## filtering+## adjusting  	master           adjusted/master 	A@@ -29,7 +29,7 @@  When generating commit A', reuse the date of A and use a standard author, committer, and message. This means that two users with the adjusted branch-checked out and using the same filters will get identical shas for A', and+checked out and using the same adjustments will get identical shas for A', and so can collaborate on them.  ## commit@@ -38,7 +38,7 @@ So, the user can `git commit` as usual. This does not touch the original branch yet.  -Then we need to get from that commit to one with the filters reversed,+Then we need to get from that commit to one with the adjustments reversed, which should be the same as if the adjusted branch had not been used. This commit gets added onto the original branch. @@ -57,17 +57,14 @@ Note particularly that B does not have A' or C in its history; the adjusted branch is not evident from outside. -Also note that B gets filtered and the adjusted branch is rebased on top of+Also note that B gets adjusted and the adjusted branch is rebased on top of it, so C does not remain in the adjusted branch history either. This will make other checkouts that are in the same adjusted branch end up with the same B' commit when they pull B. -It might be useful to have a post-commit hook that generates B and B'-and updates the branches. And/or `git-annex sync` could do it.- There may be multiple commits made to the adjusted branch before any get-applied back to the original branch. This is handled by reverse filtering-one at a time and rebasing the others on top.+applied back to the original branch. This is handled by reverse adjusting+commits one at a time and rebasing the others on top.  	master           adjusted/master 	A@@ -94,7 +91,7 @@   [WORKTREE: A pre-commit hook would be needed to update the staged changes, -reversing the filter before the commit is made. All the other complications+reversing the adjustment before the commit is made. All the other complications above are avoided.]  ## merge@@ -106,64 +103,62 @@ that are merged in, for object add/remove to work as described below.  When merging, there should never be any commits present on the-adjusted/master branch that have not yet been filtered over to the master-branch. If there are any such commits, just filter them into master before-beginning the merge. There may be staged changes, or changes in the work tree.--First filter the new commit:+adjusted/master branch that have not yet been propigated back to the master+branch. If there are any such commits, just propigate them into master+before beginning the merge. There may be staged changes, or changes in the+work tree. -	origin/master    adjusted/master-	A-	|--------------->A'-	|                |-	|                |-	B-	|                -	|---------->B'+First, merge origin/master into master. This is done in a temp work+tree and with a temp index, so does not affect the checked out adjusted+branch. -Then, merge that into adjusted/master:+(Note that the reason this is done, rather than adjusting origin/master+and merging it into the work tree, is that merge conflicts would be very+common with the naive approach, because the adjusted branch often changes+files, and origin/master may change the same files.) -	origin/master    adjusted/master-	A-	|--------------->A'-	|                |-	|                |-	B                |-	|                |-	|----------->B'->B''+	origin/master  master   adjusted/master+	A------------->A- - - ->A'+	|              |+	B------------->C -That merge will take care of updating the work tree.+While a fast-forward merge is shown here, other merges work the same way.+There may be merge conflicts; if so they're auto-resolved. -(What if there is a merge conflict between A' and B'? Normally such a merge-conflict should only affect the work tree/index, so can be resolved without-making a commit, but B'' may end up being made to resolve a merge-conflict.)+Then, adjust merge commit C, and merge that into adjusted/master.+	+	origin/master  master   adjusted/master+	A------------->A- - - ->A'+	|              |        |+	B------------->C- - C'->D' -Once the merge is done, we have a commit B'' on adjusted/master. To finish,-adjust that commit so it does not have adjusted/master as its parent.+This merge is done in-worktree, so the work tree gets updated.+There may be more merge conflicts here; they're also auto-resolved. -	origin/master    adjusted/master-	A-	|--------------->A'-	|                |-	|                |-	B-	|                -	|--------------->B''-	|                |+Now, D' is a merge commit, between A' and C'. +To finish, change that commit so it does not have A' as its parent. -Finally, update master to point to B''.+This can be accomplished by propigating the reverse-adjusted D'+back to master, and then adjusting master to yield the final+adjusted/master.+	+	origin/master  master   adjusted/master+	A------------->A+	|              |         +	B------------->C         +	               |         +		       D - - -> D' -Notice how similar this is to the commit graph. So, "fast-forward" +Notice how similar this is to the commit graph. Indeed, "fast-forward"  merging the same B commit from origin/master will lead to an identical-sha for B' as the original committer got.+sha for B' as the original committer got!  Since the adjusted/master branch is not present on the remote, if the user does a `git pull`, it won't merge in changes from origin/master. Which is-good because the filter needs to be applied first.+good because the adjustment needs to be applied first.  However, if the user does `git merge origin/master`, they'll get into a-state where the filter has not been applied. The post-merge hook could be+state where the adjustment has not been applied. The post-merge hook could be used to clean up after that. Or, let the user foot-shoot this way; they can always reset back once they notice the mistake. @@ -175,45 +170,39 @@ ## annex object add/remove  When objects are added/removed from the annex, the associated file has to-be looked up, and the filter applied to it. So, dropping a file with the-missing file filter would cause it to be removed from the adjusted branch,+be looked up, and the adjustment applied to it. So, dropping a file with the+missing file adjustment would cause it to be removed from the adjusted branch, and receiving a file's content would cause it to appear in the adjusted-branch.+branch. TODO  These changes would need to be committed to the adjusted branch, otherwise `git diff` would show them. -[WORKTREE: Simply adjust the work tree (and index) per the filter.]+How to avoid making a new commit each time a single object is+added/removed? That seems too expensive in both CPU and dangling git+objects for old versions of the adjusted branch. It would be fine if+`git annex get` and `git annex drop` only re-adjusted the branch one time+at the end. OTOH, when should the assistant re-adjust the branch? -## reverse filtering+Maybe instead of re-adjusting the branch after each file, stage the+worktree change, and hold off on committing. Then when a commit is+eventually made, the reverse adjusting to propigate it to master would need+to make sure to not remove files that were deleted as part of the commit,+if their content is not present. -Reversing filter #1 would mean only converting pointer files to-symlinks when the file was originally a symlink. This is problimatic when a-file is renamed. Would it be ok, if foo is renamed to bar and bar is-committed, for it to be committed as an unlocked file, even if foo was-originally locked? Probably.+[WORKTREE: Simply adjust the work tree (and index) per the adjustment.] -Reversing filter #2 would mean not deleting removed files whose content was-not present. When the commit includes deletion of files that were removed-due to their content not being present, those deletions are not propigated.-When the user deletes an unlocked file, the content is still-present in annex, so reversing the filter should propigate the file-deletion. +## reverse adjusting commits -What if an object was sent to the annex (or removed from the annex)-after the commit and before the reverse filtering? This would cause the-reverse filter to draw the wrong conclusion. Maybe look at a list of what-objects were not present when applying the filter, and use that to decide-which to not delete when reversing it?+A user's commits on the adjusted branch have to be reverse adjusted+to get changes to apply to the master branch. -So, a reverse filter may need some state that was collected when running-the filter forwards, in order to decide what to do.+This reversal of one adjustment can be done as just another adjustment.+Since only files touched by the commit will be reverse adjusted, it doesn't+need to reverse all changes made by the original adjustment. -Alternatively, instead of reverse filtering the whole adjusted tree,-look at just the new commit that's being propigated back from the-adjusted to master branch. Get the diff from it to the previous-commit; the changes that were made. Then de-adjust those changes,-and apply the changes to the master branch.+For example, reversing the unlock adjustment might lock the file. Or, it might+do nothing, which would make all committed files remain unlocked.  ## push @@ -242,11 +231,12 @@ WORKTREE notes throughout this page. Overall, the WORKTREE approach seems too problimatic. -Ah, but we know that when filter #2 is in place, any file that `git annex+Ah, but we know that when adjustment #2 is in place, any file that `git annex get` could act on is not in the index. So, it could look at the master branch-instead. (Same for `git annex move --from` and `git annex copy --from`)+instead. (Same for `git annex move --from` and `git annex copy --from` and+the assistant.) -OTOH, if filter #1 is in place and not #2, a file might be renamed in the+OTOH, if adjustment #1 is in place and not #2, a file might be renamed in the index, and `git annex get $newname` should work. So, it should look at the index in that case. @@ -254,9 +244,16 @@  Using `git checkout` when in an adjusted branch is problimatic, because a non-adjusted branch would then be checked out. But, we can just say, if-you want to get into an adjusted branch, you have to run some command.-Or, could make a post-checkout hook.+you want to get into an adjusted branch, you have to run git annex adjust+Or, could make a post-checkout hook. This is would mostly be confusing when+git-annex init switched into the adjusted branch due to lack of symlink+support. +After a commit to an adjusted branch, `git push` won't do anything. The+user has to know to git-annex sync. (Even if a pre-commit hook propigated+the commit back to the master branch, `git push` wouldn't push it with the+default "matching" push strategy.)+ Tags are bit of a problem. If the user tags an ajusted branch, the tag includes the local adjustments.   [WORKTREE: not a problem]@@ -266,63 +263,54 @@ [WORKTREE: not a problem]  When a pull modifies a file, its content won't be available, and so it-would be hidden temporarily by filter #2. So the file would seem to vanish,+would be hidden temporarily by adjustment #2. So the file would seem to vanish, and come back later, which could be confusing. Could be fixed as discussed in [[todo/deferred_update_mode]]. Arguably, it's just as confusing for the file to remain visible but have its content temporarily replaced with a annex pointer. +### master push overwrite race (fixed)++There are potentially races in code that assumes a branch like+master is not being changed by someone else. +  +In particular, if propigateAdjustedCommits rebases the adjusted branch on+top of master. That is called by sync. The assumption is that any changes+in master have already been handled by updateAdjustedBranch. But, if+another remote pushed a new master at just the right time, the adjusted+branch could be rebased on top of a master that it doesn't incorporate,+which is wrong.++Best fix seems to be to maintain a basis ref, that is not a branch,+like refs/adjusted/master(unlocked). Copy master's ref to it when+entering the view branch. Then, make all adjustments via the basis+ref, and propigate back to refs/heads/master.++It's fine to overwrite changes that were pushed to master when+propigating from the adjusted branch. Synced changes also go to+synced/master so won't be lost. Pushes not made using git-annex sync+of master are not really desired, just a possibility.+ ## integration with view branches -Entering a view from an adjusted branch should probably carry the filtering+Entering a view from an adjusted branch should probably carry the adjusting over into the creation/updating of the view branch.  Could go a step further, and implement view branches as another branch-adjusting filter, albeit an extreme one. This might improve view branches.+adjustment, albeit an extreme one. This might improve view branches. For example, it's not currently possible to update a view branch with changes fetched from a remote, and this could get us there. -This would need the reverse filter to be able to change metadata.+This would need the reverse adjust to be able to change metadata,+so that a commit that moved files in the view updates their metadata.  [WORKTREE: Wouldn't be able to integrate, unless view branches are changed into adjusted view worktrees.] -## filter interface--Distilling all of the above, the filter interface needs to be something-like this, at its most simple:--	data Filter = UnlockFilter | HideMissingFilter | UnlockHideMissingFilter--	getFilter :: Annex Filter--	setFilter :: Filter -> Annex ()--	data FilterAction-		= UnchangedFile FilePath-		| UnlockFile FilePath-		| HideFile FilePath--	data FileInfo = FileInfo-		{ originalBranchFile :: FileStatus-		, isContentPresent :: Bool-		}--	data FileStatus = IsAnnexSymlink | IsAnnexPointer-		deriving (Eq)--	filterAction :: Filter -> FilePath -> FileInfo -> FilterAction-	filterAction UnlockFilter f fi-		| originalBranchFile fi == IsAnnexSymlink = UnlockFile f-	filterAction HideMissingFilter f fi-		| not (isContentPresent fi) = HideFile f-	filterAction UnlockHideMissingFilter f fi-		| not (isContentPresent fi) = HideFile f-		| otherwise = filterAction UnlockFilter f fi-	filterAction _ f _ = UnchangedFile f--	filteredCommit :: Filter -> Git.Commit -> Git.Commit+## TODOs -	-- Generate a version of the commit made on the filter branch-	-- with the filtering of modified files reversed.-	unfilteredCommit :: Filter -> Git.Commit -> Git.Commit+* Interface in webapp to enable adjustments.+* Honor annex.thin when entering an adjusted branch. git checkout+  will make copies of the content of annexed files, so this would need+  to checkout the adjusted branch some other way. Maybe generalize so this+  more efficient checkout is available as a git-annex command?
doc/design/assistant/polls/Android_default_directory.mdwn view
@@ -4,4 +4,4 @@ want the first time they run it, but to save typing on android, anything that gets enough votes will be included in a list of choices as well. -[[!poll open=yes expandable=yes 73 "/sdcard/annex" 6 "Whole /sdcard" 8 "DCIM directory (photos and videos only)" 2 "Same as for regular git-annex. ~/annex/"]]+[[!poll open=yes expandable=yes 73 "/sdcard/annex" 6 "Whole /sdcard" 8 "DCIM directory (photos and videos only)" 3 "Same as for regular git-annex. ~/annex/"]]
doc/design/external_special_remote_protocol.mdwn view
@@ -194,10 +194,11 @@   determined.     The Filename can be empty (in which case a default is used),   or can specify a filename that is suggested to be used for this url.-* `CHECKURL-MULTI Url Size|UNKNOWN Filename ...`  +* `CHECKURL-MULTI Url1 Size1|UNKNOWN Filename1 Url2 Size2|UNKNOWN Filename2 ...`     Indicates that the requested url has been verified to exist,   and contains multiple files, which can each be accessed using-  their own url.  +  their own url.  Each triplet of url, size, and filename should be listed,+  one after the other.   Note that since a list is returned, neither the Url nor the Filename   can contain spaces. * `CHECKURL-FAILURE`  
+ doc/devblog/day_374__security_fix.mdwn view
@@ -0,0 +1,4 @@+Pushed out a git-annex release this morning mostly because of the recent+[[bugs/git_security_fix]]. Several git-annex builds bundle a copy of git and+needed to be updated. Note that the OSX autobuilder is temporarily down and+so it's not been updated yet -- hopefully soon.
+ doc/devblog/day_375__back.mdwn view
@@ -0,0 +1,10 @@+Back from Libreplanet and a week of spring break. Backlog is not too bad+for two weeks mostly away; 143 messages.++Finally got the OSX app updated for the git security fix yesterday. Had to+drop builds for old OSX releases.++Getting back into working on adjusted branches now. Polishing up the UI and+docs today. Nearly ready to merge the feature; the only blocker is there+seems to be something a little bit wrong with how pulled changes are merged+into the adjusted branch that I noticed in testing.
+ doc/devblog/day_376__in_the_weeds.mdwn view
@@ -0,0 +1,18 @@+Spent all day fixing sync in adjusted branches. I was lost in the weeds for+a long time. Eventually, drawing this diagram helped me find my way+to a solution:++	origin/master    adjusted/master     master+	A                                    A+	|--------------->A'                  |+	|                |                   |+	|                C'- - - - - - - - > C+	B                                    |+	|                                    |+	|--------------->M'<-----------------|++After implementing that, syncing in adjusted branches seems to work much+better now. And I've finally merged support for them into master.++There's still several bugs and race conditions and upgrade things to sort+out around adjusted branches. Proably another week's work all told.
+ doc/devblog/day_377__will_adjusted_branches_ever_end.mdwn view
@@ -0,0 +1,21 @@+Feels like I've been working on adjusted branches too long.++Did make some excellent progress today. Upgrading a direct mode repo to v6+will now enter an adjusted branch where all files are unlocked. Using an+adjusted branch like this avoids unlocking all files in the master branch+of the repo, which means that different clones of a repo can be+upgraded to v6 mode at different times. This should let me advance the+timetable for enabling v6 by default, and getting rid of direct mode.++Also, cloning a repository that has an adjusted branch checked out will+now work; the clone starts out in the same adjusted branch.++But, I realized today that the way merges from origin/master into+adjusted/master are done will often lead to merge conflicts. I have came up+with a better way to handle these merges that won't unncessarily conflict,+but didn't feel ready to implement that today.++----++Instead, I spent the latter half of the day getting caught up on some+of the backlog. Got it down from some 200 messages to 150.
+ doc/devblog/day_378__finishing_adjusted_branches_merge.mdwn view
@@ -0,0 +1,23 @@+Well, I had to rethink how merges into adjusted branches should be handled.+The old method often led to unnecessary merge conflicts. My new approach+should always avoid unncessary merge conflicts, but it's quite a trick.++To merge origin/master into adjusted/master, it first merges origin/master+into master. But, since adjusted/master is checked out, it has to do the+merge in a temporary work tree. Luckily this can be done fairly+inexpensively. To handle merge conflicts at this stage, git-annex's+automatic merge conflict resolver is used. This approach wouldn't be+feasible without a way to automatically resolve merge conflicts, because+the user can't help with conflict resolution when the merge is not+happening in their working tree.++Once that out-of-tree merge is done, the result is adjusted, and merged+into the adjusted branch. Since we know the adjusted branch is a child of+the old master branch, this merge can be forced to always be a+fast-forward. This second merge will only ever have conflicts if the work+tree has something uncommitted in it that causes a merge conflict.++Wow! That's super tricky, but it seems to work well. While I ended up+throwing away everything I did [[last Thursday|day_376__in_the_weeds]]+due to this new approach, the code is in some ways simpler than that+old, busted approach.
+ doc/devblog/day_379__bugs_race_conditions_and_taxes.mdwn view
@@ -0,0 +1,12 @@+Think I'm really finished with adjusted branches now. Fixed a bug in+annex symlink calculation when merging into an adjusted branch. And, fixed+a race condition involving a push of master from another repository.++While `git annex adjust --unlock` is reason enough to have adjusted+branches, I do want to at some point look into implementing `git annex+adjust --hide-missing`, and perhaps rewrite the view branches to use+adjusted branches, which would allow for updating view branches when+pulling from a remote.++Also, turns out Windows supports hard links, so I got annex.thin working+on Windows, as well as a few other things that work better with hard links.
+ doc/encryption/comment_5_5c9897663aaa83ca39a7e8cb292a3fd1._comment view
@@ -0,0 +1,10 @@+[[!comment format=mdwn+ username="gavinwahl@d3a94ffbd6df3b8833a53ff11ec435f58f7c44a9"+ nickname="gavinwahl"+ subject="Shared key - how many keys?"+ date="2016-04-03T03:43:58Z"+ content="""+In shared mode, is a single key used to encrypt every file in the repository? Or is a new key created for each file?++Shared mode has the properties I need - getting access to the git repo should give you access to all the content. BUT, if one loses access to updates to the git repo, they should not have access to files added after they lost access.+"""]]
+ doc/encryption/comment_6_1756ce62906586f876a3491e5d9befde._comment view
@@ -0,0 +1,13 @@+[[!comment format=mdwn+ username="joey"+ subject="""comment 6"""+ date="2016-04-04T18:48:34Z"+ content="""+@gavinwahl, it's a single shared key that any clone of the repository+provides access to.++If you use the [[tahoe]] special remote, storing files in tahoe-lafs does result+in a new capability (a kind of key) being stored in the git repo.+So someone with an old clone can't access the files from tahoe-lafs.+Tahoe is unique in providing that ability.+"""]]
+ doc/forum/Android__58___Cabal_hell.mdwn view
@@ -0,0 +1,32 @@+I tried to build the Android app according to the instructions on [the install page](https://git-annex.branchable.com/install/Android/).++But during step 2 (In the chroot, run install-haskell-packages) cabal fails to handle the dependencies correctly. So I tried to change the standalone/android/cabal.config file to update all the dependencies, but this had me running into something I think is unresolvable in another package's+dependencies. Eventually I had the following output:++    # ./standalone/android/install-haskell-packages +    Downloading the latest package list from hackage.haskell.org+    Skipping download: Local and remote files match.+    /home/repo/git-annex /home/repo/git-annex/standalone/android+    Resolving dependencies...+    cabal: Could not resolve dependencies:+    trying: git-annex-6.20160318 (user goal)+    trying: persistent-template-2.1.6/installed-08b... (dependency of+    git-annex-6.20160318)+    next goal: monad-control (dependency of git-annex-6.20160318)+    rejecting: monad-control-1.0.0.5/installed-cac..., 1.0.0.5, 1.0.0.4, 1.0.0.3,+    1.0.0.2, 1.0.0.1, 1.0.0.0, 0.3.3.1, 0.3.3.0, 0.3.2.3 (global constraint+    requires ==0.3.2.2)+    rejecting: monad-control-0.3.2.2 (conflict: persistent-template =>+    monad-control==1.0.0.5/installed-cac...)+    rejecting: monad-control-0.3.2.1, 0.3.2, 0.3.1.4, 0.3.1.3, 0.3.1.2, 0.3.1.1,+    0.3.1, 0.3.0.1, 0.3, 0.2.0.3, 0.2.0.2, 0.2.0.1, 0.2, 0.1 (global constraint+    requires ==0.3.2.2)++This tells me that the package persistent-template depends on the package monad-control at a version of 1.0.0.5. So I look at the [persistent-template hackage page](https://hackage.haskell.org/package/persistent-template-2.1.6) and see that it lists its dependency on monad-control as:++    monad-control (>=0.2 && <1.1)++And I don't think that's possible to resolve.++All I wanted to do was change the icons on the Android package, so if you'll just accept the changed+icons folder, I can submit the patch without testing the Android build, but currently I'm unable to build the Android port of git-annex.
+ doc/forum/CD-R_as_special_remote.mdwn view
@@ -0,0 +1,10 @@+I would like to use a CD-R as a special remote for one of my repositories. I'm not sure what the best way to do this is. I'm thinking aomething like:++1. Make a new directory+2. Add the directory as a special remote using type=directory+3. Copy the files to the special remote+4. Create an iso of the directory and burn it++Does that sound right?++I'm not sure how I can do stuff like tell git-annex that the maximum size of the remote is 700MB and that (after the initial push) the remote should be considered read only. I intend to have multiple of these CD-R/directory remotes for the one annex. Has anybody done anything like this before?
− doc/forum/MegaAnnex_not_working..mdwn
@@ -1,32 +0,0 @@-When copying to a megaannex remote, it hangs after a while, and I get this:--    copy Boomarks/Android (gpg) Traceback (most recent call last):-      File "/usr/local/bin//git-annex-remote-mega", line 511, in <module>-        common.startRemote()-      File "/home/zack/megaannex/lib/CommonFunctions.py", line 557, in startRemote-        sys.modules["__main__"].checkpresent(line)-      File "/usr/local/bin//git-annex-remote-mega", line 483, in checkpresent-        folder = setFolder(conf["folder"], common.ask("DIRHASH " + line[1]))-      File "/usr/local/bin//git-annex-remote-mega", line 401, in setFolder-        folder = createFolder(conf["folder"], 2)-      File "/usr/local/bin//git-annex-remote-mega", line 378, in createFolder-        res = m.create_folder(subject, folder)-      File "/usr/lib/python2.7/site-packages/mega/mega.py", line 617, in create_folder-        'i': self.request_id})-      File "/usr/lib/python2.7/site-packages/mega/mega.py", line 110, in _api_request-        timeout=self.timeout)-      File "/usr/lib/python2.7/site-packages/requests/api.py", line 88, in post-        return request('post', url, data=data, **kwargs)-      File "/usr/lib/python2.7/site-packages/requests/api.py", line 44, in request-        return session.request(method=method, url=url, **kwargs)-      File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 354, in request-        resp = self.send(prep, **send_kwargs)-      File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 460, in send-        r = adapter.send(request, **kwargs)-      File "/usr/lib/python2.7/site-packages/requests/adapters.py", line 250, in send-        raise SSLError(e)-    requests.exceptions.SSLError: The read operation timed out-    (external special remote protocol error, unexpectedly received "" (unable to parse command)) failed---Any help would be appreciated, thanks!
+ doc/forum/MegaAnnex_not_working.mdwn view
@@ -0,0 +1,32 @@+When copying to a megaannex remote, it hangs after a while, and I get this:++    copy Boomarks/Android (gpg) Traceback (most recent call last):+      File "/usr/local/bin//git-annex-remote-mega", line 511, in <module>+        common.startRemote()+      File "/home/zack/megaannex/lib/CommonFunctions.py", line 557, in startRemote+        sys.modules["__main__"].checkpresent(line)+      File "/usr/local/bin//git-annex-remote-mega", line 483, in checkpresent+        folder = setFolder(conf["folder"], common.ask("DIRHASH " + line[1]))+      File "/usr/local/bin//git-annex-remote-mega", line 401, in setFolder+        folder = createFolder(conf["folder"], 2)+      File "/usr/local/bin//git-annex-remote-mega", line 378, in createFolder+        res = m.create_folder(subject, folder)+      File "/usr/lib/python2.7/site-packages/mega/mega.py", line 617, in create_folder+        'i': self.request_id})+      File "/usr/lib/python2.7/site-packages/mega/mega.py", line 110, in _api_request+        timeout=self.timeout)+      File "/usr/lib/python2.7/site-packages/requests/api.py", line 88, in post+        return request('post', url, data=data, **kwargs)+      File "/usr/lib/python2.7/site-packages/requests/api.py", line 44, in request+        return session.request(method=method, url=url, **kwargs)+      File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 354, in request+        resp = self.send(prep, **send_kwargs)+      File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 460, in send+        r = adapter.send(request, **kwargs)+      File "/usr/lib/python2.7/site-packages/requests/adapters.py", line 250, in send+        raise SSLError(e)+    requests.exceptions.SSLError: The read operation timed out+    (external special remote protocol error, unexpectedly received "" (unable to parse command)) failed+++Any help would be appreciated, thanks!
+ doc/forum/Simple_question_about_web_remote.mdwn view
@@ -0,0 +1,27 @@+Hello. I have been having some trouble with downloading podcasts. I have read the guide, but I was getting the following error message:++```+  verification of content failed++  Unable to access these remotes: web++  Try making some of these repositories available:+  	00000000-0000-0000-0000-000000000001 -- web+failed+git-annex: get: 1 failed+```+I have tried several times. Some times it seemed to work, others it did not — it was not very structured, so I do not recall the details. Recently I recreated the entire stuff from scratch and was downloading files, and after I upgraded to 6.20160318 it stopped working and just gives me the error message above, after downloading the file.++I tried looking up information about the web remote, but it mentions nothing about "making the web remote available" or something that I found to address this subject. So I am confused. What is wrong with my web repository? Why did it stop working? How can I fix it? How can I prevent this from happening in the future? Thank you.++Here is the version information:++```+git-annex version: 6.20160318+build flags: Assistant Webapp Pairing Testsuite S3(multipartupload)(storageclasses) WebDAV Inotify DBus DesktopNotify XMPP ConcurrentOutput TorrentParser MagicMime Feeds Quvi+key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 SHA1E SHA1 MD5E MD5 WORM URL+remote types: git gcrypt S3 bup directory rsync web bittorrent webdav tahoe glacier ddar hook external+local repository version: 6+supported repository versions: 5 6+upgrade supported from repository versions: 0 1 2 4 5+```
− doc/forum/mistakenly_checked___42__files__42___into_an_annex.__bummer..mdwn
@@ -1,3 +0,0 @@-A couple times working in an annex manually, I accidentally did "git add" instead of "git annex add" and ended up with files checked into my repo instead of symlinks.  So now there is some file content in git, rather than in the annex.  Is there any way to root that out, or is it there forever?  (My limited knowledge of git says: it's there forever, unless maybe you go into the branches where it lives, do an interactive rebase to the time before it was added, remove that commit, replay history, and then garbage collect, but I have no idea if that would suddenly break git annex, and it sounds painful anyway.)--If say I were a neat freak and wanted to just start over with a clean annex, I imagine the thing to do would be to just start the hell over -- and if I wanted to do that, the way to go would be to get into a full repository, do a "git annex uninit" and then throw away the .git directory, then do "git init" and "git annex init" and then "git annex add ." ?
+ doc/forum/mistakenly_checked___42__files__42___into_an_annex.__bummer.mdwn view
@@ -0,0 +1,3 @@+A couple times working in an annex manually, I accidentally did "git add" instead of "git annex add" and ended up with files checked into my repo instead of symlinks.  So now there is some file content in git, rather than in the annex.  Is there any way to root that out, or is it there forever?  (My limited knowledge of git says: it's there forever, unless maybe you go into the branches where it lives, do an interactive rebase to the time before it was added, remove that commit, replay history, and then garbage collect, but I have no idea if that would suddenly break git annex, and it sounds painful anyway.)++If say I were a neat freak and wanted to just start over with a clean annex, I imagine the thing to do would be to just start the hell over -- and if I wanted to do that, the way to go would be to get into a full repository, do a "git annex uninit" and then throw away the .git directory, then do "git init" and "git annex init" and then "git annex add ." ?
+ doc/forum/syncing_music_to_my_android_device.mdwn view
@@ -0,0 +1,17 @@+Hi!++So I am not sure how to deal with this issue right now. I have described in [[bugs/direct_cripple_mode_crippled_my_other_non-crippled_repos/]] how it takes a long time to replicate my `mp3` repository to another, crippled, filesystem (namely, FAT32). I am not sure what is going on there, but is seems difficult to setup an external device with only a subset of my music *and* keeping a proper directory structure in place.++When I `git clone` the git-annex repository onto the device, it fails because it (apparently?) transfers all the files and runs out of space. I have also tried to `git init; git annex init; git remote add [...] ; git annex sync` with similar failure modes. All those tests take a long time and I would prefer avoiding to have to reproduce those again, but I will if necessary. :) There is over 20 000 files in the git-annex repository, and about 115GB of data in there. `.git` is about 130MB on a fresh clone on a non-crippled filesystem.++Basically, my workaround so far has been to use a bare repository on the device: it works fairly well! I can transfer files to it with `git annex copy --to` and the clone is actually much faster. ++This was working well on my Nokia N900 device, as the music player was fairly smart and could figure out that similar album tags belonged together. It did have trouble finding all the files (as it does a inotify on all the directories it finds, which obviously runs out of ram on that bit git-annex), but after a few restarts it worked.++On this new Android 5.1 device (Cyanogenmod 12.1, to be more accurate), things don't go so well. The music player finds all the files much faster, but unfortunately, each song is put in a separate album, because they are all in different directories (because this is a bare repository).++This is an issue that a [[todo/dumb__44___unsafe__44___human-readable_backend/]] would solve, but since that approach doesn't seem feasible right now, I am wondering how I can manage to deploy that repository more reliably.++This is also similar to [[forum/usability__58___creating_an_archive_on_a_new_external_drive/]].++Thanks for any advice! -- [[anarcat]]
+ doc/forum/web-browser_for_the_repository.mdwn view
@@ -0,0 +1,10 @@+Hi!++I am a teacher and I would like to organize my school-files with git-annex in combination with a wiki. In the wiki I would like to outline lessons with included pictures (and links) of work-sheets etc. git-annex would help me to transfer and organize all the files. ++Now I'm searching for a web-browser for a git-annex-repository, like the source-browser of trac (or gitweb). Actually I would really like to use trac (or dokuwiki) for my school-project. I tried trac with a bare-annex-repos, but it only shows the hash-links. In the web-assistent of annex I couldn't find such a feature.+++Is there any web-browser for a git-annex-repository?++-- Tobias 
+ doc/git-annex-adjust.mdwn view
@@ -0,0 +1,50 @@+# NAME++git-annex adjust - enter an adjusted branch++# SYNOPSIS++git annex adjust --unlock`++# DESCRIPTION++Enters an adjusted form of the current branch. The annexed files will+be treated differently. For example with --unlock all annexed files will+be unlocked.++The adjusted branch will have a name like "adjusted/master(unlocked)".+Since it's a regular git branch, you can use `git checkout` to switch+back to the original branch at any time.++While in the adjusted branch, you can use git-annex and git commands as+usual. Any commits that you make will initially only be made to the+adjusted branch. ++To propigate changes from the adjusted branch back to the original branch,+and to other repositories, as well as to merge in changes from other+repositories, use `git annex sync`.++This command can only be used in a v6 git-annex repository.++# OPTIONS++* `--unlock`++  Unlock all annexed files in the adjusted branch. This allows+  annexed files to be modified.++# SEE ALSO++[[git-annex]](1)++[[git-annex-unlock]](1)++[[git-annex-upgrade]](1)++[[git-annex-sync]](1)++# AUTHOR++Joey Hess <id@joeyh.name>++Warning: Automatically converted into a man page by mdwn2man. Edit with care.
+ doc/git-annex-copy/comment_4_44dcb42a011cc203655bccca06de2e10._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="b@526b37d9a821b5f9ce4e48014422239233ded155"+ nickname="b"+ subject="Fetch files from two (or more) remotes simultaneously?"+ date="2016-03-21T22:47:42Z"+ content="""+Let's assume that user has two slow remotes. Is it possible to fetch the data from both to at least partially speed-up the process?+"""]]
+ doc/git-annex-copy/comment_5_fe7c2c6617b3a5ca153af2225fc66498._comment view
@@ -0,0 +1,11 @@+[[!comment format=mdwn+ username="joey"+ subject="""comment 5"""+ date="2016-04-04T20:30:33Z"+ content="""+If you run `git annex copy --from slowremote1` in one terminal and at the+same time run `git annex copy --from slowremote2` in another terminal,+the two processes will cooperatively get the files, spreading the load +amoung the remotes. This works because git-annex avoids downloading a file+if the same file is already being downloaded by a different process.+"""]]
doc/git-annex-direct.mdwn view
@@ -20,6 +20,8 @@ Note that the direct mode/indirect mode distinction is removed in v6 git-annex repositories. In such a repository, you can use [[git-annex-unlock]](1) to make a file's content be directly present.+You can also use [[git-annex-adjust]](1) to enter a branch where all+annexed files are unlocked, which is similar to the old direct mode.  # SEE ALSO @@ -28,6 +30,8 @@ [[git-annex-indirect]](1)  [[git-annex-unlock]](1)++[[git-annex-adjust]](1)  # AUTHOR 
doc/git-annex-log.mdwn view
@@ -20,6 +20,11 @@      For example: `--since "1 month ago"` +* `--raw-date`++  Rather than the normal display of a date in the local time zone,+  displays seconds since the unix epoch.+ * `--gource`    Generates output suitable for the `gource` visualization program.
doc/git-annex-matching-options.mdwn view
@@ -10,10 +10,10 @@ Arbitrarily complicated expressions can be built using these options. For example: -	--exclude '*.mp3' --and --not -( --in=usbdrive --or --in=archive -)+	--include='*.mp3' --and -( --in=usbdrive --or --in=archive -) -The above example prevents git-annex from working on mp3 files whose-file contents are present at either of two repositories.+The above example makes git-annex work on only mp3 files that are present+in either of two repositories.  # OPTIONS 
doc/git-annex-preferred-content.mdwn view
@@ -225,11 +225,11 @@  * `anything` -  Matches any version of any file.+  Always matches.  * `nothing` -  Matches nothing. (Same as "not anything")+  Never matches. (Same as "not anything")  * `not expression` 
doc/git-annex-shell.mdwn view
@@ -134,6 +134,24 @@   If set, git-annex-shell will refuse to run commands that do not operate   on the specified directory. +# EXAMPLES++To make a `~/.ssh/authorized_keys` file that only allows git-annex-shell+to be run, and not other commands, pass the original command to the -c+option:+    +	command="git-annex-shell -c \"$SSH_ORIGINAL_COMMAND\"",no-agent-forwarding,no-port-forwarding,no-X11-forwarding ssh-rsa AAAAB3NzaC1y[...] user@example.com++To further restrict git-annex-shell to a particular repository, +and fully lock it down to read-only mode:++	command="GIT_ANNEX_SHELL_DIRECTORY=/srv/annex GIT_ANNEX_SHELL_LIMITED=true GIT_ANNEX_SHELL_READONLY=true git-annex-shell -c \"$SSH_ORIGINAL_COMMAND\"",no-agent-forwarding,no-port-forwarding,no-X11-forwarding ssh-rsa AAAAB3NzaC1y[...] user@example.com++Obviously, `ssh-rsa AAAAB3NzaC1y[...] user@example.com` needs to+replaced with your SSH key. The above also assumes `git-annex-shell`+is availble in your `$PATH`, use an absolute path if it is not the+case.+ # SEE ALSO  [[git-annex]](1)
doc/git-annex-unlock.mdwn view
@@ -18,7 +18,7 @@ to the repository, and is temporary. With version 6, unlocking a file changes how it is stored in the git repository (from a symlink to a pointer file), so you can commit it like any other change. Also in version 6, you-can use `git add` to add a fie to the annex in unlocked form. This allows+can use `git add` to add a file to the annex in unlocked form. This allows workflows where a file starts out unlocked, is modified as necessary, and is locked once it reaches its final version. 
doc/git-annex.mdwn view
@@ -295,6 +295,13 @@      See [[git-annex-indirect]](1) for details. +* `adjust`++  Switches a repository to use an adjusted branch, which can automatically+  unlock all files, etc.+  +  See [[git-annex-adjust]](1) for details.+ # REPOSITORY MAINTENANCE COMMANDS  * `fsck [path ...]`
doc/install/OSX.mdwn view
@@ -4,8 +4,6 @@ For easy installation, use the prebuilt app bundle.  * 10.11 El Capitan / 10.10 Yosemite / 10.9 Mavericks: [git-annex.dmg](https://downloads.kitenet.net/git-annex/OSX/current/10.10_Yosemite/git-annex.dmg)-* 10.8.2 Mountain Lion: [git-annex.dmg.bz2](https://downloads.kitenet.net/git-annex/OSX/current/10.8.2_Mountain_Lion/git-annex.dmg.bz2) **warning: not being updated any longer**-* 10.7.5 Lion: [git-annex.dmg](https://downloads.kitenet.net/git-annex/OSX/current/10.7.5_Lion/git-annex.dmg) **warning: not being updated any longer**  To run the [[git-annex_assistant|/assistant]], just install the app, look for the icon, and start it up. 
− doc/news/version_6.20160126.mdwn
@@ -1,29 +0,0 @@-git-annex 6.20160126 released with [[!toggle text="these changes"]]-[[!toggleable text="""-   * Fix nasty reversion in the last release that broke sync --content's-     handling of many preferred content expressions.-   * whereis --json: Urls are now listed inside the remote that claims them,-     rather than all together at the end.-   * info, add, whereis, find: Support --batch mode.-   * Force output to be line-buffered, even when it's not connected to the-     terminal. This is particuarly important for commands with --batch-     output, which was not always being flushed at an appropriate time.-   * add, import: Support --json output.-   * addurl --json: Include field for added key (unless the file was-     added directly to git due to annex.largefiles configuration.)-     (Also done by add --json and import --json)-   * registerurl: Check if a remote claims the url, same as addurl does.-   * Bug fix: Git config settings passed to git-annex -c did not always take-     effect.-   * assistant: Use udisks2 dbus events to detect when disks are mounted,-     instead of relying on gnome/kde stuff that is not stable.-   * Fix build with QuickCheck 2.8.2-   * matchexpression: New plumbing command to check if a preferred content-     expression matches some data.-   * Removed the webapp-secure build flag, rolling it into the webapp build-     flag.-   * Removed the quvi, tahoe, feed, and tfds build flags, adding-     aeson feed and regex-tdfa to the core dependencies.-   * Roll the dns build flag into the assistant build flag.-   * Debian: Avoid building debug package, since gdb is not often useful-     to debug haskell programs."""]]
+ doc/news/version_6.20160412.mdwn view
@@ -0,0 +1,21 @@+git-annex 6.20160412 released with [[!toggle text="these changes"]]+[[!toggleable text="""+   * adjust --unlock: Enters an adjusted branch in which all annexed files+     are unlocked. The v6 equivilant of direct mode, but much cleaner!+   * Upgrading a direct mode repository to v6 has changed to enter+     an adjusted unlocked branch. This makes the direct mode to v6 upgrade+     able to be performed in one clone of a repository without affecting+     other clones, which can continue using v5 and direct mode.+   * init --version=6: Automatically enter the adjusted unlocked branch+     when filesystem doesn't support symlinks.+   * ddar remote: fix ssh calls+     Thanks, Robie Basak+   * log: Display time with time zone.+   * log --raw-date: Use to display seconds from unix epoch.+   * v6: Close pointer file handles more quickly, to avoid problems on Windows.+   * sync: Show output of git commit.+   * annex.thin and annex.hardlink are now supported on Windows.+   * unannex --fast now makes hard links on Windows.+   * Fix bug in annex.largefiles mimetype= matching when git-annex+     is run in a subdirectory of the repository.+   * Fix build with ghc v7.11. Thanks, Gabor Greif."""]]
+ doc/special_remotes/ipfs/comment_8_eedf260df630192b49557bfc84c9ce82._comment view
@@ -0,0 +1,7 @@+[[!comment format=mdwn+ username="anarcat"+ subject="git remote"+ date="2016-03-24T14:15:06Z"+ content="""+there is now a [git remote for IPFS](https://github.com/cryptix/git-remote-ipfs). I *believe* it suffers from the same problem as all files within ipfs, namely that the contents are duplicated inside the repo. However, it certainly make for an interesting decentralised way of sharing metadata. --[[anarcat]]+"""]]
+ doc/tips/playlist_fetch.mdwn view
@@ -0,0 +1,29 @@+I have made a small script to fetch a specific set of songs from a+playlist. It just iterates through a [M3U][] playlist and makes sure+that git-annex has a copy of every file in the list.++Sample run:++    [1041]anarcat@angela:Music1$ ~/bin/get-playlist -p1 -v ~/playlists/Favoris.m3u+    git-annex: Bach/Unknown Album/Concerto for 2 Violins in D.mp3 not found+    git-annex: get: 1 failed+    git annex failed to get Bach/Unknown Album/Concerto for 2 Violins in D.mp3 (originally espresso/Bach/Unknown Album/Concerto for 2 Violins in D.mp3)+    get Groovy Aardvark/Oryctérope/05 - Téléthargique.flac (from marcos...)+    SHA256E-s26735079--13c04501b9c6fa5ddda02438484d569f4d3d9b1f0bcdd8740f3b927ab756c968.flac+         26,735,079 100%   10.00MB/s    0:00:02 (xfr#1, to-chk=0/1)+    (checksum...) ok+    Groovy Aardvark/Oryctérope/05 - Téléthargique.flac+    [...]+    merge git-annex ok++I use this to synchronize specific playlists to my phone, instead of+the whole music collection, because of the limited space of the+device.++The source is AGPL and available in my+[personal git repository][]. Unfortunately, it is written in Python+and can probably not be merged into git-annex, but since it is so+specific, I figured it wouldn't be anyways. -- [[anarcat]]++[personal git repository]: http://src.anarc.at/scripts.git/blob_plain/HEAD:/get-playlist+[M3U]: https://en.wikipedia.org/wiki/M3U
doc/tips/unlocked_files.mdwn view
@@ -95,6 +95,8 @@ `git config annex.addunlocked true` """]] +## mixing locked and unlocked files+ A v6 repository can contain both locked and unlocked files. You can switch  a file back and forth using the `git annex lock` and `git annex unlock` commands. This changes what's stored in git between a git-annex symlink@@ -102,6 +104,12 @@ the repository in locked mode, use `git annex add`; to add a file in unlocked mode, use `git add`. +If you want to mostly keep files locked, but be able to locally switch+to having them all unlocked, you can do so using `git annex adjust+--unlock`. See [[git-annex-adjust]] for details. This is particularly+useful when using filesystems like FAT, and OS's like Windows that don't+support symlinks.+ ## using less disk space  Unlocked files are handy, but they have one significant disadvantage@@ -135,7 +143,7 @@ 	git annex fix  Note that setting annex.thin only has any effect on systems that support-hard links. Ie, not Windows, and not FAT filesystems.+hard links. It is supported on Windows, but not on FAT filesystems.  ## tradeoffs 
+ doc/todo/Compile_error_with_GHC_prerelease.mdwn view
@@ -0,0 +1,16 @@+For various reasons we cannot use v8.0 (prereleases) yet,+but GHC v7.11.20150407++There was a compilation hiccup with polymorphic types. I corrected it in++https://github.com/ggreif/git-annex/tree/patch-1++The commit is++https://github.com/ggreif/git-annex/commit/a0ddad8d395b5eb61d1e7e6fdcbfa766c05de3d4++Cheers,++   Gabor++> Applied, thanks. [[done]] --[[Joey]]
− doc/todo/Set_total_storage_limit_for_special_remotes..mdwn
@@ -1,1 +0,0 @@-I'd like to be able to set a fixed limit on how much storage can be uploaded to a special remote. A use case for this may be that I want to spend no more than Y dollars, on a storage service that charges $X per gigabyte. I would thus set a limit where I a upload would be interrupted with a warning about the limit, and to continue I would need to use a --force option.
+ doc/todo/Set_total_storage_limit_for_special_remotes.mdwn view
@@ -0,0 +1,1 @@+I'd like to be able to set a fixed limit on how much storage can be uploaded to a special remote. A use case for this may be that I want to spend no more than Y dollars, on a storage service that charges $X per gigabyte. I would thus set a limit where I a upload would be interrupted with a warning about the limit, and to continue I would need to use a --force option.
− doc/todo/Slow_transfer_for_a_lot_of_small_files..mdwn
@@ -1,20 +0,0 @@-What steps will reproduce the problem?-Sync a lot of small files.--What is the expected output? What do you see instead?-The expected output is hopefully a fast transfer.--But currently it seems like git-annex is only using one thread to transfer(per host or total?)--An option to select number of transfer threads to use(possibly per host) would be very nice.--> Opening a lot of connections to a single host is probably not desirable.-> -> I do want to do something to allow slow hosts to not hold up transfers to-> other hosts, which might involve running multiple queued transfers at-> once. The webapp already allows the user to force a given transfer to-> happen immediately. --[[Joey]] --And maybe also an option to limit how long a queue the browser should show, it can become quite resource intensive with a long queue.--> The queue is limited to 20 items for this reason. --[[Joey]]
+ doc/todo/Slow_transfer_for_a_lot_of_small_files.mdwn view
@@ -0,0 +1,20 @@+What steps will reproduce the problem?+Sync a lot of small files.++What is the expected output? What do you see instead?+The expected output is hopefully a fast transfer.++But currently it seems like git-annex is only using one thread to transfer(per host or total?)++An option to select number of transfer threads to use(possibly per host) would be very nice.++> Opening a lot of connections to a single host is probably not desirable.+> +> I do want to do something to allow slow hosts to not hold up transfers to+> other hosts, which might involve running multiple queued transfers at+> once. The webapp already allows the user to force a given transfer to+> happen immediately. --[[Joey]] ++And maybe also an option to limit how long a queue the browser should show, it can become quite resource intensive with a long queue.++> The queue is limited to 20 items for this reason. --[[Joey]]
doc/todo/add_sftp_backend.mdwn view
@@ -1,3 +1,9 @@ A sftp backend would be nice because gpg operations could be pipelined to the network transfer, not requiring the creation of a full file to disk with gpg before the network transmission, as it happens with rsync.  There should be some libraries that can handle the sftp connections and transfers. I read that even curl has support for that.++> Another reason to build this is that sftp has a `SFTP_FXP_STAT`+> that can get disk free space information. "echo df | sftp user@host"+> exposes this, when available. Some sftp servers can be locked down+> so that the user can't run git-annex on them, so that could be the only+> way to get diskreserve working for such a remote. --[[Joey]]
+ doc/todo/batch_get__47__drop__47__etc.mdwn view
@@ -0,0 +1,3 @@+in the spirit of [[todo/--batch_for_add/]], [[todo/--batch_for_info/]], [[todo/--batch_for_find/]] and [[todo/--batch_for_whereis/]], why not add `--batch` to get/drop/import operations?++I am writing a script to get a bunch of arbitrary files and i want to avoid the overhead of running git-annex multiple times. I know i can use `annex.alwayscommit=false` but that is rather counter-intuitive as well. --[[anarcat]]
+ doc/todo/cleaner_hack_for_man_pages.mdwn view
@@ -0,0 +1,119 @@+In recent history, we have realized that the small Perl script that+generates the man pages from Markdown is fairly limited.++Two approaches have been considered:++* go-md2man+* pandoc++Here is how pandoc does it:++    $ pandoc -f markdown -t man doc/git-annex-shell.mdwn | pastebinit+    http://paste.debian.net/424341/++Both initially fail at setting a proper `.TH` line on top, but+otherwise seem to work more or less correctly. --[[anarcat]]++Okay, update: the above commandline was incorrect for some reason. The+proper incantation is:++    pandoc -s -t man doc/git-annex-shell.mdwn -o git-annex-shell.1++For example:++    $ pandoc -s -t man doc/git-annex-shell.mdwn | man -l - | pastebinit+    http://paste.debian.net/430630/++So by default, there is no title or section header, which is, if you+ask me a little stupid: pandoc could guess a little better and parse+the `.SH NAME` section.++The workaround for this is to add Pandoc metadata either to the file,+for example:++[[!format diff """+diff --git a/doc/git-annex-shell.mdwn b/doc/git-annex-shell.mdwn+index 9b3d126..13f64ae 100644+--- a/doc/git-annex-shell.mdwn++++ b/doc/git-annex-shell.mdwn+@@ -1,3 +1,6 @@++% git-annex-shell(1) Git-annex manual | Version 5++% Joey Hess+++ # NAME+ + git-annex-shell - Restricted login shell for git-annex only SSH access+"""]]++But Ikiwiki is likely to barf on such comments, so it's probably+preferable to pass those parameters at build time:++    $ pandoc -s -V title="git-annex-shell" -V section=1 -t man doc/git-annex-shell.mdwn  | man -l - | pastebinit+    http://paste.debian.net/430632/++Looks better already! But we can improve on that even more!++    $ pandoc -s -V title="git-annex-shell" -V section=1 \+        -V header="Git Annex manual" -V footer="Version 5.xxx" \+        -t man doc/git-annex-shell.mdwn  | man -l - | pastebinit+    http://paste.debian.net/430633/++Much better. And the version can probably be passed in from the build+system (or that footer can just be dropped).++So a more complete patch would involve fixing the build system to use+(and depend on!) pandoc then remove the pesky warnings at the bottom+of all Markdown files.++More investigation would probably be necessary to check the resulting+man pages for syntax errors. For example, the above rendering, in the+`SEE ALSO` section, has `[git-annex] (1)` instead of+`git-annex(1)`, since Pandoc doesn't know about ikiwiki links. Maybe+some pre-processing would be necessary there? :/ It sure is useful to+have those links working in the web version!++I hope that helps regardless.++Update: regarding preprocessing, it seems there are basically two+options for preprocessing with pandoc:++* [scripting](http://pandoc.org/scripting.html)+* [preprocessors](https://github.com/jgm/pandoc/wiki/Pandoc-Extras#preprocessors)+  like gpp+* external filters++Preprocessors don't support arbitrary patterns like Ikiwiki links, so+they're out already. Scripting looks a little too complicated for us,+but could be a more stable alternative in the long term (if not for+Ikiwiki itself ;).++So I ended up using a simple sed(1) filter for now. It would be quite+interesting to implement a better filter directly in Pandoc, if only+for the benefit of Ikiwiki (which could then all be reimplemented in+Haskell, No Big Deal™). But for now, I am afraid that will have to do.++The resulting manpages are quite different, [here's the diff][]. It+seems mostly better escapes and markup, in general. We get nicer+bullet lists, cleaner command names (`git-annex add` instead of+`git-annex-add`).++[here's the diff]: http://fpaste.org/353524/++I have pushed a [patch][] that implements a Pandoc build to my+[personnal git-annex repo][]. It also adds pandoc as a build-dep to+the debian package - and I may be missing some parts of the build+system, hopefully you will find the missing bits and fix them, if+any.++Pandoc is awesome, and I think a great fit for this! --[[anarcat]]++Oh, and I forgot: another thing that is not handled through this+(yet?) is the "Version" footer I was using in the above examples. I+couldn't figure out how to pull that value out of the Makefile, but+maybe I missed something obvious there. I also didn't notice the+`git-union-merge.1` manpage, but it seems to be broken anyways, as it+is not in the `man/` directory and there is a comment there saying it+is "not built normally" so I ignored it.++ [personnal git-annex repo]: http://src.anarc.at/git-annex.git/+ [patch]: http://src.anarc.at/git-annex.git/commitdiff/d8a8f42f5a7ec0458718d65b72f1f814862b125b
doc/todo/hide_missing_files.mdwn view
@@ -7,3 +7,15 @@ Maybe this could be accomplished through a [[dumb, unsafe, human-readable backend]]?  Thanks for any advice! --[[anarcat]]++> This has never been done by direct mode AFAICR.+> +> But, [[design/adjusted_branches]] can do it. The basic functionality is+> implemented already; what's missing is that, once in an adjusted branch +> with missing files hidden, when a file's content arrives the adjusted+> branch needs to be updated to expose the file.+> +> This will need hooks into+> the adjusted branch code when file contents are get/dropped, and the+> naive way to do it could make things quite slow, if the branch needs to+> be re-adjusted after each get/drop of each file. --[[Joey]]
doc/todo/smudge.mdwn view
@@ -23,19 +23,16 @@   (May need to use libgit2 to do this efficiently, cannot find   any plumbing except git-update-index, which is very inneficient for   smudged files.)-* Crippled filesystem should cause all files to be transparently unlocked.-  Note that this presents problems when dealing with merge conflicts and-  when pushing changes committed in such a repo. Ideally, should avoid-  committing implicit unlocks, or should prevent such commits leaking out-  in pushes. See [[design/adjusted_branches]].-+* Checking out a different branch causes git to smudge all changed files,+  and write their content. This does not honor annex.thin.  +  This is particularly wasteful when checking out an adjusted unlocked+  branch, which causes 2x the space to be used.  +  Seems worth having a "git annex checkout" that's like "git checkout"+  to change branches, and honors annex.thin. And, `git annex adjust`+  could use the same thing internally when checking out an adjusted branch. * Eventually (but not yet), make v6 the default for new repositories.   Note that the assistant forces repos into direct mode; that will need to   be changed then, and it should enable annex.thin instead.-* annex.thin doesn't work on crippled filesystems, so changing to v6-  unlocked files on such a FS always doubles disk use from direct mode.-  Do something about this? Could use windows hard link equivilant.. Or,-  could only store the file content in the work tree and not annex/objects. * Later still, remove support for direct mode, and enable automatic   v5 to v6 upgrades. 
+ doc/todo/smudge/comment_10_19dd6be938d71c7311aecb3081849792._comment view
@@ -0,0 +1,7 @@+[[!comment format=mdwn+ username="joey"+ subject="""comment 10"""+ date="2016-04-09T17:22:11Z"+ content="""+Hardlinks now used on windows when annex.thin is enabled.+"""]]
+ doc/todo/smudge/comment_8_ab39263b7145094a9eb4a86bb5410421._comment view
@@ -0,0 +1,9 @@+[[!comment format=mdwn+ username="ExGen"+ subject="Harlinks"+ date="2016-04-02T23:32:24Z"+ content="""+Why not use **hardlinks** on Windows? This could fix \"only direct mode\" issue too. +Symlinks on windows sure want admin privilege but hardlinks won't. At least not with this tool: +<http://schinagl.priv.at/nt/ln/ln.html>+"""]]
+ doc/todo/smudge/comment_9_e194d6371384f2db560f026d6ef728ff._comment view
@@ -0,0 +1,7 @@+[[!comment format=mdwn+ username="ExGen"+ subject="Harlinks"+ date="2016-04-03T11:21:02Z"+ content="""+Also I tried now and confirmed both git's ln and cygwin's ln work on windows with hardlink, and it's supported since XP.+"""]]
doc/todo/windows_support.mdwn view
@@ -1,6 +1,18 @@ The git-annex Windows port is beta, but rapidly becoming polished and usable! +## do we need this port anymore?++See <http://blog.dustinkirkland.com/2016/03/ubuntu-on-windows.html>++If windows has transparent support for running linux executables, and those+executables can access files in "." which are on the windows system, then+you could just use this to run linux git-annex on windows. No port needed.++That would be great!++Seems like this would need Windows 10.+ ## status  * There can be problems when the git-annex repository is in a deep
+ doc/todo/wishlist__58___Unix_time_in_git_annex_log.mdwn view
@@ -0,0 +1,15 @@+Could `git annex log` show the modification times using the Unix time instead of human-readable timestamps?++This is an example of the output of `git annex log`:++```++ 2014-10-27 01:00:18 ev-2014.pdf | 50083bd6-7e20-4356-a32f-a1dde07de441 -- penn+```++If the timestamp were in Unix time, it would be easier to process in a mechanical way. Unix time would also avoid having to guess what is the correct timezone for the timestamp.++```++ 1414368018 ev-2014.pdf | 50083bd6-7e20-4356-a32f-a1dde07de441 -- penn+```++> [[done]] --[[Joey]] 
− doc/todo/wishlist__58_____39__get__39___queue_and_schedule..mdwn
@@ -1,32 +0,0 @@-During the campaign adding a chunking feature to obscure filesize for encrypted files was added to the roadmap.  But there is still one potentially valuable set* of data that git-annex can help obscure: when you access your remotes.--This data can be used to determine when a user is actively using a remote, but if a remote is always accessed at the same time that data becomes less useful.  Somebody could still monitor total traffic over a long period and figure out that a remote was more active in a given week or month, but scheduling reduces the resolution of your access times and their data.  Maybe this isn't the most important feature to add, but it would be nice to have, and could possibly be built on top of the existing git-annex scheduler.  It could work by queuing inter-remote transactions ('get', 'copy', 'sync', etc.), so that jobs start at the same time every day, or even the same time and day every week.--Possible syntax examples:-###Setting up the schedule:-git annex queue schedule Monday:1730 (starts every monday at 5:30PM)--git annex queue schedule 1400 (starts every day at 2PM)--###Queuing git-annex commands:-git annex queue prepend sync (pretends 'sync' to the very front of the queue)--git annex queue append get file.ISO (appends to queue file.ISO for retrieval from a repo)--###Viewing/editing queue:-git annex queue view (view the current queue, jobs displayed with corresponding numbers)--git annex queue rm 20 (removes job 20 from queue)---\*The four I can think of are:--* File contents (solved by crypto)--* File size (solved on the remote by chunking, but total traffic usage can't be helped)--* User IP/Remote IP (solved by VPN - outside scope of git-annex, unless someone writes a plugin)--* Access times (obscured by a queue and scheduling)--Note, there is a [[git-annex-schedule]] command now, but it only does `fsck`.
+ doc/todo/wishlist__58_____39__get__39___queue_and_schedule.mdwn view
@@ -0,0 +1,32 @@+During the campaign adding a chunking feature to obscure filesize for encrypted files was added to the roadmap.  But there is still one potentially valuable set* of data that git-annex can help obscure: when you access your remotes.++This data can be used to determine when a user is actively using a remote, but if a remote is always accessed at the same time that data becomes less useful.  Somebody could still monitor total traffic over a long period and figure out that a remote was more active in a given week or month, but scheduling reduces the resolution of your access times and their data.  Maybe this isn't the most important feature to add, but it would be nice to have, and could possibly be built on top of the existing git-annex scheduler.  It could work by queuing inter-remote transactions ('get', 'copy', 'sync', etc.), so that jobs start at the same time every day, or even the same time and day every week.++Possible syntax examples:+###Setting up the schedule:+git annex queue schedule Monday:1730 (starts every monday at 5:30PM)++git annex queue schedule 1400 (starts every day at 2PM)++###Queuing git-annex commands:+git annex queue prepend sync (pretends 'sync' to the very front of the queue)++git annex queue append get file.ISO (appends to queue file.ISO for retrieval from a repo)++###Viewing/editing queue:+git annex queue view (view the current queue, jobs displayed with corresponding numbers)++git annex queue rm 20 (removes job 20 from queue)+++\*The four I can think of are:++* File contents (solved by crypto)++* File size (solved on the remote by chunking, but total traffic usage can't be helped)++* User IP/Remote IP (solved by VPN - outside scope of git-annex, unless someone writes a plugin)++* Access times (obscured by a queue and scheduling)++Note, there is a [[git-annex-schedule]] command now, but it only does `fsck`.
doc/upgrades.mdwn view
@@ -45,47 +45,38 @@  ## v5 -> v6 (git-annex version 6.x) -The upgrade from v5 to v6 is handled manually. Run `git-annex upgrade`-performs the upgrade.--Warning: All places that a direct mode repository is cloned to should be -running git-annex version 6.x before you upgrade the repository.-This is necessary because the contents of the repository are changed-in the upgrade, and the old version of git-annex won't be able to-access files after the repo is upgraded.+The upgrade from v5 to v6 is handled manually for now.+Run `git-annex upgrade` to perform the upgrade. -This upgrade does away with the direct mode/indirect mode distinction.-A v6 git-annex repository can have some files locked and other files+A v6 git-annex repository can have some files locked while other files are unlocked, and all git and git-annex commands can be used on both locked and-unlocked files. (Although for locked files to work, the filesystem-must support symbolic links..)+unlocked files. (Although for locked files to be accessible, the filesystem+must support symbolic links.. +Direct mode repositories are upgraded to instead use the new +[[adjusted branches feature|git-annex-adjust]], which transparently unlocks+all locked files in the local repository.+ The behavior of some commands changes in an upgraded repository: -* `git add` will add files to the annex, in unlocked mode, rather than-   adding them directly to the git repository. To cause some files to be-   added directly to git, you can configure `annex.largefiles`. For-   example:+* `git add` will add files to the annex, rather than adding them directly+   to the git repository. To cause some files to be added directly+   to git, you can configure `annex.largefiles`. For example:     	git config annex.largefiles "largerthan=100kb and not (include=*.c or include=*.h)"  * `git annex unlock` and `git annex lock` change how the pointer to    the annexed content is stored in git. -There is also a new `annex.thin` setting, which makes unlocked files in v6 repositories-be hard linked to their content, instead of a copy. This saves disk-space but means any modification of an unlocked file will lose the local-(and possibly only) copy of the old version.--On upgrade, all files in a direct mode repository will be converted to-unlocked files with the `annex.thin` setting enabled.-The upgrade will stage changes to all annexed files in-the git repository, which you can then commit.--If a repository has some clones using direct mode and some using indirect-mode, all the files will end up unlocked in all clones after the upgrade.+There is also a new `annex.thin` setting, which makes unlocked files in v6+repositories be hard linked to their content, instead of a copy. This saves+disk space but means any modification of an unlocked file will lose the+local (and possibly only) copy of the old version. This is automatically+enabled when upgrading a direct mode repository, since direct mode made the+same tradeoff. -See [[tips/unlocked_files/]] for more details about locked files and thin mode.+See [[tips/unlocked_files/]] for more details about locked files and thin+mode.  ## v4 -> v5 (git-annex version 5.x) 
git-annex.cabal view
@@ -1,5 +1,5 @@ Name: git-annex-Version: 6.20160318+Version: 6.20160412 Cabal-Version: >= 1.8 License: GPL-3 Maintainer: Joey Hess <id@joeyh.name>
+ man/git-annex-adjust.1 view
@@ -0,0 +1,46 @@+.TH git-annex-adjust 1+.SH NAME+git-annex-adjust \- enter an adjusted branch+.PP+.SH SYNOPSIS+git annex adjust \-\-unlock+.PP+.SH DESCRIPTION+Enters an adjusted form of the current branch. The annexed files will+be treated differently. For example with \-\-unlock all annexed files will+be unlocked.+.PP+The adjusted branch will have a name like "adjusted/master(unlocked)".+Since it's a regular git branch, you can use \fBgit checkout\fP to switch+back to the original branch at any time.+.PP+While in the adjusted branch, you can use git-annex and git commands as+usual. Any commits that you make will initially only be made to the+adjusted branch. +.PP+To propigate changes from the adjusted branch back to the original branch,+and to other repositories, as well as to merge in changes from other+repositories, use \fBgit annex sync\fP.+.PP+This command can only be used in a v6 git-annex repository.+.PP+.SH OPTIONS+.IP "\fB\-\-unlock\fP"+.IP+Unlock all annexed files in the adjusted branch. This allows+annexed files to be modified.+.IP+.SH SEE ALSO+git-annex(1)+.PP+git-annex\-unlock(1)+.PP+git-annex\-upgrade(1)+.PP+git-annex\-sync(1)+.PP+.SH AUTHOR+Joey Hess <id@joeyh.name>+.PP+.PP+
− man/git-annex-clean.1
@@ -1,33 +0,0 @@-.TH git-annex-clean 1-.SH NAME-git-annex-clean \- git filter driver for git-annex-.PP-.SH SYNOPSIS-git annex clean-.PP-.SH DESCRIPTION-When git-annex is used as a git filter driver, this command is run-by git commands such as \fBgit add\fP. It generates a file that-is added to the git repository and points to the git-annex object-containing the content of a large file.-.PP-To configure git to use git-annex as a git filter driver, place the-following in the .gitattributes file:-.PP- * filter=annex-\&.* !filter-.PP-The annex.largefiles config is consulted to decide if a given file should-be added to git as\-is, or if its content are large enough to need to use-git-annex.-.PP-.SH SEE ALSO-git-annex(1)-.PP-git-annex\-smudge(1)-.PP-.SH AUTHOR-Joey Hess <id@joeyh.name>-.PP-.PP-
man/git-annex-direct.1 view
@@ -18,6 +18,8 @@ Note that the direct mode/indirect mode distinction is removed in v6 git-annex repositories. In such a repository, you can use git-annex\-unlock(1) to make a file's content be directly present.+You can also use git-annex\-adjust(1) to enter a branch where all+annexed files are unlocked, which is similar to the old direct mode. .PP .SH SEE ALSO git-annex(1)@@ -25,6 +27,8 @@ git-annex\-indirect(1) .PP git-annex\-unlock(1)+.PP+git-annex\-adjust(1) .PP .SH AUTHOR Joey Hess <id@joeyh.name>
man/git-annex-log.1 view
@@ -17,6 +17,10 @@ .IP For example: \fB\-\-since "1 month ago"\fP .IP+.IP "\fB\-\-raw\-date\fP"+Rather than the normal display of a date in the local time zone,+displays seconds since the unix epoch.+.IP .IP "\fB\-\-gource\fP" Generates output suitable for the \fBgource\fP visualization program. .IP
man/git-annex-matching-options.1 view
@@ -9,10 +9,10 @@ Arbitrarily complicated expressions can be built using these options. For example: .PP- \-\-exclude '*.mp3' \-\-and \-\-not \-( \-\-in=usbdrive \-\-or \-\-in=archive \-)+ \-\-include='*.mp3' \-\-and \-( \-\-in=usbdrive \-\-or \-\-in=archive \-) .PP-The above example prevents git-annex from working on mp3 files whose-file contents are present at either of two repositories.+The above example makes git-annex work on only mp3 files that are present+in either of two repositories. .PP .SH OPTIONS .IP "\fB\-\-exclude=glob\fP"
man/git-annex-preferred-content.1 view
@@ -206,10 +206,10 @@ them.) .IP .IP "\fBanything\fP"-Matches any version of any file.+Always matches. .IP .IP "\fBnothing\fP"-Matches nothing. (Same as "not anything")+Never matches. (Same as "not anything") .IP .IP "\fBnot expression\fP" Inverts what the expression matches. For example, \fBnot include=archive/*\fP
man/git-annex-shell.1 view
@@ -114,6 +114,23 @@ If set, git-annex\-shell will refuse to run commands that do not operate on the specified directory. .IP+.SH EXAMPLES+To make a \fB~/.ssh/authorized_keys\fP file that only allows git-annex\-shell+to be run, and not other commands, pass the original command to the \-c+option:+.PP+ command="git-annex\-shell \-c \\"$SSH_ORIGINAL_COMMAND\\"",no\-agent\-forwarding,no\-port\-forwarding,no\-X11\-forwarding ssh\-rsa AAAAB3NzaC1y[...] user@example.com+.PP+To further restrict git-annex\-shell to a particular repository, +and fully lock it down to read\-only mode:+.PP+ command="GIT_ANNEX_SHELL_DIRECTORY=/srv/annex GIT_ANNEX_SHELL_LIMITED=true GIT_ANNEX_SHELL_READONLY=true git-annex\-shell \-c \\"$SSH_ORIGINAL_COMMAND\\"",no\-agent\-forwarding,no\-port\-forwarding,no\-X11\-forwarding ssh\-rsa AAAAB3NzaC1y[...] user@example.com+.PP+Obviously, \fBssh\-rsa AAAAB3NzaC1y[...] user@example.com\fP needs to+replaced with your SSH key. The above also assumes \fBgit-annex\-shell\fP+is availble in your \fB$PATH\fP, use an absolute path if it is not the+case.+.PP .SH SEE ALSO git-annex(1) .PP
man/git-annex-unlock.1 view
@@ -16,7 +16,7 @@ to the repository, and is temporary. With version 6, unlocking a file changes how it is stored in the git repository (from a symlink to a pointer file), so you can commit it like any other change. Also in version 6, you-can use \fBgit add\fP to add a fie to the annex in unlocked form. This allows+can use \fBgit add\fP to add a file to the annex in unlocked form. This allows workflows where a file starts out unlocked, is modified as necessary, and is locked once it reaches its final version. .PP
man/git-annex.1 view
@@ -254,6 +254,12 @@ .IP See git-annex\-indirect(1) for details. .IP+.IP "\fBadjust\fP"+Switches a repository to use an adjusted branch, which can automatically+unlock all files, etc.+.IP+See git-annex\-adjust(1) for details.+.IP .SH REPOSITORY MAINTENANCE COMMANDS .IP "\fBfsck [path ...]\fP" .IP