Support core.sharedRepository=0xxx at long last
Sponsored-by: Brett Eisenberg on Patreon
This commit is contained in:
parent
0aa98aa09b
commit
67f8268b3f
6 changed files with 87 additions and 34 deletions
|
@ -44,8 +44,7 @@ import Config
|
||||||
import Utility.Directory.Create
|
import Utility.Directory.Create
|
||||||
import qualified Utility.RawFilePath as R
|
import qualified Utility.RawFilePath as R
|
||||||
|
|
||||||
import System.PosixCompat.Files (fileMode, intersectFileModes, nullFileMode, groupWriteMode, ownerWriteMode, ownerReadMode, groupReadMode, stdFileMode, ownerExecuteMode, groupExecuteMode)
|
import System.PosixCompat.Files (fileMode, intersectFileModes, nullFileMode, groupWriteMode, ownerWriteMode, ownerReadMode, groupReadMode, otherReadMode, stdFileMode, ownerExecuteMode, groupExecuteMode, otherExecuteMode, setGroupIDMode)
|
||||||
import Numeric
|
|
||||||
|
|
||||||
withShared :: (SharedRepository -> Annex a) -> Annex a
|
withShared :: (SharedRepository -> Annex a) -> Annex a
|
||||||
withShared a = a =<< coreSharedRepository <$> Annex.getGitConfig
|
withShared a = a =<< coreSharedRepository <$> Annex.getGitConfig
|
||||||
|
@ -78,15 +77,10 @@ setAnnexPerm' modef isdir file = unlessM crippledFileSystem $
|
||||||
Nothing -> noop
|
Nothing -> noop
|
||||||
Just f -> void $ liftIO $ tryIO $
|
Just f -> void $ liftIO $ tryIO $
|
||||||
modifyFileMode file $ f []
|
modifyFileMode file $ f []
|
||||||
go (UmaskShared n) = do
|
go (UmaskShared n) = void $ liftIO $ tryIO $ R.setFileMode file $
|
||||||
warnUmaskSharedUnsupported n
|
if isdir then umaskSharedDirectory n else n
|
||||||
go UnShared
|
|
||||||
modef' = fromMaybe addModes modef
|
modef' = fromMaybe addModes modef
|
||||||
|
|
||||||
warnUmaskSharedUnsupported :: Int -> Annex ()
|
|
||||||
warnUmaskSharedUnsupported n = warning $ UnquotedString $
|
|
||||||
"core.sharedRepository set to a umask override (0" ++ showOct n "" ++ ") is not supported by git-annex; ignoring that configuration"
|
|
||||||
|
|
||||||
resetAnnexFilePerm :: RawFilePath -> Annex ()
|
resetAnnexFilePerm :: RawFilePath -> Annex ()
|
||||||
resetAnnexFilePerm = resetAnnexPerm False
|
resetAnnexFilePerm = resetAnnexPerm False
|
||||||
|
|
||||||
|
@ -109,14 +103,12 @@ resetAnnexPerm isdir file = unlessM crippledFileSystem $ do
|
||||||
- taken into account; this is for use with actions that create the file
|
- taken into account; this is for use with actions that create the file
|
||||||
- and apply the umask automatically. -}
|
- and apply the umask automatically. -}
|
||||||
annexFileMode :: Annex FileMode
|
annexFileMode :: Annex FileMode
|
||||||
annexFileMode = withShared go
|
annexFileMode = withShared (pure . go)
|
||||||
where
|
where
|
||||||
go GroupShared = return sharedmode
|
go GroupShared = sharedmode
|
||||||
go AllShared = return $ combineModes (sharedmode:readModes)
|
go AllShared = combineModes (sharedmode:readModes)
|
||||||
go UnShared = return stdFileMode
|
go UnShared = stdFileMode
|
||||||
go (UmaskShared n) = do
|
go (UmaskShared n) = n
|
||||||
warnUmaskSharedUnsupported n
|
|
||||||
go UnShared
|
|
||||||
sharedmode = combineModes groupSharedModes
|
sharedmode = combineModes groupSharedModes
|
||||||
|
|
||||||
{- Creates a directory inside the gitAnnexDir (or possibly the dbdir),
|
{- Creates a directory inside the gitAnnexDir (or possibly the dbdir),
|
||||||
|
@ -179,6 +171,7 @@ freezeContent'' sr file rv = do
|
||||||
unlessM crippledFileSystem $ go sr
|
unlessM crippledFileSystem $ go sr
|
||||||
freezeHook file
|
freezeHook file
|
||||||
where
|
where
|
||||||
|
go UnShared = liftIO $ nowriteadd [ownerReadMode]
|
||||||
go GroupShared = if versionNeedsWritableContentFiles rv
|
go GroupShared = if versionNeedsWritableContentFiles rv
|
||||||
then liftIO $ ignoresharederr $ modmode $ addModes
|
then liftIO $ ignoresharederr $ modmode $ addModes
|
||||||
[ownerReadMode, groupReadMode, ownerWriteMode, groupWriteMode]
|
[ownerReadMode, groupReadMode, ownerWriteMode, groupWriteMode]
|
||||||
|
@ -189,10 +182,13 @@ freezeContent'' sr file rv = do
|
||||||
(readModes ++ writeModes)
|
(readModes ++ writeModes)
|
||||||
else liftIO $ ignoresharederr $
|
else liftIO $ ignoresharederr $
|
||||||
nowriteadd readModes
|
nowriteadd readModes
|
||||||
go UnShared = liftIO $ nowriteadd [ownerReadMode]
|
go (UmaskShared n) = if versionNeedsWritableContentFiles rv
|
||||||
go (UmaskShared n) = do
|
-- Assume that the configured mode includes write bits
|
||||||
warnUmaskSharedUnsupported n
|
-- for all users who should be able to lock the file, so
|
||||||
go UnShared
|
-- don't need to add any write modes.
|
||||||
|
then liftIO $ ignoresharederr $ modmode $ const n
|
||||||
|
else liftIO $ ignoresharederr $ modmode $ const $
|
||||||
|
removeModes writeModes n
|
||||||
|
|
||||||
ignoresharederr = void . tryIO
|
ignoresharederr = void . tryIO
|
||||||
|
|
||||||
|
@ -228,6 +224,7 @@ checkContentWritePerm' :: SharedRepository -> RawFilePath -> Maybe RepoVersion -
|
||||||
checkContentWritePerm' sr file rv hasfreezehook
|
checkContentWritePerm' sr file rv hasfreezehook
|
||||||
| hasfreezehook = return (Just True)
|
| hasfreezehook = return (Just True)
|
||||||
| otherwise = case sr of
|
| otherwise = case sr of
|
||||||
|
UnShared -> want Just (excludemodes writeModes)
|
||||||
GroupShared
|
GroupShared
|
||||||
| versionNeedsWritableContentFiles rv -> want sharedret
|
| versionNeedsWritableContentFiles rv -> want sharedret
|
||||||
(includemodes [ownerWriteMode, groupWriteMode])
|
(includemodes [ownerWriteMode, groupWriteMode])
|
||||||
|
@ -236,9 +233,11 @@ checkContentWritePerm' sr file rv hasfreezehook
|
||||||
| versionNeedsWritableContentFiles rv ->
|
| versionNeedsWritableContentFiles rv ->
|
||||||
want sharedret (includemodes writeModes)
|
want sharedret (includemodes writeModes)
|
||||||
| otherwise -> want sharedret (excludemodes writeModes)
|
| otherwise -> want sharedret (excludemodes writeModes)
|
||||||
UnShared -> want Just (excludemodes writeModes)
|
UmaskShared n
|
||||||
UmaskShared _ ->
|
| versionNeedsWritableContentFiles rv -> want sharedret
|
||||||
checkContentWritePerm' UnShared file rv hasfreezehook
|
(\havemode -> havemode == n)
|
||||||
|
| otherwise -> want sharedret
|
||||||
|
(\havemode -> havemode == removeModes writeModes n)
|
||||||
where
|
where
|
||||||
want mk f = catchMaybeIO (fileMode <$> R.getFileStatus file)
|
want mk f = catchMaybeIO (fileMode <$> R.getFileStatus file)
|
||||||
>>= return . \case
|
>>= return . \case
|
||||||
|
@ -264,9 +263,7 @@ thawContent' sr file = do
|
||||||
go GroupShared = liftIO $ void $ tryIO $ groupWriteRead file
|
go GroupShared = liftIO $ void $ tryIO $ groupWriteRead file
|
||||||
go AllShared = liftIO $ void $ tryIO $ groupWriteRead file
|
go AllShared = liftIO $ void $ tryIO $ groupWriteRead file
|
||||||
go UnShared = liftIO $ allowWrite file
|
go UnShared = liftIO $ allowWrite file
|
||||||
go (UmaskShared n) = do
|
go (UmaskShared n) = liftIO $ void $ tryIO $ R.setFileMode file n
|
||||||
warnUmaskSharedUnsupported n
|
|
||||||
go UnShared
|
|
||||||
|
|
||||||
{- Runs an action that thaws a file's permissions. This will probably
|
{- Runs an action that thaws a file's permissions. This will probably
|
||||||
- fail on a crippled filesystem. But, if file modes are supported on a
|
- fail on a crippled filesystem. But, if file modes are supported on a
|
||||||
|
@ -281,7 +278,7 @@ thawPerms a hook = ifM crippledFileSystem
|
||||||
{- Blocks writing to the directory an annexed file is in, to prevent the
|
{- Blocks writing to the directory an annexed file is in, to prevent the
|
||||||
- file accidentally being deleted. However, if core.sharedRepository
|
- file accidentally being deleted. However, if core.sharedRepository
|
||||||
- is set, this is not done, since the group must be allowed to delete the
|
- is set, this is not done, since the group must be allowed to delete the
|
||||||
- file.
|
- file without eing able to thaw the directory.
|
||||||
-}
|
-}
|
||||||
freezeContentDir :: RawFilePath -> Annex ()
|
freezeContentDir :: RawFilePath -> Annex ()
|
||||||
freezeContentDir file = do
|
freezeContentDir file = do
|
||||||
|
@ -290,19 +287,26 @@ freezeContentDir file = do
|
||||||
freezeHook dir
|
freezeHook dir
|
||||||
where
|
where
|
||||||
dir = parentDir file
|
dir = parentDir file
|
||||||
|
go UnShared = liftIO $ preventWrite dir
|
||||||
go GroupShared = liftIO $ void $ tryIO $ groupWriteRead dir
|
go GroupShared = liftIO $ void $ tryIO $ groupWriteRead dir
|
||||||
go AllShared = liftIO $ void $ tryIO $ groupWriteRead dir
|
go AllShared = liftIO $ void $ tryIO $ groupWriteRead dir
|
||||||
go UnShared = liftIO $ preventWrite dir
|
go (UmaskShared n) = liftIO $ void $ tryIO $ R.setFileMode dir $
|
||||||
go (UmaskShared n) = do
|
umaskSharedDirectory $
|
||||||
warnUmaskSharedUnsupported n
|
-- If n includes group or other write mode, leave them set
|
||||||
go UnShared
|
-- to allow them to delete the file without being able to
|
||||||
|
-- thaw the directory.
|
||||||
|
removeModes [ownerWriteMode] n
|
||||||
|
|
||||||
thawContentDir :: RawFilePath -> Annex ()
|
thawContentDir :: RawFilePath -> Annex ()
|
||||||
thawContentDir file = do
|
thawContentDir file = do
|
||||||
fastDebug "Annex.Perms" ("thawing content directory " ++ fromRawFilePath dir)
|
fastDebug "Annex.Perms" ("thawing content directory " ++ fromRawFilePath dir)
|
||||||
thawPerms (liftIO $ allowWrite dir) (thawHook dir)
|
thawPerms (withShared (liftIO . go)) (thawHook dir)
|
||||||
where
|
where
|
||||||
dir = parentDir file
|
dir = parentDir file
|
||||||
|
go UnShared = allowWrite dir
|
||||||
|
go GroupShared = allowWrite dir
|
||||||
|
go AllShared = allowWrite dir
|
||||||
|
go (UmaskShared n) = R.setFileMode dir n
|
||||||
|
|
||||||
{- Makes the directory tree to store an annexed file's content,
|
{- Makes the directory tree to store an annexed file's content,
|
||||||
- with appropriate permissions on each level. -}
|
- with appropriate permissions on each level. -}
|
||||||
|
@ -354,3 +358,17 @@ thawHook p = maybe noop go =<< annexThawContentCommand <$> Annex.getGitConfig
|
||||||
go basecmd = void $ liftIO $
|
go basecmd = void $ liftIO $
|
||||||
boolSystem "sh" [Param "-c", Param $ gencmd basecmd]
|
boolSystem "sh" [Param "-c", Param $ gencmd basecmd]
|
||||||
gencmd = massReplace [ ("%path", shellEscape (fromRawFilePath p)) ]
|
gencmd = massReplace [ ("%path", shellEscape (fromRawFilePath p)) ]
|
||||||
|
|
||||||
|
{- Calculate mode to use for a directory from the mode to use for a file.
|
||||||
|
-
|
||||||
|
- This corresponds to git's handling of core.sharedRepository=0xxx
|
||||||
|
-}
|
||||||
|
umaskSharedDirectory :: FileMode -> FileMode
|
||||||
|
umaskSharedDirectory n = flip addModes n $ map snd $ filter fst
|
||||||
|
[ (isset ownerReadMode, ownerExecuteMode)
|
||||||
|
, (isset groupReadMode, groupExecuteMode)
|
||||||
|
, (isset otherReadMode, otherExecuteMode)
|
||||||
|
, (isset groupReadMode || isset groupWriteMode, setGroupIDMode)
|
||||||
|
]
|
||||||
|
where
|
||||||
|
isset v = checkMode v n
|
||||||
|
|
|
@ -29,7 +29,7 @@ git-annex (10.20230408) UNRELEASED; urgency=medium
|
||||||
--json-error-messages is enabled, output a JSON object indicating the
|
--json-error-messages is enabled, output a JSON object indicating the
|
||||||
problem. (But git ls-files --error-unmatch still displays errors about
|
problem. (But git ls-files --error-unmatch still displays errors about
|
||||||
such files in some situations.)
|
such files in some situations.)
|
||||||
* Warn about unsupported core.sharedRepository=0xxx when set.
|
* Support core.sharedRepository=0xxx at long last.
|
||||||
* Bug fix: Create .git/annex/, .git/annex/fsckdb,
|
* Bug fix: Create .git/annex/, .git/annex/fsckdb,
|
||||||
.git/annex/sentinal, .git/annex/sentinal.cache, and
|
.git/annex/sentinal, .git/annex/sentinal.cache, and
|
||||||
.git/annex/journal/* with permissions configured by core.sharedRepository.
|
.git/annex/journal/* with permissions configured by core.sharedRepository.
|
||||||
|
|
|
@ -12,13 +12,14 @@ module Git.ConfigTypes where
|
||||||
import Data.Char
|
import Data.Char
|
||||||
import Numeric
|
import Numeric
|
||||||
import qualified Data.ByteString.Char8 as S8
|
import qualified Data.ByteString.Char8 as S8
|
||||||
|
import System.PosixCompat.Types
|
||||||
|
|
||||||
import Common
|
import Common
|
||||||
import Git
|
import Git
|
||||||
import Git.Types
|
import Git.Types
|
||||||
import qualified Git.Config
|
import qualified Git.Config
|
||||||
|
|
||||||
data SharedRepository = UnShared | GroupShared | AllShared | UmaskShared Int
|
data SharedRepository = UnShared | GroupShared | AllShared | UmaskShared FileMode
|
||||||
deriving (Eq)
|
deriving (Eq)
|
||||||
|
|
||||||
getSharedRepository :: Repo -> SharedRepository
|
getSharedRepository :: Repo -> SharedRepository
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
With core.sharedRepository=0666, some lock files get created mode 644
|
||||||
|
(with umask 0022).
|
||||||
|
|
||||||
|
With core.sharedRepository=group, some lock files get created mode 660,
|
||||||
|
rather than 644 (with umask 0022).
|
||||||
|
|
||||||
|
Root of the problem is uses of annexFileMode.
|
||||||
|
|
||||||
|
Some callers use noUmask with it, which works in cases other than these (at
|
||||||
|
least with umask 0022). But in the core.sharedRepository=group case, the
|
||||||
|
umask is cleared by noUmask, which is why the g+r bit is not set.
|
||||||
|
|
||||||
|
Some callers don't use noUmask with it, and when
|
||||||
|
core.sharedRepository=0666, that results in the umask being applied
|
||||||
|
to the mode. Which it's not supposed to with an octal mode configured.
|
||||||
|
|
||||||
|
The affected files are all lock files.
|
||||||
|
|
||||||
|
Fix will probably involve getting rid of annexFileMode, and noUmask, and
|
||||||
|
creating the lock file with default umask, then fixing up the mode if necessary,
|
||||||
|
before using it. Ie, the same pattern used everywhere else in git-annex.
|
||||||
|
--[[Joey]]
|
|
@ -5,3 +5,5 @@ etc is not supported.
|
||||||
There's no insormountable reason why not, Joey just hates umask mode math
|
There's no insormountable reason why not, Joey just hates umask mode math
|
||||||
stuff and nobody has sent a patch. Note that Annex.Content.freezeContent
|
stuff and nobody has sent a patch. Note that Annex.Content.freezeContent
|
||||||
should remove the write bit from files, no matter what.
|
should remove the write bit from files, no matter what.
|
||||||
|
|
||||||
|
> [[fixed|done]] --[[Joey]]
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
[[!comment format=mdwn
|
||||||
|
username="joey"
|
||||||
|
subject="""comment 3"""
|
||||||
|
date="2023-04-26T17:39:21Z"
|
||||||
|
content="""
|
||||||
|
I've implemented this today!
|
||||||
|
|
||||||
|
(Did notice a bug,
|
||||||
|
[[wrong_modes_for_some_lock_files_withcoresharedrepository]])
|
||||||
|
"""]]
|
Loading…
Reference in a new issue