Display a warning message when asked to operate on a file inside a directory that's a symbolic link to elsewhere
This relicates git's behavior. It adds a few stat calls for the command line parameters, so there is some minor slowdown, but even with thousands of parameters it will not be very noticable, and git does the same statting in similar circumstances. Note that this does not prevent eg "git annex add symlink"; the symlink will be added to git as usual. And "git annex find symlink" will silently list nothing as well. It's only "symlink/foo" or "subdir/symlink/foo" that triggers the warning.
This commit is contained in:
parent
39d7e6dd2a
commit
2a8fdfc7d8
4 changed files with 33 additions and 10 deletions
|
@ -24,6 +24,8 @@ git-annex (8.20200502) UNRELEASED; urgency=medium
|
|||
without any sanitization, but will fail if the filename has an obvious
|
||||
security problem like using an escape sequence or trying to escape
|
||||
the current directory.
|
||||
* Display a warning message when asked to operate on a file inside a
|
||||
directory that's a symbolic link to elsewhere.
|
||||
|
||||
-- Joey Hess <id@joeyh.name> Mon, 04 May 2020 12:46:11 -0400
|
||||
|
||||
|
|
|
@ -243,28 +243,47 @@ newtype WorkTreeItem = WorkTreeItem FilePath
|
|||
-- seeking for such files.
|
||||
newtype AllowHidden = AllowHidden Bool
|
||||
|
||||
-- Many git commands seek work tree items matching some criteria,
|
||||
-- Many git commands like ls-files seek work tree items matching some criteria,
|
||||
-- and silently skip over anything that does not exist. But users expect
|
||||
-- an error message when one of the files they provided as a command-line
|
||||
-- parameter doesn't exist, so this checks that each exists.
|
||||
--
|
||||
-- Also, when two directories are symlinked, referring to a file
|
||||
-- inside the symlinked directory will be silently skipped by git commands
|
||||
-- like ls-files. But, the user would be surprised for it to be skipped, so
|
||||
-- check if the parent directories are symlinks.
|
||||
workTreeItems :: CmdParams -> Annex [WorkTreeItem]
|
||||
workTreeItems = workTreeItems' (AllowHidden False)
|
||||
|
||||
workTreeItems' :: AllowHidden -> CmdParams -> Annex [WorkTreeItem]
|
||||
workTreeItems' (AllowHidden allowhidden) ps = do
|
||||
currbranch <- getCurrentBranch
|
||||
forM_ ps $ \p ->
|
||||
unlessM (exists p <||> hidden currbranch p) $ do
|
||||
toplevelWarning False (p ++ " not found")
|
||||
Annex.incError
|
||||
forM_ ps $ \p -> do
|
||||
relf <- liftIO $ relPathCwdToFile p
|
||||
ifM (not <$> (exists p <||> hidden currbranch relf))
|
||||
( prob (p ++ " not found")
|
||||
, whenM (viasymlink (upFrom relf)) $
|
||||
prob (p ++ " is beyond a symbolic link")
|
||||
)
|
||||
return (map (WorkTreeItem) ps)
|
||||
where
|
||||
exists p = isJust <$> liftIO (catchMaybeIO $ getSymbolicLinkStatus p)
|
||||
hidden currbranch p
|
||||
| allowhidden = do
|
||||
f <- liftIO $ relPathCwdToFile p
|
||||
isJust <$> catObjectMetaDataHidden (toRawFilePath f) currbranch
|
||||
|
||||
viasymlink Nothing = return False
|
||||
viasymlink (Just p) =
|
||||
ifM (liftIO $ isSymbolicLink <$> getSymbolicLinkStatus p)
|
||||
( return True
|
||||
, viasymlink (upFrom p)
|
||||
)
|
||||
|
||||
hidden currbranch f
|
||||
| allowhidden = isJust
|
||||
<$> catObjectMetaDataHidden (toRawFilePath f) currbranch
|
||||
| otherwise = return False
|
||||
|
||||
prob msg = do
|
||||
toplevelWarning False msg
|
||||
Annex.incError
|
||||
|
||||
notSymlink :: RawFilePath -> IO Bool
|
||||
notSymlink f = liftIO $ not . isSymbolicLink <$> R.getSymbolicLinkStatus f
|
||||
|
|
|
@ -88,7 +88,7 @@ parentDir :: FilePath -> FilePath
|
|||
parentDir = takeDirectory . dropTrailingPathSeparator
|
||||
|
||||
{- Just the parent directory of a path, or Nothing if the path has no
|
||||
- parent (ie for "/" or ".") -}
|
||||
- parent (ie for "/" or "." or "foo") -}
|
||||
upFrom :: FilePath -> Maybe FilePath
|
||||
upFrom dir
|
||||
| length dirs < 2 = Nothing
|
||||
|
|
|
@ -8,3 +8,5 @@ This happens because git ls-files doesn't list the file, but then I think
|
|||
the code that handles erroring if a file that does not exist is specified
|
||||
doesn't catch it because the file does exist, it's just behind the symlink.
|
||||
--[[Joey]]
|
||||
|
||||
> [[fixed|done]] --[[Joey]]
|
||||
|
|
Loading…
Reference in a new issue