fileRef: make paths relative and simplified

Fix behavior of several commands, including reinject, addurl, and rmurl
when given an absolute path to an unlocked file, or a relative path that
leaves and re-enters the repository.

To avoid slowing down all the cases where the paths are already ok
with an unncessary call to getCurrentDirectory, put in an optimisation
in relPathCwdToFile. That will probably also speed up other parts of
git-annex by some small amount, but I have not benchmarked.

Note that I did not convert branchFileRef, because it seems likely that
it will be used with a file that is not provided by the user, so is already
in a sane format. This is certainly true for the way git-annex uses it,
though maybe arguable to the extent Git.Ref is a reusable library.
This commit is contained in:
Joey Hess 2021-05-07 13:25:59 -04:00
parent 6b980c1514
commit 4bf7940d6b
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
5 changed files with 32 additions and 16 deletions

View file

@ -64,12 +64,17 @@ branchRef = underBase "refs/heads"
{- A Ref that can be used to refer to a file in the repository, as staged
- in the index.
-
- Prefixing the file with ./ makes this work even if in a subdirectory
- of a repo.
-}
fileRef :: RawFilePath -> Ref
fileRef f = Ref $ ":./" <> toInternalGitPath f
fileRef :: RawFilePath -> IO Ref
fileRef f = do
-- The filename could be absolute, or contain eg "../repo/file",
-- neither of which work in a ref, so convert it to a minimal
-- relative path.
f' <- relPathCwdToFile f
-- Prefixing the file with ./ makes this work even when in a
-- subdirectory of a repo. Eg, ./foo in directory bar refers
-- to bar/foo, not to foo in the top of the repository.
return $ Ref $ ":./" <> toInternalGitPath f'
{- A Ref that can be used to refer to a file in a particular branch. -}
branchFileRef :: Branch -> RawFilePath -> Ref
@ -81,8 +86,10 @@ dateRef r (RefDate d) = Ref $ fromRef' r <> "@" <> encodeBS' d
{- A Ref that can be used to refer to a file in the repository as it
- appears in a given Ref. -}
fileFromRef :: Ref -> RawFilePath -> Ref
fileFromRef r f = let (Ref fr) = fileRef f in Ref (fromRef' r <> fr)
fileFromRef :: Ref -> RawFilePath -> IO Ref
fileFromRef r f = do
(Ref fr) <- fileRef f
return (Ref (fromRef' r <> fr))
{- Checks if a ref exists. Note that it must be fully qualified,
- eg refs/heads/master rather than master. -}