annex.maxextensionlength for view

view: Support annex.maxextensionlength when generating filenames for the
view branch.

Note that refining an existing view will reuse the extension length that was
configured when initially constructing the view. This is necessarily the case
because it reuses the filenames.

Also view files used to have all extensions at the end, no matter how
many there were. Since annex.maxextensionlength's documentation includes
that it's limited to 2 extensions, I made it consistent with that.

Sponsored-by: k0ld on Patreon
This commit is contained in:
Joey Hess 2023-03-24 13:53:51 -04:00
parent 70a9e995b8
commit 2b5fa091e2
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
7 changed files with 48 additions and 14 deletions

View file

@ -387,7 +387,7 @@ prop_view_roundtrips (AssociatedFile Nothing) _ _ = True
prop_view_roundtrips (AssociatedFile (Just f)) metadata visible = or prop_view_roundtrips (AssociatedFile (Just f)) metadata visible = or
[ B.null (P.takeFileName f) && B.null (P.takeDirectory f) [ B.null (P.takeFileName f) && B.null (P.takeDirectory f)
, viewTooLarge view , viewTooLarge view
, all hasfields (viewedFiles view viewedFileFromReference (fromRawFilePath f) metadata) , all hasfields (viewedFiles view (viewedFileFromReference' Nothing) (fromRawFilePath f) metadata)
] ]
where where
view = View (Git.Ref "foo") $ view = View (Git.Ref "foo") $
@ -421,7 +421,9 @@ getViewedFileMetaData = getDirMetaData . dirFromViewedFile . takeFileName
- branch for the view. - branch for the view.
-} -}
applyView :: View -> Maybe Adjustment -> Annex Git.Branch applyView :: View -> Maybe Adjustment -> Annex Git.Branch
applyView = applyView' viewedFileFromReference getWorkTreeMetaData applyView v ma = do
gc <- Annex.getGitConfig
applyView' (viewedFileFromReference gc) getWorkTreeMetaData v ma
{- Generates a new branch for a View, which must be a more narrow {- Generates a new branch for a View, which must be a more narrow
- version of the View originally used to generate the currently - version of the View originally used to generate the currently
@ -553,7 +555,8 @@ updateView view madj = do
Git.LsTree.LsTreeRecursive Git.LsTree.LsTreeRecursive
(Git.LsTree.LsTreeLong True) (Git.LsTree.LsTreeLong True)
(viewParentBranch view) (viewParentBranch view)
applyView'' viewedFileFromReference getWorkTreeMetaData view madj l clean $ gc <- Annex.getGitConfig
applyView'' (viewedFileFromReference gc) getWorkTreeMetaData view madj l clean $
\ti -> do \ti -> do
let ref = Git.Ref.branchFileRef (viewParentBranch view) let ref = Git.Ref.branchFileRef (viewParentBranch view)
(getTopFilePath (Git.LsTree.file ti)) (getTopFilePath (Git.LsTree.file ti))

View file

@ -1,6 +1,6 @@
{- filenames (not paths) used in views {- filenames (not paths) used in views
- -
- Copyright 2014 Joey Hess <id@joeyh.name> - Copyright 2014-2023 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -11,6 +11,7 @@ module Annex.View.ViewedFile (
ViewedFile, ViewedFile,
MkViewedFile, MkViewedFile,
viewedFileFromReference, viewedFileFromReference,
viewedFileFromReference',
viewedFileReuse, viewedFileReuse,
dirFromViewedFile, dirFromViewedFile,
prop_viewedFile_roundtrips, prop_viewedFile_roundtrips,
@ -35,17 +36,27 @@ type MkViewedFile = FilePath -> ViewedFile
- -
- So, from dir/subdir/file.foo, generate file_%dir%subdir%.foo - So, from dir/subdir/file.foo, generate file_%dir%subdir%.foo
-} -}
viewedFileFromReference :: MkViewedFile viewedFileFromReference :: GitConfig -> MkViewedFile
viewedFileFromReference f = concat $ viewedFileFromReference g = viewedFileFromReference' (annexMaxExtensionLength g)
[ escape (fromRawFilePath base)
viewedFileFromReference' :: Maybe Int -> MkViewedFile
viewedFileFromReference' maxextlen f = concat $
[ escape (fromRawFilePath base')
, if null dirs then "" else "_%" ++ intercalate "%" (map escape dirs) ++ "%" , if null dirs then "" else "_%" ++ intercalate "%" (map escape dirs) ++ "%"
, escape $ fromRawFilePath $ S.concat extensions , escape $ fromRawFilePath $ S.concat extensions'
] ]
where where
(path, basefile) = splitFileName f (path, basefile) = splitFileName f
dirs = filter (/= ".") $ map dropTrailingPathSeparator (splitPath path) dirs = filter (/= ".") $ map dropTrailingPathSeparator (splitPath path)
(base, extensions) = splitShortExtensions (toRawFilePath basefile') (base, extensions) = case maxextlen of
Nothing -> splitShortExtensions (toRawFilePath basefile')
Just n -> splitShortExtensions' (n+1) (toRawFilePath basefile')
{- Limit to two extensions maximum. -}
(base', extensions')
| length extensions <= 2 = (base, extensions)
| otherwise =
let (es,more) = splitAt 2 (reverse extensions)
in (base <> mconcat (reverse more), reverse es)
{- On Windows, if the filename looked like "dir/c:foo" then {- On Windows, if the filename looked like "dir/c:foo" then
- basefile would look like it contains a drive letter, which will - basefile would look like it contains a drive letter, which will
- not work. There cannot really be a filename like that, probably, - not work. There cannot really be a filename like that, probably,
@ -90,7 +101,7 @@ prop_viewedFile_roundtrips tf
-- Relative filenames wanted, not directories. -- Relative filenames wanted, not directories.
| any (isPathSeparator) (end f ++ beginning f) = True | any (isPathSeparator) (end f ++ beginning f) = True
| isAbsolute f || isDrive f = True | isAbsolute f || isDrive f = True
| otherwise = dir == dirFromViewedFile (viewedFileFromReference f) | otherwise = dir == dirFromViewedFile (viewedFileFromReference' Nothing f)
where where
f = fromTestableFilePath tf f = fromTestableFilePath tf
dir = joinPath $ beginning $ splitDirectories f dir = joinPath $ beginning $ splitDirectories f

View file

@ -5,6 +5,8 @@ git-annex (10.20230322) UNRELEASED; urgency=medium
drop when annex.adjustedbranchrefresh=1 drop when annex.adjustedbranchrefresh=1
* Avoid leaving repo with a detached head when there is a failure * Avoid leaving repo with a detached head when there is a failure
checking out an updated adjusted branch. checking out an updated adjusted branch.
* view: Support annex.maxextensionlength when generating filenames for
the view branch.
-- Joey Hess <id@joeyh.name> Thu, 23 Mar 2023 15:04:41 -0400 -- Joey Hess <id@joeyh.name> Thu, 23 Mar 2023 15:04:41 -0400

View file

@ -20,6 +20,7 @@ module Utility.Path (
runSegmentPaths', runSegmentPaths',
dotfile, dotfile,
splitShortExtensions, splitShortExtensions,
splitShortExtensions',
relPathDirToFileAbs, relPathDirToFileAbs,
inSearchPath, inSearchPath,
searchPath, searchPath,

View file

@ -44,6 +44,12 @@ into the `_` directory and committing will unset the metadata.
The name of the `_` directory can be changed using the annex.viewunsetdirectory The name of the `_` directory can be changed using the annex.viewunsetdirectory
git config. git config.
Filenames in the view branch include their path within the original branch, to
ensure that they are unique. The path comes after the main filename, and
before any extensions. For example, "foo/bar.baz" will have a name
like "bar_%foo%.baz". annex.maxextensionlength can be used to configure
what is treated as an extension.
# OPTIONS # OPTIONS
* The [[git-annex-common-options]](1) can be used. * The [[git-annex-common-options]](1) can be used.

View file

@ -825,9 +825,11 @@ repository, using [[git-annex-config]]. See its man page for a list.)
* `annex.maxextensionlength` * `annex.maxextensionlength`
Maximum length, in bytes, of what is considered a filename extension when Maximum length, in bytes, of what is considered a filename extension.
adding a file to a backend that preserves filename extensions. The This is used when adding a file to a backend that preserves filename extensions,
default length is 4, which allows extensions like "jpeg". The dot before and also when generating a view branch.
The default length is 4, which allows extensions like "jpeg". The dot before
the extension is not counted part of its length. At most two extensions the extension is not counted part of its length. At most two extensions
at the end of a filename will be preserved, e.g. .gz or .tar.gz . at the end of a filename will be preserved, e.g. .gz or .tar.gz .

View file

@ -0,0 +1,9 @@
[[!comment format=mdwn
username="joey"
subject="""comment 8"""
date="2023-03-24T17:48:43Z"
content="""
I've made git-annex view use `annex.maxextensionlength`. Note that refining
an existing view will reuse the extension length that was configured when
initially constructing the view.
"""]]