80 lines
		
	
	
	
		
			2.2 KiB
			
		
	
	
	
		
			Haskell
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
	
		
			2.2 KiB
			
		
	
	
	
		
			Haskell
		
	
	
	
	
	
{- git-annex command
 | 
						|
 -
 | 
						|
 - Copyright 2014 Joey Hess <id@joeyh.name>
 | 
						|
 -
 | 
						|
 - Licensed under the GNU GPL version 3 or higher.
 | 
						|
 -}
 | 
						|
 | 
						|
module Command.Proxy where
 | 
						|
 | 
						|
import Command
 | 
						|
import Config
 | 
						|
import Utility.Tmp
 | 
						|
import Utility.Env
 | 
						|
import Annex.Direct
 | 
						|
import qualified Git
 | 
						|
import qualified Git.Sha
 | 
						|
import qualified Git.Ref
 | 
						|
import qualified Git.Branch
 | 
						|
import qualified Git.LsFiles
 | 
						|
import Git.FilePath
 | 
						|
import Utility.CopyFile
 | 
						|
 | 
						|
cmd :: Command
 | 
						|
cmd = notBareRepo $
 | 
						|
	command "proxy" SectionPlumbing 
 | 
						|
		"safely bypass direct mode guard"
 | 
						|
		("-- git command") (withParams seek)
 | 
						|
 | 
						|
seek :: CmdParams -> CommandSeek
 | 
						|
seek = withWords start
 | 
						|
 | 
						|
start :: [String] -> CommandStart
 | 
						|
start [] = error "Did not specify command to run."
 | 
						|
start (c:ps) = liftIO . exitWith =<< ifM isDirect
 | 
						|
	( do
 | 
						|
		tmp <- gitAnnexTmpMiscDir <$> gitRepo
 | 
						|
		withTmpDirIn tmp "proxy" go
 | 
						|
	, liftIO $ safeSystem c (map Param ps)
 | 
						|
	)
 | 
						|
  where
 | 
						|
	go tmp = do
 | 
						|
		oldref <- fromMaybe Git.Sha.emptyTree
 | 
						|
			<$> (inRepo . maybe Git.Ref.headSha Git.Ref.sha
 | 
						|
				=<< inRepo Git.Branch.currentUnsafe)
 | 
						|
		
 | 
						|
		exitcode <- proxy tmp
 | 
						|
 | 
						|
		cleanupproxy tmp oldref
 | 
						|
 | 
						|
		return exitcode
 | 
						|
	
 | 
						|
	proxy tmp = do
 | 
						|
		usetmp <- liftIO $ Just . addEntry "GIT_WORK_TREE" tmp  <$> getEnvironment
 | 
						|
 | 
						|
		-- Set up the tmp work tree, to contain both a checkout of all
 | 
						|
		-- staged files as well as hard links (or copies) of any
 | 
						|
		-- unstaged files.
 | 
						|
		unlessM (isNothing <$> inRepo Git.Branch.current) $
 | 
						|
			unlessM (liftIO $ boolSystemEnv "git" [Param "checkout", Param "--", Param "."] usetmp) $
 | 
						|
				error "Failed to set up proxy work tree."
 | 
						|
		top <- fromRepo Git.repoPath
 | 
						|
		(fs, cleanup) <- inRepo $ Git.LsFiles.notInRepo True [top]
 | 
						|
		forM_ fs $ \f -> do
 | 
						|
			tf <- inRepo $ toTopFilePath f
 | 
						|
			let tmpf = tmp </> getTopFilePath tf
 | 
						|
			liftIO $ do
 | 
						|
				createDirectoryIfMissing True (takeDirectory tmpf)
 | 
						|
				createLinkOrCopy f tmpf
 | 
						|
		liftIO $ void cleanup
 | 
						|
 | 
						|
		liftIO $ safeSystemEnv c (map Param ps) usetmp
 | 
						|
		
 | 
						|
	-- To merge the changes made by the proxied command into
 | 
						|
	-- the work tree is similar to cleaning up after a
 | 
						|
	-- direct mode merge. But, here we force updates of any
 | 
						|
	-- non-annxed files that were changed by the proxied
 | 
						|
	-- command.
 | 
						|
	cleanupproxy tmp oldref = do
 | 
						|
		updateWorkTree tmp oldref True
 | 
						|
		liftIO $ removeDirectoryRecursive tmp
 |