diff options
| author | 2026-06-07 11:01:26 +0000 | |
|---|---|---|
| committer | 2026-06-07 11:04:43 +0000 | |
| commit | c2d883c7c58a3bd64d799dd000fe7254e450a4e5 (patch) | |
| tree | a4456d8fc3718f235c2e934d42c056b3bcd3e1f9 /object/tree/mode/parse.go | |
| parent | object/tag: Add (diff) | |
| signature | No signature | |
object/tree/mode: Initialize
Diffstat (limited to 'object/tree/mode/parse.go')
| -rw-r--r-- | object/tree/mode/parse.go | 43 |
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 +} |
