fix(versioner): fix perms of created folders (fixes #9626) (#10105)

As suggested in the linked issue, I've updated the versioner code to use
the permissions of the corresponding directory in the synced folder,
when creating the folder in the versions directory

### Testing
- Some tests are included with the PR. Happy to add more if you think
there are some edge-cases that we're missing.
- I've tested manually on linux to confirm the permissions of the
created directories.
- I haven't tested on Windows or OSX (I don't have access to these OS)
This commit is contained in:
Ashish Bhate
2025-05-24 07:35:32 +02:00
committed by GitHub
parent beda37f28b
commit 1a131a56f2
2 changed files with 147 additions and 3 deletions
+47 -3
View File
@@ -10,6 +10,7 @@ import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
"sort"
@@ -164,9 +165,8 @@ func archiveFile(method fs.CopyRangeMethod, srcFs, dstFs fs.Filesystem, filePath
file := filepath.Base(filePath)
inFolderPath := filepath.Dir(filePath)
err = dstFs.MkdirAll(inFolderPath, 0o755)
if err != nil && !fs.IsExist(err) {
err = dupDirTree(srcFs, dstFs, inFolderPath)
if err != nil {
l.Debugln("archiving", filePath, err)
return err
}
@@ -190,6 +190,50 @@ func archiveFile(method fs.CopyRangeMethod, srcFs, dstFs fs.Filesystem, filePath
return err
}
func dupDirTree(srcFs, dstFs fs.Filesystem, folderPath string) error {
// Return early if the folder already exists.
_, err := dstFs.Stat(folderPath)
if err == nil || !fs.IsNotExist(err) {
return err
}
hadParent := true
for i := range folderPath {
if os.IsPathSeparator(folderPath[i]) {
// If the parent folder didn't exist, then this folder doesn't exist
// so we can skip the check
if hadParent {
_, err := dstFs.Stat(folderPath[:i])
if err == nil {
continue
}
if !fs.IsNotExist(err) {
return err
}
}
hadParent = false
err := dupDirWithPerms(srcFs, dstFs, folderPath[:i])
if err != nil {
return err
}
}
}
return dupDirWithPerms(srcFs, dstFs, folderPath)
}
func dupDirWithPerms(srcFs, dstFs fs.Filesystem, folderPath string) error {
srcStat, err := srcFs.Stat(folderPath)
if err != nil {
return err
}
// If we call Mkdir with srcStat.Mode(), we won't get the expected perms because of umask
// So, we create the folder with 0700, and then change the perms to the srcStat.Mode()
err = dstFs.Mkdir(folderPath, 0o700)
if err != nil {
return err
}
return dstFs.Chmod(folderPath, srcStat.Mode())
}
func restoreFile(method fs.CopyRangeMethod, src, dst fs.Filesystem, filePath string, versionTime time.Time, tagger fileTagger) error {
tag := versionTime.In(time.Local).Truncate(time.Second).Format(TimeFormat)
taggedFilePath := tagger(filePath, tag)