aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-06-06 21:51:58 +0000
committerGravatar Runxi Yu2026-06-06 21:51:58 +0000
commit41e45d38f2d1ec78881f7e0ce778b2f43fed80a2 (patch)
tree85378d19030bbc44e6fd22078a8fe7ac01c055f1
parentref: detached -> direct (diff)
signatureNo signature
ref/name, object: Simplify errors
-rw-r--r--object/parse.go21
-rw-r--r--ref/name/component.go19
-rw-r--r--ref/name/errors.go14
-rw-r--r--ref/name/shorthand.go9
-rw-r--r--ref/name/update.go13
-rw-r--r--ref/name/validate.go10
6 files changed, 39 insertions, 47 deletions
diff --git a/object/parse.go b/object/parse.go
index 9a7b9068..b488eb49 100644
--- a/object/parse.go
+++ b/object/parse.go
@@ -1,6 +1,7 @@
package object
import (
+ "errors"
"fmt"
"lindenii.org/go/furgit/object/blob"
@@ -10,20 +11,10 @@ import (
"lindenii.org/go/furgit/object/typ"
)
-// SizeMismatchError indicates a mismatch
-// between the size expected from the object header
-// and the size of the object.
-type SizeMismatchError struct {
- Expected uint64
- Got uint64
-}
-
-func (sizeMismatchError SizeMismatchError) Error() string {
- return fmt.Sprintf(
- "object: size mismatch: header says %d bytes, but got %d from body",
- sizeMismatchError.Expected, sizeMismatchError.Got,
- )
-}
+// ErrSizeMismatch indicates a mismatch
+// between the size declared in the object header
+// and the size of the object body.
+var ErrSizeMismatch = errors.New("object: size mismatch")
// ParseWithHeader parses a loose object
// in "type size\x00body" format.
@@ -37,7 +28,7 @@ func ParseWithHeader(raw []byte, objectFormat id.ObjectFormat) (Object, error) {
body := raw[headerLen:]
if uint64(len(body)) != size {
- return nil, SizeMismatchError{Expected: size, Got: uint64(len(body))}
+ return nil, fmt.Errorf("%w: header declares %d bytes, body has %d", ErrSizeMismatch, size, len(body))
}
return ParseWithoutHeader(ty, body, objectFormat)
diff --git a/ref/name/component.go b/ref/name/component.go
index 40a736e2..b7d3bbb7 100644
--- a/ref/name/component.go
+++ b/ref/name/component.go
@@ -1,6 +1,9 @@
package name
-import "strings"
+import (
+ "fmt"
+ "strings"
+)
const lockSuffix = ".lock"
@@ -23,7 +26,7 @@ func nameDisposition(ch byte) byte {
}
}
-func checkRefnameComponent(name string, flags *int, sanitized *strings.Builder, fullName string) (int, error) {
+func checkRefnameComponent(name string, flags *int, sanitized *strings.Builder) (int, error) {
var last byte
var componentStart int
@@ -47,7 +50,7 @@ func checkRefnameComponent(name string, flags *int, sanitized *strings.Builder,
if sanitized != nil {
truncateBuilder(sanitized, sanitized.Len()-1)
} else {
- return 0, &NameError{Name: fullName, Reason: "name contains '..'"}
+ return 0, fmt.Errorf("%w: name contains '..'", ErrInvalidName)
}
}
case 3:
@@ -55,21 +58,21 @@ func checkRefnameComponent(name string, flags *int, sanitized *strings.Builder,
if sanitized != nil {
overwriteBuilderAt(sanitized, sanitized.Len()-1)
} else {
- return 0, &NameError{Name: fullName, Reason: "name contains '@{'"}
+ return 0, fmt.Errorf("%w: name contains '@{'", ErrInvalidName)
}
}
case 4:
if sanitized != nil {
overwriteBuilderAt(sanitized, sanitized.Len()-1)
} else {
- return 0, &NameError{Name: fullName, Reason: "name contains a forbidden character"}
+ return 0, fmt.Errorf("%w: name contains a forbidden character", ErrInvalidName)
}
case 5:
if *flags&nameRefspecPattern == 0 {
if sanitized != nil {
overwriteBuilderAt(sanitized, sanitized.Len()-1)
} else {
- return 0, &NameError{Name: fullName, Reason: "name contains '*'"}
+ return 0, fmt.Errorf("%w: name contains '*'", ErrInvalidName)
}
}
@@ -94,13 +97,13 @@ out:
if sanitized != nil {
overwriteBuilderAt(sanitized, componentStart)
} else {
- return 0, &NameError{Name: fullName, Reason: "component starts with '.'"}
+ return 0, fmt.Errorf("%w: component starts with '.'", ErrInvalidName)
}
}
if componentLen >= len(lockSuffix) && name[componentLen-len(lockSuffix):componentLen] == lockSuffix {
if sanitized == nil {
- return 0, &NameError{Name: fullName, Reason: "component ends with .lock"}
+ return 0, fmt.Errorf("%w: component ends with .lock", ErrInvalidName)
}
for strings.HasSuffix(sanitized.String(), lockSuffix) {
diff --git a/ref/name/errors.go b/ref/name/errors.go
index 438c60aa..1011d518 100644
--- a/ref/name/errors.go
+++ b/ref/name/errors.go
@@ -1,14 +1,6 @@
package name
-import "fmt"
+import "errors"
-// NameError reports an invalid reference name.
-type NameError struct {
- Name string
- Reason string
-}
-
-// Error implements error.
-func (err *NameError) Error() string {
- return fmt.Sprintf("ref/name: invalid name %q: %s", err.Name, err.Reason)
-}
+// ErrInvalidName indicates an invalid reference name.
+var ErrInvalidName = errors.New("ref/name: invalid name")
diff --git a/ref/name/shorthand.go b/ref/name/shorthand.go
index 75d4854f..24142edb 100644
--- a/ref/name/shorthand.go
+++ b/ref/name/shorthand.go
@@ -1,6 +1,9 @@
package name
-import "strings"
+import (
+ "fmt"
+ "strings"
+)
// Branch checks a branch shorthand
// and returns its fully-qualified refs/heads/... name.
@@ -10,7 +13,7 @@ import "strings"
func Branch(name string) (string, error) {
full := "refs/heads/" + name
if strings.HasPrefix(name, "-") || full == "refs/heads/HEAD" {
- return "", &NameError{Name: name, Reason: "invalid branch name"}
+ return "", fmt.Errorf("%w: invalid branch name", ErrInvalidName)
}
err := validate(full, 0)
@@ -29,7 +32,7 @@ func Branch(name string) (string, error) {
// and returns its fully-qualified refs/tags/... name.
func Tag(name string) (string, error) {
if strings.HasPrefix(name, "-") || name == "HEAD" {
- return "", &NameError{Name: name, Reason: "invalid tag name"}
+ return "", fmt.Errorf("%w: invalid tag name", ErrInvalidName)
}
full := "refs/tags/" + name
diff --git a/ref/name/update.go b/ref/name/update.go
index d29afe4b..a87165a4 100644
--- a/ref/name/update.go
+++ b/ref/name/update.go
@@ -1,11 +1,14 @@
package name
-import "strings"
+import (
+ "fmt"
+ "strings"
+)
// ValidateUpdateName checks whether name is valid for a direct ref update.
func ValidateUpdateName(name string, hasNewValue bool) error {
if IsPseudo(name) {
- return &NameError{Name: name, Reason: "pseudoref updates are not allowed"}
+ return fmt.Errorf("%w: pseudoref updates are not allowed", ErrInvalidName)
}
if hasNewValue {
@@ -13,7 +16,7 @@ func ValidateUpdateName(name string, hasNewValue bool) error {
}
if !IsSafe(name) {
- return &NameError{Name: name, Reason: "unsafe name for update"}
+ return fmt.Errorf("%w: unsafe name for update", ErrInvalidName)
}
return nil
@@ -23,7 +26,7 @@ func ValidateUpdateName(name string, hasNewValue bool) error {
func ValidateSymbolicTarget(name string, target string) error {
parsed := ParseWorktree(name)
if parsed.BareRefName == "HEAD" && !strings.HasPrefix(target, "refs/heads/") {
- return &NameError{Name: target, Reason: name + " must point to refs/heads/..."}
+ return fmt.Errorf("%w: %s must point to refs/heads/...", ErrInvalidName, name)
}
if IsRoot(target) {
@@ -43,5 +46,5 @@ func ValidateSymbolicTarget(name string, target string) error {
return nil
}
- return &NameError{Name: target, Reason: "symref target is not a ref"}
+ return fmt.Errorf("%w: symref target is not a ref", ErrInvalidName)
}
diff --git a/ref/name/validate.go b/ref/name/validate.go
index 989858b1..2c524491 100644
--- a/ref/name/validate.go
+++ b/ref/name/validate.go
@@ -20,7 +20,7 @@ func checkOrSanitizeRefname(name string, flags int, sanitized *strings.Builder)
if name == "@" {
if sanitized == nil {
- return &NameError{Name: name, Reason: "single @ is not allowed"}
+ return fmt.Errorf("%w: single @ is not allowed", ErrInvalidName)
}
sanitized.WriteByte('-')
@@ -31,7 +31,7 @@ func checkOrSanitizeRefname(name string, flags int, sanitized *strings.Builder)
sanitized.WriteByte('/')
}
- componentLen, err := checkRefnameComponent(remaining, &flags, sanitized, name)
+ componentLen, err := checkRefnameComponent(remaining, &flags, sanitized)
switch {
case sanitized != nil && componentLen == 0:
case componentLen <= 0:
@@ -39,7 +39,7 @@ func checkOrSanitizeRefname(name string, flags int, sanitized *strings.Builder)
return err
}
- return &NameError{Name: name, Reason: "component has zero length"}
+ return fmt.Errorf("%w: component has zero length", ErrInvalidName)
case err != nil:
return err
}
@@ -56,12 +56,12 @@ func checkOrSanitizeRefname(name string, flags int, sanitized *strings.Builder)
componentLen := len(remaining)
if componentLen > 0 && remaining[componentLen-1] == '.' {
if sanitized == nil {
- return &NameError{Name: name, Reason: "name ends with '.'"}
+ return fmt.Errorf("%w: name ends with '.'", ErrInvalidName)
}
}
if flags&nameAllowOneLevel == 0 && componentCount < 2 {
- return &NameError{Name: name, Reason: "one-level name is not allowed"}
+ return fmt.Errorf("%w: one-level name is not allowed", ErrInvalidName)
}
return nil