From 7a08a67b0badaf65372a97ae248f6c206c868ca6 Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Mon, 17 Nov 2025 05:21:43 +0000 Subject: [PATCH] types: add backwards compat layer to filemode handling Change-Id: vkqnuulvrqxyklpovwswuystktpqtpyv older knots return a full modestring for each file. use some primitive parsing to extract a filemode in these scenarios. Signed-off-by: oppiliappan --- types/tree.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/types/tree.go b/types/tree.go index f78a9f07..fc366f00 100644 --- a/types/tree.go +++ b/types/tree.go @@ -1,6 +1,8 @@ package types import ( + "fmt" + "os" "time" "github.com/go-git/go-git/v5/plumbing" @@ -18,7 +20,65 @@ type NiceTree struct { } func (t *NiceTree) FileMode() (filemode.FileMode, error) { - return filemode.New(t.Mode) + if numericMode, err := filemode.New(t.Mode); err == nil { + return numericMode, nil + } + + // TODO: this is here for backwards compat, can be removed in future versions + osMode, err := parseModeString(t.Mode) + if err != nil { + return filemode.Empty, nil + } + + conv, err := filemode.NewFromOSFileMode(osMode) + if err != nil { + return filemode.Empty, nil + } + + return conv, nil +} + +// ParseFileModeString parses a file mode string like "-rw-r--r--" +// and returns an os.FileMode +func parseModeString(modeStr string) (os.FileMode, error) { + if len(modeStr) != 10 { + return 0, fmt.Errorf("invalid mode string length: expected 10, got %d", len(modeStr)) + } + + var mode os.FileMode + + // Parse file type (first character) + switch modeStr[0] { + case 'd': + mode |= os.ModeDir + case 'l': + mode |= os.ModeSymlink + case '-': + // regular file + default: + return 0, fmt.Errorf("unknown file type: %c", modeStr[0]) + } + + // parse permissions for owner, group, and other + perms := modeStr[1:] + shifts := []int{6, 3, 0} // bit shifts for owner, group, other + + for i := range 3 { + offset := i * 3 + shift := shifts[i] + + if perms[offset] == 'r' { + mode |= os.FileMode(4 << shift) + } + if perms[offset+1] == 'w' { + mode |= os.FileMode(2 << shift) + } + if perms[offset+2] == 'x' { + mode |= os.FileMode(1 << shift) + } + } + + return mode, nil } func (t *NiceTree) IsFile() bool { -- 2.43.0