aboutsummaryrefslogtreecommitdiff
path: root/object/tree/mode/parse.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-06-07 11:01:26 +0000
committerGravatar Runxi Yu2026-06-07 11:04:43 +0000
commitc2d883c7c58a3bd64d799dd000fe7254e450a4e5 (patch)
treea4456d8fc3718f235c2e934d42c056b3bcd3e1f9 /object/tree/mode/parse.go
parentobject/tag: Add (diff)
signatureNo signature
object/tree/mode: Initialize
Diffstat (limited to 'object/tree/mode/parse.go')
-rw-r--r--object/tree/mode/parse.go43
1 files changed, 43 insertions, 0 deletions
diff --git a/object/tree/mode/parse.go b/object/tree/mode/parse.go
new file mode 100644
index 00000000..7839a89a
--- /dev/null
+++ b/object/tree/mode/parse.go
@@ -0,0 +1,43 @@
+package mode
+
+import (
+ "errors"
+ "fmt"
+)
+
+// ErrInvalidMode indicates a malformed or unsupported tree entry mode.
+var ErrInvalidMode = errors.New("object/tree/mode: invalid mode")
+
+// Parse decodes a canonical octal tree entry mode.
+//
+// It accepts only the modes Git itself writes
+// and rejects malformed, unsupported, and zero-padded encodings.
+func Parse(raw []byte) (Mode, error) {
+ if len(raw) == 0 {
+ return 0, fmt.Errorf("%w: empty mode", ErrInvalidMode)
+ }
+
+ if raw[0] == '0' {
+ return 0, fmt.Errorf("%w: zero-padded mode %q", ErrInvalidMode, raw)
+ }
+
+ if len(raw) > maxModeDigits {
+ return 0, fmt.Errorf("%w: mode %q too long", ErrInvalidMode, raw)
+ }
+
+ var mode Mode
+
+ for _, c := range raw {
+ if c < '0' || c > '7' {
+ return 0, fmt.Errorf("%w: non-octal byte in mode %q", ErrInvalidMode, raw)
+ }
+
+ mode = mode<<3 | Mode(c-'0')
+ }
+
+ if !mode.IsValid() {
+ return 0, fmt.Errorf("%w: unsupported mode %q", ErrInvalidMode, raw)
+ }
+
+ return mode, nil
+}