2010-11-02 23:04:24 +00:00
|
|
|
{- git-annex command
|
|
|
|
-
|
2022-06-14 20:38:34 +00:00
|
|
|
- Copyright 2010-2022 Joey Hess <id@joeyh.name>
|
2010-11-02 23:04:24 +00:00
|
|
|
-
|
2019-03-13 19:48:14 +00:00
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
2010-11-02 23:04:24 +00:00
|
|
|
-}
|
|
|
|
|
2023-04-10 16:56:45 +00:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
|
2010-11-02 23:04:24 +00:00
|
|
|
module Command.Add where
|
|
|
|
|
|
|
|
import Command
|
2015-12-22 17:23:33 +00:00
|
|
|
import Annex.Ingest
|
2011-10-15 20:21:08 +00:00
|
|
|
import Logs.Location
|
2011-10-04 04:40:47 +00:00
|
|
|
import Annex.Content
|
fully support core.symlinks=false in all relevant symlink handling code
Refactored annex link code into nice clean new library.
Audited and dealt with calls to createSymbolicLink.
Remaining calls are all safe, because:
Annex/Link.hs: ( liftIO $ createSymbolicLink linktarget file
only when core.symlinks=true
Assistant/WebApp/Configurators/Local.hs: createSymbolicLink link link
test if symlinks can be made
Command/Fix.hs: liftIO $ createSymbolicLink link file
command only works in indirect mode
Command/FromKey.hs: liftIO $ createSymbolicLink link file
command only works in indirect mode
Command/Indirect.hs: liftIO $ createSymbolicLink l f
refuses to run if core.symlinks=false
Init.hs: createSymbolicLink f f2
test if symlinks can be made
Remote/Directory.hs: go [file] = catchBoolIO $ createSymbolicLink file f >> return True
fast key linking; catches failure to make symlink and falls back to copy
Remote/Git.hs: liftIO $ catchBoolIO $ createSymbolicLink loc file >> return True
ditto
Upgrade/V1.hs: liftIO $ createSymbolicLink link f
v1 repos could not be on a filesystem w/o symlinks
Audited and dealt with calls to readSymbolicLink.
Remaining calls are all safe, because:
Annex/Link.hs: ( liftIO $ catchMaybeIO $ readSymbolicLink file
only when core.symlinks=true
Assistant/Threads/Watcher.hs: ifM ((==) (Just link) <$> liftIO (catchMaybeIO $ readSymbolicLink file))
code that fixes real symlinks when inotify sees them
It's ok to not fix psdueo-symlinks.
Assistant/Threads/Watcher.hs: mlink <- liftIO (catchMaybeIO $ readSymbolicLink file)
ditto
Command/Fix.hs: stopUnless ((/=) (Just link) <$> liftIO (catchMaybeIO $ readSymbolicLink file)) $ do
command only works in indirect mode
Upgrade/V1.hs: getsymlink = takeFileName <$> readSymbolicLink file
v1 repos could not be on a filesystem w/o symlinks
Audited and dealt with calls to isSymbolicLink.
(Typically used with getSymbolicLinkStatus, but that is just used because
getFileStatus is not as robust; it also works on pseudolinks.)
Remaining calls are all safe, because:
Assistant/Threads/SanityChecker.hs: | isSymbolicLink s -> addsymlink file ms
only handles staging of symlinks that were somehow not staged
(might need to be updated to support pseudolinks, but this is
only a belt-and-suspenders check anyway, and I've never seen the code run)
Command/Add.hs: if isSymbolicLink s || not (isRegularFile s)
avoids adding symlinks to the annex, so not relevant
Command/Indirect.hs: | isSymbolicLink s -> void $ flip whenAnnexed f $
only allowed on systems that support symlinks
Command/Indirect.hs: whenM (liftIO $ not . isSymbolicLink <$> getSymbolicLinkStatus f) $ do
ditto
Seek.hs:notSymlink f = liftIO $ not . isSymbolicLink <$> getSymbolicLinkStatus f
used to find unlocked files, only relevant in indirect mode
Utility/FSEvents.hs: | Files.isSymbolicLink s = runhook addSymlinkHook $ Just s
Utility/FSEvents.hs: | Files.isSymbolicLink s ->
Utility/INotify.hs: | Files.isSymbolicLink s ->
Utility/INotify.hs: checkfiletype Files.isSymbolicLink addSymlinkHook f
Utility/Kqueue.hs: | Files.isSymbolicLink s = callhook addSymlinkHook (Just s) change
all above are lower-level, not relevant
Audited and dealt with calls to isSymLink.
Remaining calls are all safe, because:
Annex/Direct.hs: | isSymLink (getmode item) =
This is looking at git diff-tree objects, not files on disk
Command/Unused.hs: | isSymLink (LsTree.mode l) = do
This is looking at git ls-tree, not file on disk
Utility/FileMode.hs:isSymLink :: FileMode -> Bool
Utility/FileMode.hs:isSymLink = checkMode symbolicLinkMode
low-level
Done!!
2013-02-17 19:05:55 +00:00
|
|
|
import qualified Annex
|
|
|
|
import qualified Annex.Queue
|
2016-01-20 20:36:33 +00:00
|
|
|
import qualified Database.Keys
|
2013-03-29 20:17:13 +00:00
|
|
|
import Annex.FileMatcher
|
2016-05-16 19:30:40 +00:00
|
|
|
import Annex.Link
|
2019-05-07 17:04:39 +00:00
|
|
|
import Annex.Tmp
|
2022-06-14 20:38:34 +00:00
|
|
|
import Annex.HashObject
|
2022-10-26 17:58:20 +00:00
|
|
|
import Annex.WorkTree
|
2019-06-25 17:12:47 +00:00
|
|
|
import Messages.Progress
|
2016-05-16 19:30:40 +00:00
|
|
|
import Git.FilePath
|
2022-06-14 20:38:34 +00:00
|
|
|
import Git.Types
|
|
|
|
import Git.UpdateIndex
|
2019-12-26 20:24:40 +00:00
|
|
|
import Config.GitConfig
|
Added --no-check-gitignore option for finer grained control than using --force.
add, addurl, importfeed, import: Added --no-check-gitignore option
for finer grained control than using --force.
(--force is used for too many different things, and at least one
of these also uses it for something else. I would like to reduce
--force's footprint until it only forces drops or a few other data
losses. For now, --force still disables checking ignores too.)
addunused: Don't check .gitignores when adding files. This is a behavior
change, but I justify it by analogy with git add of a gitignored file
adding it, asking to add all unused files back should add them all back,
not skip some. The old behavior was surprising.
In Command.Lock and Command.ReKey, CheckGitIgnore False does not change
behavior, it only makes explicit what is done. Since these commands are run
on annexed files, the file is already checked into git, so git add won't
check ignores.
2020-09-18 17:12:04 +00:00
|
|
|
import Utility.OptParse
|
smudge: check for known annexed inodes before checking annex.largefiles
smudge: Fix a case where an unlocked annexed file that annex.largefiles
does not match could get its unchanged content checked into git, due to git
running the smudge filter unecessarily.
When the file has the same inodecache as an already annexed file,
we can assume that the user is not intending to change how it's stored in
git.
Note that checkunchangedgitfile already handled the inverse case, where the
file was added to git previously. That goes further and actually sha1
hashes the new file and checks if it's the same hash in the index.
It would be possible to generate a key for the file and see if it's the
same as the old key, however that could be considerably more expensive than
sha1 of a small file is, and it is not necessary for the case I have, at
least, where the file is not modified or touched, and so its inode will
match the cache.
git-annex add was changed, when adding a small file, to remove the inode
cache for it. This is necessary to keep the recipe in
doc/tips/largefiles.mdwn for converting from annex to git working.
It also avoids bugs/case_where_using_pathspec_with_git-commit_leaves_s.mdwn
which the earlier try at this change introduced.
2021-05-10 17:05:08 +00:00
|
|
|
import Utility.InodeCache
|
|
|
|
import Annex.InodeSentinal
|
fix add overwrite race with git-annex add to annex
This is not a complete fix for all such races, only the one where a
large file gets changed while adding and gets added to git rather than
to the annex.
addLink needs to go away, any caller of it is probably subject to the
same kind of race. (Also, addLink itself fails to check gitignore when
symlinks are not supported.)
ingestAdd no longer checks gitignore. (It didn't check it consistently
before either, since there were cases where it did not run git add!)
When git-annex import calls it, it's already checked gitignore itself
earlier. When git-annex add calls it, it's usually on files found
by withFilesNotInGit, which handles checking ignores.
There was one other case, when git-annex add --batch calls it. In that
case, old git-annex behaved rather badly, it would seem to add the file,
but git add would later fail, leaving the file as an unstaged annex symlink.
That behavior has also been fixed.
Sponsored-by: Brett Eisenberg on Patreon
2022-06-14 17:20:42 +00:00
|
|
|
import Annex.CheckIgnore
|
2019-12-06 19:37:12 +00:00
|
|
|
import qualified Utility.RawFilePath as R
|
2022-06-22 20:47:34 +00:00
|
|
|
import qualified System.FilePath.ByteString as P
|
2010-11-02 23:04:24 +00:00
|
|
|
|
2023-03-01 19:55:58 +00:00
|
|
|
import System.PosixCompat.Files (fileSize, isSymbolicLink, isRegularFile, modificationTime, fileID, deviceID, fileMode, ownerExecuteMode, intersectFileModes)
|
2022-06-14 20:38:34 +00:00
|
|
|
|
2015-07-08 16:33:27 +00:00
|
|
|
cmd :: Command
|
2018-02-19 18:28:17 +00:00
|
|
|
cmd = notBareRepo $
|
2022-06-29 17:28:08 +00:00
|
|
|
withAnnexOptions opts $
|
2018-02-19 18:28:17 +00:00
|
|
|
command "add" SectionCommon "add files to annex"
|
|
|
|
paramPaths (seek <$$> optParser)
|
2020-10-19 19:36:18 +00:00
|
|
|
where
|
|
|
|
opts =
|
2022-06-29 17:28:08 +00:00
|
|
|
[ backendOption
|
|
|
|
, jobsOption
|
2020-10-19 19:36:18 +00:00
|
|
|
, jsonOptions
|
|
|
|
, jsonProgressOption
|
|
|
|
, fileMatchingOptions LimitDiskFiles
|
|
|
|
]
|
2015-02-06 21:08:14 +00:00
|
|
|
|
2015-07-10 17:18:46 +00:00
|
|
|
data AddOptions = AddOptions
|
|
|
|
{ addThese :: CmdParams
|
2016-01-19 21:46:46 +00:00
|
|
|
, batchOption :: BatchMode
|
2017-04-07 19:55:34 +00:00
|
|
|
, updateOnly :: Bool
|
2020-01-01 18:03:06 +00:00
|
|
|
, largeFilesOverride :: Maybe Bool
|
Added --no-check-gitignore option for finer grained control than using --force.
add, addurl, importfeed, import: Added --no-check-gitignore option
for finer grained control than using --force.
(--force is used for too many different things, and at least one
of these also uses it for something else. I would like to reduce
--force's footprint until it only forces drops or a few other data
losses. For now, --force still disables checking ignores too.)
addunused: Don't check .gitignores when adding files. This is a behavior
change, but I justify it by analogy with git add of a gitignored file
adding it, asking to add all unused files back should add them all back,
not skip some. The old behavior was surprising.
In Command.Lock and Command.ReKey, CheckGitIgnore False does not change
behavior, it only makes explicit what is done. Since these commands are run
on annexed files, the file is already checked into git, so git add won't
check ignores.
2020-09-18 17:12:04 +00:00
|
|
|
, checkGitIgnoreOption :: CheckGitIgnore
|
2022-08-03 15:16:04 +00:00
|
|
|
, dryRunOption :: DryRun
|
2015-07-10 17:18:46 +00:00
|
|
|
}
|
2014-03-26 18:52:07 +00:00
|
|
|
|
2015-07-10 17:18:46 +00:00
|
|
|
optParser :: CmdParamsDesc -> Parser AddOptions
|
|
|
|
optParser desc = AddOptions
|
|
|
|
<$> cmdParams desc
|
2021-08-25 18:20:33 +00:00
|
|
|
<*> parseBatchOption False
|
2017-04-07 19:55:34 +00:00
|
|
|
<*> switch
|
|
|
|
( long "update"
|
|
|
|
<> short 'u'
|
|
|
|
<> help "only update tracked files"
|
|
|
|
)
|
2020-01-01 18:03:06 +00:00
|
|
|
<*> (parseforcelarge <|> parseforcesmall)
|
Added --no-check-gitignore option for finer grained control than using --force.
add, addurl, importfeed, import: Added --no-check-gitignore option
for finer grained control than using --force.
(--force is used for too many different things, and at least one
of these also uses it for something else. I would like to reduce
--force's footprint until it only forces drops or a few other data
losses. For now, --force still disables checking ignores too.)
addunused: Don't check .gitignores when adding files. This is a behavior
change, but I justify it by analogy with git add of a gitignored file
adding it, asking to add all unused files back should add them all back,
not skip some. The old behavior was surprising.
In Command.Lock and Command.ReKey, CheckGitIgnore False does not change
behavior, it only makes explicit what is done. Since these commands are run
on annexed files, the file is already checked into git, so git add won't
check ignores.
2020-09-18 17:12:04 +00:00
|
|
|
<*> checkGitIgnoreSwitch
|
2022-08-03 15:16:04 +00:00
|
|
|
<*> parseDryRunOption
|
2020-01-01 18:03:06 +00:00
|
|
|
where
|
|
|
|
parseforcelarge = flag Nothing (Just True)
|
|
|
|
( long "force-large"
|
|
|
|
<> help "add all files to annex, ignoring other configuration"
|
|
|
|
)
|
|
|
|
parseforcesmall = flag Nothing (Just False)
|
|
|
|
( long "force-small"
|
|
|
|
<> help "add all files to git, ignoring other configuration"
|
|
|
|
)
|
2010-12-30 18:19:16 +00:00
|
|
|
|
Added --no-check-gitignore option for finer grained control than using --force.
add, addurl, importfeed, import: Added --no-check-gitignore option
for finer grained control than using --force.
(--force is used for too many different things, and at least one
of these also uses it for something else. I would like to reduce
--force's footprint until it only forces drops or a few other data
losses. For now, --force still disables checking ignores too.)
addunused: Don't check .gitignores when adding files. This is a behavior
change, but I justify it by analogy with git add of a gitignored file
adding it, asking to add all unused files back should add them all back,
not skip some. The old behavior was surprising.
In Command.Lock and Command.ReKey, CheckGitIgnore False does not change
behavior, it only makes explicit what is done. Since these commands are run
on annexed files, the file is already checked into git, so git add won't
check ignores.
2020-09-18 17:12:04 +00:00
|
|
|
checkGitIgnoreSwitch :: Parser CheckGitIgnore
|
|
|
|
checkGitIgnoreSwitch = CheckGitIgnore <$>
|
|
|
|
invertableSwitch "check-gitignore" True
|
|
|
|
(help "Do not check .gitignore when adding files")
|
|
|
|
|
2015-07-10 17:18:46 +00:00
|
|
|
seek :: AddOptions -> CommandSeek
|
git-annex assist
assist: New command, which is the same as git-annex sync but with
new files added and content transferred by default.
(Also this fixes another reversion in git-annex sync,
--commit --no-commit, and --message were not enabled, oops.)
See added comment for why git-annex assist does commit staged
changes elsewhere in the work tree, but only adds files under
the cwd.
Note that it does not support --no-commit, --no-push, --no-pull
like sync does. My thinking is, why should it? If you want that
level of control, use git commit, git annex push, git annex pull.
Sync only got those options because pull and push were not split
out.
Sponsored-by: k0ld on Patreon
2023-05-18 18:37:29 +00:00
|
|
|
seek o = startConcurrency commandStages (seek' o)
|
|
|
|
|
|
|
|
seek' :: AddOptions -> CommandSeek
|
|
|
|
seek' o = do
|
2019-12-20 19:01:34 +00:00
|
|
|
largematcher <- largeFilesMatcher
|
|
|
|
addunlockedmatcher <- addUnlockedMatcher
|
2019-12-26 20:24:40 +00:00
|
|
|
annexdotfiles <- getGitConfigVal annexDotFiles
|
2022-03-21 19:50:27 +00:00
|
|
|
let gofile includingsmall (si, file) = case largeFilesOverride o of
|
2022-08-19 16:49:17 +00:00
|
|
|
Nothing -> ifM (pure (annexdotfiles || not (dotfile file))
|
|
|
|
<&&> (checkFileMatcher largematcher file
|
|
|
|
<||> Annex.getRead Annex.force))
|
|
|
|
( start dr si file addunlockedmatcher
|
|
|
|
, if includingsmall
|
|
|
|
then ifM (annexAddSmallFiles <$> Annex.getGitConfig)
|
|
|
|
( startSmall dr si file
|
|
|
|
, stop
|
|
|
|
)
|
|
|
|
else stop
|
|
|
|
)
|
2022-08-03 15:16:04 +00:00
|
|
|
Just True -> start dr si file addunlockedmatcher
|
|
|
|
Just False -> startSmallOverridden dr si file
|
2016-01-19 21:46:46 +00:00
|
|
|
case batchOption o of
|
added -z
Added -z option to git-annex commands that use --batch, useful for
supporting filenames containing newlines.
It only controls input to --batch, the output will still be line delimited
unless --json or etc is used to get some other output. While git often
makes -z affect both input and output, I don't like trying them together,
and making it affect output would have been a significant complication,
and also git-annex output is generally not intended to be machine parsed,
unless using --json or a format option.
Commands that take pairs like "file key" still separate them with a space
in --batch mode. All such commands take care to support filenames with
spaces when parsing that, so there was no need to change it, and it would
have needed significant changes to the batch machinery to separate tose
with a null.
To make fromkey and registerurl support -z, I had to give them a --batch
option. The implicit batch mode they enter when not provided with input
parameters does not support -z as that would have complicated option
parsing. Seemed better to move these toward using the same --batch as
everything else, though the implicit batch mode can still be used.
This commit was sponsored by Ole-Morten Duesund on Patreon.
2018-09-20 20:09:21 +00:00
|
|
|
Batch fmt
|
2017-04-07 19:55:34 +00:00
|
|
|
| updateOnly o ->
|
|
|
|
giveup "--update --batch is not supported"
|
2022-01-26 16:59:55 +00:00
|
|
|
| otherwise -> batchOnly Nothing (addThese o) $
|
fix add overwrite race with git-annex add to annex
This is not a complete fix for all such races, only the one where a
large file gets changed while adding and gets added to git rather than
to the annex.
addLink needs to go away, any caller of it is probably subject to the
same kind of race. (Also, addLink itself fails to check gitignore when
symlinks are not supported.)
ingestAdd no longer checks gitignore. (It didn't check it consistently
before either, since there were cases where it did not run git add!)
When git-annex import calls it, it's already checked gitignore itself
earlier. When git-annex add calls it, it's usually on files found
by withFilesNotInGit, which handles checking ignores.
There was one other case, when git-annex add --batch calls it. In that
case, old git-annex behaved rather badly, it would seem to add the file,
but git add would later fail, leaving the file as an unstaged annex symlink.
That behavior has also been fixed.
Sponsored-by: Brett Eisenberg on Patreon
2022-06-14 17:20:42 +00:00
|
|
|
batchFiles fmt $ \v@(_si, file) ->
|
|
|
|
ifM (checkIgnored (checkGitIgnoreOption o) file)
|
|
|
|
( stop
|
|
|
|
, gofile True v
|
|
|
|
)
|
2016-01-19 21:46:46 +00:00
|
|
|
NoBatch -> do
|
2020-05-28 19:55:17 +00:00
|
|
|
-- Avoid git ls-files complaining about files that
|
|
|
|
-- are not known to git yet, since this will add
|
|
|
|
-- them. Instead, have workTreeItems warn about other
|
|
|
|
-- problems, like files that don't exist.
|
2023-04-25 23:26:20 +00:00
|
|
|
let ww = WarnUnmatchWorkTreeItems "add"
|
2020-05-28 19:55:17 +00:00
|
|
|
l <- workTreeItems ww (addThese o)
|
2022-03-21 19:50:27 +00:00
|
|
|
let go b a = a ww (commandAction . gofile b) l
|
2017-04-07 19:55:34 +00:00
|
|
|
unless (updateOnly o) $
|
2022-03-21 19:50:27 +00:00
|
|
|
go True (withFilesNotInGit (checkGitIgnoreOption o))
|
|
|
|
go True withFilesMaybeModified
|
|
|
|
-- Convert newly unlocked files back to locked files,
|
|
|
|
-- same as a modified unlocked file would get
|
|
|
|
-- locked when added.
|
|
|
|
go False withUnmodifiedUnlockedPointers
|
2022-08-03 15:16:04 +00:00
|
|
|
where
|
|
|
|
dr = dryRunOption o
|
2010-11-11 22:54:52 +00:00
|
|
|
|
2015-04-08 20:14:23 +00:00
|
|
|
{- Pass file off to git-add. -}
|
2022-08-19 16:49:17 +00:00
|
|
|
startSmall :: DryRun -> SeekInput -> RawFilePath -> CommandStart
|
|
|
|
startSmall dr si file =
|
|
|
|
liftIO (catchMaybeIO $ R.getSymbolicLinkStatus file) >>= \case
|
|
|
|
Just s ->
|
|
|
|
starting "add" (ActionItemTreeFile file) si $
|
|
|
|
addSmall dr file s
|
|
|
|
Nothing -> stop
|
2015-12-02 18:48:42 +00:00
|
|
|
|
2022-08-03 15:16:04 +00:00
|
|
|
addSmall :: DryRun -> RawFilePath -> FileStatus -> CommandPerform
|
|
|
|
addSmall dr file s = do
|
2015-04-08 20:16:42 +00:00
|
|
|
showNote "non-large file; adding content to git repository"
|
2022-08-03 15:16:04 +00:00
|
|
|
skipWhenDryRun dr $ next $ addFile Small file s
|
2015-07-07 20:15:30 +00:00
|
|
|
|
2022-08-03 15:16:04 +00:00
|
|
|
startSmallOverridden :: DryRun -> SeekInput -> RawFilePath -> CommandStart
|
|
|
|
startSmallOverridden dr si file =
|
2022-06-14 20:38:34 +00:00
|
|
|
liftIO (catchMaybeIO $ R.getSymbolicLinkStatus file) >>= \case
|
2022-08-03 15:16:04 +00:00
|
|
|
Just s -> starting "add" (ActionItemTreeFile file) si $ do
|
2022-06-14 20:38:34 +00:00
|
|
|
showNote "adding content to git repository"
|
2022-08-03 15:16:04 +00:00
|
|
|
skipWhenDryRun dr $ next $ addFile Small file s
|
2022-06-14 20:38:34 +00:00
|
|
|
Nothing -> stop
|
2020-01-01 18:03:06 +00:00
|
|
|
|
2021-01-04 17:12:28 +00:00
|
|
|
data SmallOrLarge = Small | Large
|
2020-01-01 18:03:06 +00:00
|
|
|
|
2022-06-14 20:38:34 +00:00
|
|
|
addFile :: SmallOrLarge -> RawFilePath -> FileStatus -> Annex Bool
|
|
|
|
addFile smallorlarge file s = do
|
|
|
|
sha <- if isSymbolicLink s
|
|
|
|
then hashBlob =<< liftIO (R.readSymbolicLink file)
|
|
|
|
else if isRegularFile s
|
|
|
|
then hashFile file
|
2023-04-10 16:56:45 +00:00
|
|
|
else do
|
|
|
|
qp <- coreQuotePath <$> Annex.getGitConfig
|
|
|
|
giveup $ decodeBS $ quote qp $
|
|
|
|
file <> " is not a regular file"
|
2022-06-14 20:38:34 +00:00
|
|
|
let treetype = if isSymbolicLink s
|
|
|
|
then TreeSymlink
|
|
|
|
else if intersectFileModes ownerExecuteMode (fileMode s) /= 0
|
|
|
|
then TreeExecutable
|
|
|
|
else TreeFile
|
|
|
|
s' <- liftIO $ catchMaybeIO $ R.getSymbolicLinkStatus file
|
|
|
|
if maybe True (changed s) s'
|
|
|
|
then do
|
filter out control characters in warning messages
Converted warning and similar to use StringContainingQuotedPath. Most
warnings are static strings, some do refer to filepaths that need to be
quoted, and others don't need quoting.
Note that, since quote filters out control characters of even
UnquotedString, this makes all warnings safe, even when an attacker
sneaks in a control character in some other way.
When json is being output, no quoting is done, since json gets its own
quoting.
This does, as a side effect, make warning messages in json output not
be indented. The indentation is only needed to offset warning messages
underneath the display of the file they apply to, so that's ok.
Sponsored-by: Brett Eisenberg on Patreon
2023-04-10 18:47:32 +00:00
|
|
|
warning $ QuotedPath file <> " changed while it was being added"
|
2022-06-14 20:38:34 +00:00
|
|
|
return False
|
|
|
|
else do
|
|
|
|
case smallorlarge of
|
|
|
|
-- In case the file is being converted from
|
|
|
|
-- an annexed file to be stored in git,
|
|
|
|
-- remove the cached inode, so that if the
|
|
|
|
-- smudge clean filter later runs on the file,
|
|
|
|
-- it will not remember it was annexed.
|
|
|
|
Small -> maybe noop Database.Keys.removeInodeCache
|
|
|
|
=<< withTSDelta (liftIO . genInodeCache file)
|
|
|
|
Large -> noop
|
|
|
|
Annex.Queue.addUpdateIndex =<<
|
2023-02-27 19:02:53 +00:00
|
|
|
inRepo (stageFile sha treetype file)
|
2022-06-14 20:38:34 +00:00
|
|
|
return True
|
2012-11-12 05:05:04 +00:00
|
|
|
where
|
2022-06-14 20:38:34 +00:00
|
|
|
changed a b =
|
|
|
|
deviceID a /= deviceID b ||
|
|
|
|
fileID a /= fileID b ||
|
|
|
|
fileSize a /= fileSize b ||
|
|
|
|
modificationTime a /= modificationTime b ||
|
|
|
|
isRegularFile a /= isRegularFile b ||
|
|
|
|
isSymbolicLink a /= isSymbolicLink b
|
|
|
|
|
2022-08-03 15:16:04 +00:00
|
|
|
start :: DryRun -> SeekInput -> RawFilePath -> AddUnlockedMatcher -> CommandStart
|
|
|
|
start dr si file addunlockedmatcher =
|
2022-06-14 20:38:34 +00:00
|
|
|
liftIO (catchMaybeIO $ R.getSymbolicLinkStatus file) >>= \case
|
2017-12-05 19:00:50 +00:00
|
|
|
Nothing -> stop
|
2022-06-14 20:38:34 +00:00
|
|
|
Just s
|
2017-12-05 19:00:50 +00:00
|
|
|
| not (isRegularFile s) && not (isSymbolicLink s) -> stop
|
2022-06-14 20:38:34 +00:00
|
|
|
| otherwise -> do
|
|
|
|
mk <- liftIO $ isPointerFile file
|
|
|
|
maybe (go s) (fixuppointer s) mk
|
|
|
|
where
|
2022-10-26 17:58:20 +00:00
|
|
|
go s = lookupKey file >>= \case
|
|
|
|
Just k -> addpresent s k
|
|
|
|
Nothing -> add s
|
2022-06-14 20:38:34 +00:00
|
|
|
add s = starting "add" (ActionItemTreeFile file) si $
|
2022-08-03 15:16:04 +00:00
|
|
|
skipWhenDryRun dr $
|
|
|
|
if isSymbolicLink s
|
|
|
|
then next $ addFile Small file s
|
|
|
|
else perform file addunlockedmatcher
|
2022-06-14 20:38:34 +00:00
|
|
|
addpresent s key
|
|
|
|
| isSymbolicLink s = fixuplink key
|
|
|
|
| otherwise = add s
|
2020-11-10 16:10:51 +00:00
|
|
|
fixuplink key =
|
2021-03-12 18:09:19 +00:00
|
|
|
starting "add" (ActionItemTreeFile file) si $
|
2022-06-14 17:56:17 +00:00
|
|
|
addingExistingLink file key $
|
2022-08-03 15:16:04 +00:00
|
|
|
skipWhenDryRun dr $ withOtherTmp $ \tmp -> do
|
2022-07-05 20:22:41 +00:00
|
|
|
let tmpf = tmp P.</> P.takeFileName file
|
2022-06-22 20:47:34 +00:00
|
|
|
liftIO $ moveFile file tmpf
|
|
|
|
ifM (isSymbolicLink <$> liftIO (R.getSymbolicLinkStatus tmpf))
|
2022-06-14 17:56:17 +00:00
|
|
|
( do
|
2022-06-22 20:47:34 +00:00
|
|
|
liftIO $ R.removeLink tmpf
|
2022-06-14 17:56:17 +00:00
|
|
|
addSymlink file key Nothing
|
|
|
|
next $ cleanup key =<< inAnnex key
|
|
|
|
, do
|
2022-06-22 20:47:34 +00:00
|
|
|
liftIO $ moveFile tmpf file
|
2022-06-14 17:56:17 +00:00
|
|
|
next $ return True
|
|
|
|
)
|
2022-06-14 20:38:34 +00:00
|
|
|
fixuppointer s key =
|
2021-03-12 18:09:19 +00:00
|
|
|
starting "add" (ActionItemTreeFile file) si $
|
2022-08-03 15:16:04 +00:00
|
|
|
addingExistingLink file key $
|
|
|
|
skipWhenDryRun dr $ do
|
|
|
|
Database.Keys.addAssociatedFile key =<< inRepo (toTopFilePath file)
|
|
|
|
next $ addFile Large file s
|
2010-11-02 23:04:24 +00:00
|
|
|
|
fix add overwrite race with git-annex add to annex
This is not a complete fix for all such races, only the one where a
large file gets changed while adding and gets added to git rather than
to the annex.
addLink needs to go away, any caller of it is probably subject to the
same kind of race. (Also, addLink itself fails to check gitignore when
symlinks are not supported.)
ingestAdd no longer checks gitignore. (It didn't check it consistently
before either, since there were cases where it did not run git add!)
When git-annex import calls it, it's already checked gitignore itself
earlier. When git-annex add calls it, it's usually on files found
by withFilesNotInGit, which handles checking ignores.
There was one other case, when git-annex add --batch calls it. In that
case, old git-annex behaved rather badly, it would seem to add the file,
but git add would later fail, leaving the file as an unstaged annex symlink.
That behavior has also been fixed.
Sponsored-by: Brett Eisenberg on Patreon
2022-06-14 17:20:42 +00:00
|
|
|
perform :: RawFilePath -> AddUnlockedMatcher -> CommandPerform
|
|
|
|
perform file addunlockedmatcher = withOtherTmp $ \tmpdir -> do
|
2019-12-20 19:01:34 +00:00
|
|
|
lockingfile <- not <$> addUnlocked addunlockedmatcher
|
2021-03-01 20:34:40 +00:00
|
|
|
(MatchingFile (FileInfo file file Nothing))
|
2021-01-25 17:55:01 +00:00
|
|
|
True
|
2016-01-07 21:39:59 +00:00
|
|
|
let cfg = LockDownConfig
|
|
|
|
{ lockingFile = lockingfile
|
2019-05-07 17:04:39 +00:00
|
|
|
, hardlinkFileTmpDir = Just tmpdir
|
2021-09-02 17:45:21 +00:00
|
|
|
, checkWritePerms = True
|
2016-01-07 21:39:59 +00:00
|
|
|
}
|
2019-12-04 17:15:34 +00:00
|
|
|
ld <- lockDown cfg (fromRawFilePath file)
|
2019-06-25 17:12:47 +00:00
|
|
|
let sizer = keySource <$> ld
|
bwlimit
Added annex.bwlimit and remote.name.annex-bwlimit config that works for git
remotes and many but not all special remotes.
This nearly works, at least for a git remote on the same disk. With it set
to 100kb/1s, the meter displays an actual bandwidth of 128 kb/s, with
occasional spikes to 160 kb/s. So it needs to delay just a bit longer...
I'm unsure why.
However, at the beginning a lot of data flows before it determines the
right bandwidth limit. A granularity of less than 1s would probably improve
that.
And, I don't know yet if it makes sense to have it be 100ks/1s rather than
100kb/s. Is there a situation where the user would want a larger
granularity? Does granulatity need to be configurable at all? I only used that
format for the config really in order to reuse an existing parser.
This can't support for external special remotes, or for ones that
themselves shell out to an external command. (Well, it could, but it
would involve pausing and resuming the child process tree, which seems
very hard to implement and very strange besides.) There could also be some
built-in special remotes that it still doesn't work for, due to them not
having a progress meter whose displays blocks the bandwidth using thread.
But I don't think there are actually any that run a separate thread for
downloads than the thread that displays the progress meter.
Sponsored-by: Graham Spencer on Patreon
2021-09-21 20:58:02 +00:00
|
|
|
v <- metered Nothing sizer Nothing $ \_meter meterupdate ->
|
fix add overwrite race with git-annex add to annex
This is not a complete fix for all such races, only the one where a
large file gets changed while adding and gets added to git rather than
to the annex.
addLink needs to go away, any caller of it is probably subject to the
same kind of race. (Also, addLink itself fails to check gitignore when
symlinks are not supported.)
ingestAdd no longer checks gitignore. (It didn't check it consistently
before either, since there were cases where it did not run git add!)
When git-annex import calls it, it's already checked gitignore itself
earlier. When git-annex add calls it, it's usually on files found
by withFilesNotInGit, which handles checking ignores.
There was one other case, when git-annex add --batch calls it. In that
case, old git-annex behaved rather badly, it would seem to add the file,
but git add would later fail, leaving the file as an unstaged annex symlink.
That behavior has also been fixed.
Sponsored-by: Brett Eisenberg on Patreon
2022-06-14 17:20:42 +00:00
|
|
|
ingestAdd meterupdate ld
|
2019-06-25 17:12:47 +00:00
|
|
|
finish v
|
2013-09-25 20:07:11 +00:00
|
|
|
where
|
2016-02-16 18:43:43 +00:00
|
|
|
finish (Just key) = next $ cleanup key True
|
|
|
|
finish Nothing = stop
|
2012-06-06 00:28:34 +00:00
|
|
|
|
2016-02-16 18:43:43 +00:00
|
|
|
cleanup :: Key -> Bool -> CommandCleanup
|
|
|
|
cleanup key hascontent = do
|
2019-01-14 17:03:35 +00:00
|
|
|
maybeShowJSON $ JSONChunk [("key", serializeKey key)]
|
2014-01-05 18:09:57 +00:00
|
|
|
when hascontent $
|
|
|
|
logStatus key InfoPresent
|
2013-02-05 17:41:48 +00:00
|
|
|
return True
|