import Utility.DirWatcher
import Utility.DirWatcher.Types
import qualified Remote
+import qualified Annex
import Annex.Perms
import Control.Concurrent
where
go _ Nothing = noop -- transfer already finished
go t (Just info) = do
- debug [ "transfer starting:", describeTransfer t info ]
+ qp <- liftAnnex $ coreQuotePath <$> Annex.getGitConfig
+ debug [ "transfer starting:", describeTransfer qp t info ]
r <- liftAnnex $ Remote.remoteFromUUID $ transferUUID t
updateTransferInfo t info { transferRemote = r }
import Types.Remote
import qualified Remote
import qualified Types.Remote as Remote
+import qualified Annex
import Annex.Wanted
import Utility.TList
| otherwise = go snocTList
where
go modlist = whenM (add modlist) $ do
- debug [ "queued", describeTransfer t info, ": " ++ reason ]
+ qp <- liftAnnex $ coreQuotePath <$> Annex.getGitConfig
+ debug [ "queued", describeTransfer qp t info, ": " ++ reason ]
notifyTransfer
add modlist = do
q <- getAssistant transferQueue
return Nothing
, ifM (liftAnnex $ shouldTransfer t info)
( do
- debug [ "Transferring:" , describeTransfer t info ]
+ qp <- liftAnnex $ coreQuotePath <$> Annex.getGitConfig
+ debug [ "Transferring:" , describeTransfer qp t info ]
notifyTransfer
let sd = remoteAnnexStallDetection
(Remote.gitconfig remote)
return $ Just (t, info, go remote sd)
, do
+ qp <- liftAnnex $ coreQuotePath <$> Annex.getGitConfig
debug [ "Skipping unnecessary transfer:",
- describeTransfer t info ]
+ describeTransfer qp t info ]
void $ removeTransfer t
finishedTransfer t (Just info)
return Nothing
Later (transferKey t) (associatedFile info) Upload
| otherwise = dodrops True
where
- dodrops fromhere = handleDrops
- ("drop wanted after " ++ describeTransfer t info)
- fromhere (transferKey t) (associatedFile info) []
+ dodrops fromhere = do
+ qp <- liftAnnex $ coreQuotePath <$> Annex.getGitConfig
+ handleDrops
+ ("drop wanted after " ++ describeTransfer qp t info)
+ fromhere (transferKey t) (associatedFile info) []
finishedTransfer _ _ = noop
{- Pause a running transfer. -}
+git-annex (10.20230408) UNRELEASED; urgency=medium
+
+ * Many commands now display filenames that contain unusual characters the
+ same way that git does, to avoid exposing control characters to the terminal.
+ * Support core.quotePath, which can be set to false to display utf8
+ characters as-is in filenames.
+
+ -- Joey Hess <id@joeyh.name> Sat, 08 Apr 2023 13:57:18 -0400
+
git-annex (10.20230407) upstream; urgency=medium
* Fix laziness bug introduced in last release that breaks use
Nothing -> go True Nothing
Just (Right verification) -> go True (Just (tmpfile, verification))
Just (Left _) -> do
- warning (decodeBS (actionItemDesc ai) ++ ": failed to download file from remote")
+ qp <- coreQuotePath <$> Annex.getGitConfig
+ warning (decodeBS (actionItemDesc qp ai) ++ ": failed to download file from remote")
void $ go True Nothing
return False
dispatch (Right False) = go False Nothing
return True
(False, True) -> do
fix InfoMissing
+ qp <- coreQuotePath <$> Annex.getGitConfig
warning $
"** Based on the location log, " ++
- decodeBS (actionItemDesc ai) ++
+ decodeBS (actionItemDesc qp ai) ++
"\n** was expected to be present, " ++
"but its content is missing."
return False
if null missinglocs
then return True
else do
+ qp <- coreQuotePath <$> Annex.getGitConfig
missingrequired <- Remote.prettyPrintUUIDs "missingrequired" missinglocs
warning $
"** Required content " ++
- decodeBS (actionItemDesc ai) ++
+ decodeBS (actionItemDesc qp ai) ++
" is missing from these repositories:\n" ++
missingrequired
return False
return same
badsize a b = do
msg <- bad key
+ qp <- coreQuotePath <$> Annex.getGitConfig
warning $ concat
- [ decodeBS (actionItemDesc ai)
+ [ decodeBS (actionItemDesc qp ai)
, ": Bad file size ("
, compareSizes storageUnits True a b
, "); "
checkKeyUpgrade backend key ai (AssociatedFile (Just file)) =
case Types.Backend.canUpgradeKey backend of
Just a | a key -> do
+ qp <- coreQuotePath <$> Annex.getGitConfig
warning $ concat
- [ decodeBS (actionItemDesc ai)
+ [ decodeBS (actionItemDesc qp ai)
, ": Can be upgraded to an improved key format. "
, "You can do so by running: git annex migrate --backend="
, decodeBS (formatKeyVariety (fromKey keyVariety key)) ++ " "
ok <- verifier key file
unless ok $ do
msg <- bad key
+ qp <- coreQuotePath <$> Annex.getGitConfig
warning $ concat
- [ decodeBS (actionItemDesc ai)
+ [ decodeBS (actionItemDesc qp ai)
, ": Bad file content; "
, msg
]
withTSDelta (liftIO . genInodeCache content) >>= \case
Nothing -> noop
Just ic' -> whenM (compareInodeCaches ic ic') $ do
+ qp <- coreQuotePath <$> Annex.getGitConfig
warning $ concat
- [ decodeBS (actionItemDesc ai)
+ [ decodeBS (actionItemDesc qp ai)
, ": Stale or missing inode cache; updating."
]
Database.Keys.addInodeCaches key [ic]
uuidmap <- Remote.remoteMap id
ts <- getTransfers
maybeShowJSON $ JSONChunk [(desc, V.fromList $ map (uncurry jsonify) ts)]
+ qp <- coreQuotePath <$> Annex.getGitConfig
return $ if null ts
then "none"
else multiLine $
- map (uncurry $ line uuidmap) $ sort ts
+ map (uncurry $ line qp uuidmap) $ sort ts
where
desc = "transfers in progress"
- line uuidmap t i = unwords
+ line qp uuidmap t i = unwords
[ fromRawFilePath (formatDirection (transferDirection t)) ++ "ing"
- , fromRawFilePath $ actionItemDesc $ mkActionItem
+ , fromRawFilePath $ actionItemDesc qp $ mkActionItem
(transferKey t, associatedFile i)
, if transferDirection t == Upload then "to" else "from"
, maybe (fromUUID $ transferUUID t) Remote.name $
import Common
import Git
+import qualified Git.Filename as Filename
import qualified System.FilePath.ByteString as P
import qualified System.FilePath.Posix.ByteString
deriving (Show, Eq, Ord)
{- Git uses the branch:file form to refer to a BranchFilePath -}
-descBranchFilePath :: BranchFilePath -> S.ByteString
-descBranchFilePath (BranchFilePath b f) =
- fromRef' b <> ":" <> getTopFilePath f
+descBranchFilePath :: Filename.QuotePath -> BranchFilePath -> S.ByteString
+descBranchFilePath qp (BranchFilePath b f) =
+ fromRef' b <> ":" <> Filename.encode qp (getTopFilePath f)
{- Path to a TopFilePath, within the provided git repo. -}
fromTopFilePath :: TopFilePath -> Git.Repo -> RawFilePath
import Types.ActionItem
import Annex.Common
import qualified Git
+import qualified Git.Filename
import Utility.Metered
import Utility.Percentage
import Utility.PID
import qualified Data.ByteString.Char8 as B8
import qualified System.FilePath.ByteString as P
-describeTransfer :: Transfer -> TransferInfo -> String
-describeTransfer t info = unwords
+describeTransfer :: Git.Filename.QuotePath -> Transfer -> TransferInfo -> String
+describeTransfer qp t info = unwords
[ show $ transferDirection t
, show $ transferUUID t
- , decodeBS $ actionItemDesc $ ActionItemAssociatedFile
+ , decodeBS $ actionItemDesc qp $ ActionItemAssociatedFile
(associatedFile info)
(transferKey t)
, show $ bytesComplete info
{- git-annex output messages
-
- - Copyright 2010-2021 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2023 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
import Types.ActionItem
import Types.Concurrency
import Types.Command (StartMessage(..), SeekInput)
-import Types.Transfer (transferKey)
import Messages.Internal
import Messages.Concurrent
import Annex.Debug
where
json = JSON.start command (Just file) Nothing si
-showStartKey :: String -> Key -> ActionItem -> SeekInput -> Annex ()
-showStartKey command key ai si = outputMessage json $
- encodeBS command <> " " <> actionItemDesc ai <> " "
+showStartActionItem :: String -> ActionItem -> SeekInput -> Annex ()
+showStartActionItem command ai si = do
+ qp <- coreQuotePath <$> Annex.getGitConfig
+ outputMessage json $
+ encodeBS command <> " " <> actionItemDesc qp ai <> " "
where
- json = JSON.start command (actionItemFile ai) (Just key) si
+ json = JSON.start command (actionItemFile ai) (actionItemKey ai) si
showStartOther :: String -> Maybe String -> SeekInput -> Annex ()
showStartOther command mdesc si = outputMessage json $ encodeBS $
showStartMessage :: StartMessage -> Annex ()
showStartMessage (StartMessage command ai si) = case ai of
- ActionItemAssociatedFile _ k -> showStartKey command k ai si
- ActionItemKey k -> showStartKey command k ai si
- ActionItemBranchFilePath _ k -> showStartKey command k ai si
- ActionItemFailedTransfer t _ -> showStartKey command (transferKey t) ai si
- ActionItemTreeFile file -> showStart command file si
+ ActionItemAssociatedFile _ _ -> showStartActionItem command ai si
+ ActionItemKey _ -> showStartActionItem command ai si
+ ActionItemBranchFilePath _ _ -> showStartActionItem command ai si
+ ActionItemFailedTransfer _ _ -> showStartActionItem command ai si
+ ActionItemTreeFile _ -> showStartActionItem command ai si
ActionItemOther msg -> showStartOther command msg si
OnlyActionOn _ ai' -> showStartMessage (StartMessage command ai' si)
showStartMessage (StartUsualMessages command ai si) = do
{- Performs an action that outputs nonstandard/customized output, and
- in JSON mode wraps its output in JSON.start and JSON.end, so it's
- a complete JSON document.
- - This is only needed when showStart and showEndOk is not used.
+ - This is only needed when showStart* and showEndOk is not used.
-}
showCustom :: String -> SeekInput -> Annex Bool -> Annex ()
showCustom command si a = do
{- items that a command can act on
-
- - Copyright 2016-2019 Joey Hess <id@joeyh.name>
+ - Copyright 2016-2023 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
import Key
import Types.Transfer
import Git.FilePath
+import qualified Git.Filename
import Utility.FileSystemEncoding
import Data.Maybe
instance MkActionItem (Transfer, TransferInfo) where
mkActionItem = uncurry ActionItemFailedTransfer
-actionItemDesc :: ActionItem -> S.ByteString
-actionItemDesc (ActionItemAssociatedFile (AssociatedFile (Just f)) _) = f
-actionItemDesc (ActionItemAssociatedFile (AssociatedFile Nothing) k) =
+actionItemDesc :: Git.Filename.QuotePath -> ActionItem -> S.ByteString
+actionItemDesc qp (ActionItemAssociatedFile (AssociatedFile (Just f)) _) =
+ Git.Filename.encode qp f
+actionItemDesc _ (ActionItemAssociatedFile (AssociatedFile Nothing) k) =
serializeKey' k
-actionItemDesc (ActionItemKey k) = serializeKey' k
-actionItemDesc (ActionItemBranchFilePath bfp _) = descBranchFilePath bfp
-actionItemDesc (ActionItemFailedTransfer t i) = actionItemDesc $
+actionItemDesc _ (ActionItemKey k) = serializeKey' k
+actionItemDesc qp (ActionItemBranchFilePath bfp _) = descBranchFilePath qp bfp
+actionItemDesc qp (ActionItemFailedTransfer t i) = actionItemDesc qp $
ActionItemAssociatedFile (associatedFile i) (transferKey t)
-actionItemDesc (ActionItemTreeFile f) = f
-actionItemDesc (ActionItemOther s) = encodeBS (fromMaybe "" s)
-actionItemDesc (OnlyActionOn _ ai) = actionItemDesc ai
+actionItemDesc qp (ActionItemTreeFile f) = Git.Filename.encode qp f
+actionItemDesc _ (ActionItemOther s) = encodeBS (fromMaybe "" s)
+actionItemDesc qp (OnlyActionOn _ ai) = actionItemDesc qp ai
actionItemKey :: ActionItem -> Maybe Key
actionItemKey (ActionItemAssociatedFile _ k) = Just k
import Git.ConfigTypes
import Git.Remote (isRemoteKey, remoteKeyToRemoteName)
import Git.Branch (CommitMode(..))
+import Git.Filename (QuotePath(..))
import Utility.DataUnits
import Config.Cost
import Types.UUID
, annexSupportUnlocked :: Bool
, coreSymlinks :: Bool
, coreSharedRepository :: SharedRepository
+ , coreQuotePath :: QuotePath
, receiveDenyCurrentBranch :: DenyCurrentBranch
, gcryptId :: Maybe String
, gpgCmd :: GpgCmd
, annexSupportUnlocked = getbool (annexConfig "supportunlocked") True
, coreSymlinks = getbool "core.symlinks" True
, coreSharedRepository = getSharedRepository r
+ , coreQuotePath = QuotePath (getbool "core.quotepath" True)
, receiveDenyCurrentBranch = getDenyCurrentBranch r
, gcryptId = getmaybe "core.gcrypt-id"
, gpgCmd = mkGpgCmd (getmaybe "gpg.program")