initial export command
Very basic operation works, but of course this is only the beginning. This commit was sponsored by Nick Daly on Patreon.
This commit is contained in:
		
					parent
					
						
							
								cca2764f91
							
						
					
				
			
			
				commit
				
					
						9f3630f4e0
					
				
			
		
					 5 changed files with 121 additions and 1 deletions
				
			
		
							
								
								
									
										103
									
								
								Command/Export.hs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								Command/Export.hs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,103 @@
 | 
			
		|||
{- git-annex command
 | 
			
		||||
 -
 | 
			
		||||
 - Copyright 2017 Joey Hess <id@joeyh.name>
 | 
			
		||||
 -
 | 
			
		||||
 - Licensed under the GNU GPL version 3 or higher.
 | 
			
		||||
 -}
 | 
			
		||||
 | 
			
		||||
module Command.Export where
 | 
			
		||||
 | 
			
		||||
import Command
 | 
			
		||||
import qualified Git
 | 
			
		||||
import qualified Git.DiffTree
 | 
			
		||||
import Git.Sha
 | 
			
		||||
import Git.FilePath
 | 
			
		||||
import Types.Key
 | 
			
		||||
import Types.Remote
 | 
			
		||||
import Annex.Content
 | 
			
		||||
import Annex.CatFile
 | 
			
		||||
import Messages.Progress
 | 
			
		||||
import Utility.Tmp
 | 
			
		||||
 | 
			
		||||
import qualified Data.ByteString.Lazy as L
 | 
			
		||||
 | 
			
		||||
cmd :: Command
 | 
			
		||||
cmd = command "export" SectionCommon
 | 
			
		||||
	"export content to a remote"
 | 
			
		||||
	paramTreeish (seek <$$> optParser)
 | 
			
		||||
 | 
			
		||||
data ExportOptions = ExportOptions
 | 
			
		||||
	{ exportTreeish :: Git.Ref
 | 
			
		||||
	, exportRemote :: DeferredParse Remote
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
optParser :: CmdParamsDesc -> Parser ExportOptions
 | 
			
		||||
optParser _ = ExportOptions
 | 
			
		||||
	<$> (Git.Ref <$> parsetreeish)
 | 
			
		||||
	<*> (parseRemoteOption <$> parseToOption)
 | 
			
		||||
  where
 | 
			
		||||
	parsetreeish = argument str
 | 
			
		||||
		( metavar paramTreeish
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
seek :: ExportOptions -> CommandSeek
 | 
			
		||||
seek o = do
 | 
			
		||||
	r <- getParsed (exportRemote o)
 | 
			
		||||
	let oldtreeish = emptyTree -- XXX temporary
 | 
			
		||||
	(diff, cleanup) <- inRepo $
 | 
			
		||||
		Git.DiffTree.diffTreeRecursive oldtreeish (exportTreeish o)
 | 
			
		||||
	seekActions $ pure $ map (start r) diff
 | 
			
		||||
	void $ liftIO cleanup
 | 
			
		||||
 | 
			
		||||
start :: Remote -> Git.DiffTree.DiffTreeItem -> CommandStart
 | 
			
		||||
start r diff
 | 
			
		||||
	| Git.DiffTree.dstsha diff == nullSha = do
 | 
			
		||||
		showStart "unexport" f
 | 
			
		||||
		oldk <- either id id <$> exportKey (Git.DiffTree.srcsha diff)
 | 
			
		||||
		next $ performUnexport r oldk loc
 | 
			
		||||
	| otherwise = do
 | 
			
		||||
		showStart "export" f
 | 
			
		||||
		next $ performExport r diff loc
 | 
			
		||||
  where
 | 
			
		||||
	loc = ExportLocation $ toInternalGitPath $ 
 | 
			
		||||
		getTopFilePath $ Git.DiffTree.file diff
 | 
			
		||||
	f = getTopFilePath $ Git.DiffTree.file diff
 | 
			
		||||
 | 
			
		||||
performExport :: Remote -> Git.DiffTree.DiffTreeItem -> ExportLocation -> CommandPerform
 | 
			
		||||
performExport r diff loc = case storeExport r of
 | 
			
		||||
	Nothing -> error "remote does not support exporting files"
 | 
			
		||||
	Just storer -> next $ do
 | 
			
		||||
		v <- exportKey (Git.DiffTree.dstsha diff)
 | 
			
		||||
		case v of
 | 
			
		||||
			Right k -> metered Nothing k $ \m ->
 | 
			
		||||
				sendAnnex k
 | 
			
		||||
					(void $ performUnexport r k loc)
 | 
			
		||||
					(\f -> storer f k loc m)
 | 
			
		||||
			-- Sending a non-annexed file.
 | 
			
		||||
			Left sha1k -> metered Nothing sha1k $ \m ->
 | 
			
		||||
				withTmpFile "export" $ \tmp h -> do
 | 
			
		||||
					b <- catObject (Git.DiffTree.dstsha diff)
 | 
			
		||||
					liftIO $ L.hPut h b
 | 
			
		||||
					liftIO $ hClose h
 | 
			
		||||
					storer tmp sha1k loc m
 | 
			
		||||
 | 
			
		||||
performUnexport :: Remote -> Key -> ExportLocation -> CommandPerform
 | 
			
		||||
performUnexport r k loc = case removeExport r of
 | 
			
		||||
	Nothing -> error "remote does not support removing exported files"
 | 
			
		||||
	Just remover -> next $ remover k loc
 | 
			
		||||
 | 
			
		||||
-- When the Sha points to an annexed file, get the key as Right.
 | 
			
		||||
-- When the Sha points to a non-annexed file, convert to a SHA1 key,
 | 
			
		||||
-- as Left.
 | 
			
		||||
exportKey :: Git.Sha -> Annex (Either Key Key)
 | 
			
		||||
exportKey sha = mk <$> catKey sha
 | 
			
		||||
  where
 | 
			
		||||
	mk (Just k) = Right k
 | 
			
		||||
	mk Nothing = Left $ Key
 | 
			
		||||
		{ keyName = show sha
 | 
			
		||||
		, keyVariety = SHA1Key (HasExt False)
 | 
			
		||||
		, keySize = Nothing
 | 
			
		||||
		, keyMtime = Nothing
 | 
			
		||||
		, keyChunkSize = Nothing
 | 
			
		||||
		, keyChunkNum = Nothing
 | 
			
		||||
		}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue