shithub: furgit

Download patch

ref: ba8c85ed2456c59269214f6e4f1203537fb3f6d4
parent: 1a8842b33d6d83d1754267e087fd7b4f73ca9e91
author: Runxi Yu <runxiyu@umich.edu>
date: Thu Mar 19 11:27:39 EDT 2026

*: Update call sites

--- a/cmd/show-object/main.go
+++ b/cmd/show-object/main.go
@@ -8,6 +8,7 @@
 	"os"
 	"strings"
 
+	"codeberg.org/lindenii/furgit/object"
 	"codeberg.org/lindenii/furgit/object/stored"
 	"codeberg.org/lindenii/furgit/objectid"
 	"codeberg.org/lindenii/furgit/objecttype"
@@ -81,7 +82,7 @@
 	return resolved.ID, nil
 }
 
-func printStored(s stored.StoredObject) {
+func printStored(s *stored.Stored[object.Object]) {
 	var b strings.Builder
 
 	id := s.ID()
@@ -95,20 +96,20 @@
 	fmt.Fprintf(&b, "id: %s\n", id)
 	fmt.Fprintf(&b, "type: %s\n", tyName)
 
-	switch s := s.(type) {
-	case *stored.StoredBlob:
-		blob := s.Blob()
+	switch obj := s.Object().(type) {
+	case *object.Blob:
+		blob := obj
 		fmt.Fprintf(&b, "size: %d\n", len(blob.Data))
 		fmt.Fprintf(&b, "data: %q\n", string(blob.Data))
-	case *stored.StoredTree:
-		tree := s.Tree()
+	case *object.Tree:
+		tree := obj
 		fmt.Fprintf(&b, "entries: %d\n", len(tree.Entries))
 
 		for _, entry := range tree.Entries {
 			fmt.Fprintf(&b, "%06o %s\t%s\n", entry.Mode, entry.ID, entry.Name)
 		}
-	case *stored.StoredCommit:
-		commit := s.Commit()
+	case *object.Commit:
+		commit := obj
 		fmt.Fprintf(&b, "tree: %s\n", commit.Tree)
 
 		for _, parent := range commit.Parents {
@@ -118,8 +119,8 @@
 		fmt.Fprintf(&b, "author: %s <%s>\n", commit.Author.Name, commit.Author.Email)
 		fmt.Fprintf(&b, "committer: %s <%s>\n", commit.Committer.Name, commit.Committer.Email)
 		fmt.Fprintf(&b, "message:\n%s\n", string(commit.Message))
-	case *stored.StoredTag:
-		tag := s.Tag()
+	case *object.Tag:
+		tag := obj
 
 		targetTy, ok := objecttype.Name(tag.TargetType)
 		if !ok {
@@ -135,7 +136,7 @@
 
 		fmt.Fprintf(&b, "message:\n%s\n", string(tag.Message))
 	default:
-		fmt.Fprintf(&b, "%#v\n", s.Object())
+		fmt.Fprintf(&b, "%#v\n", obj)
 	}
 
 	_, _ = os.Stdout.WriteString(b.String())
--- a/repository/stored.go
+++ b/repository/stored.go
@@ -10,86 +10,33 @@
 )
 
 // ReadStored reads, parses, and wraps one object by ID.
-//
-//nolint:ireturn
-func (repo *Repository) ReadStored(id objectid.ObjectID) (stored.StoredObject, error) {
+func (repo *Repository) ReadStored(id objectid.ObjectID) (*stored.Stored[object.Object], error) {
 	parsed, err := repo.readParsedObject(id)
 	if err != nil {
 		return nil, err
 	}
 
-	switch parsed := parsed.(type) {
-	case *object.Blob:
-		return stored.NewStoredBlob(id, parsed), nil
-	case *object.Tree:
-		return stored.NewStoredTree(id, parsed), nil
-	case *object.Commit:
-		return stored.NewStoredCommit(id, parsed), nil
-	case *object.Tag:
-		return stored.NewStoredTag(id, parsed), nil
-	default:
-		return nil, fmt.Errorf("repository: unsupported parsed object type %T", parsed)
-	}
+	return stored.New(id, parsed), nil
 }
 
 // ReadStoredBlob reads and parses a blob object by ID.
-func (repo *Repository) ReadStoredBlob(id objectid.ObjectID) (*stored.StoredBlob, error) {
-	s, err := repo.ReadStored(id)
-	if err != nil {
-		return nil, err
-	}
-
-	blob, ok := s.(*stored.StoredBlob)
-	if !ok {
-		return nil, fmt.Errorf("repository: expected blob object %s, got %v", id, s.Object().ObjectType())
-	}
-
-	return blob, nil
+func (repo *Repository) ReadStoredBlob(id objectid.ObjectID) (*stored.Stored[*object.Blob], error) {
+	return readStoredAs[*object.Blob](repo, id)
 }
 
 // ReadStoredTree reads and parses a tree object by ID.
-func (repo *Repository) ReadStoredTree(id objectid.ObjectID) (*stored.StoredTree, error) {
-	s, err := repo.ReadStored(id)
-	if err != nil {
-		return nil, err
-	}
-
-	tree, ok := s.(*stored.StoredTree)
-	if !ok {
-		return nil, fmt.Errorf("repository: expected tree object %s, got %v", id, s.Object().ObjectType())
-	}
-
-	return tree, nil
+func (repo *Repository) ReadStoredTree(id objectid.ObjectID) (*stored.Stored[*object.Tree], error) {
+	return readStoredAs[*object.Tree](repo, id)
 }
 
 // ReadStoredCommit reads and parses a commit object by ID.
-func (repo *Repository) ReadStoredCommit(id objectid.ObjectID) (*stored.StoredCommit, error) {
-	s, err := repo.ReadStored(id)
-	if err != nil {
-		return nil, err
-	}
-
-	commit, ok := s.(*stored.StoredCommit)
-	if !ok {
-		return nil, fmt.Errorf("repository: expected commit object %s, got %v", id, s.Object().ObjectType())
-	}
-
-	return commit, nil
+func (repo *Repository) ReadStoredCommit(id objectid.ObjectID) (*stored.Stored[*object.Commit], error) {
+	return readStoredAs[*object.Commit](repo, id)
 }
 
 // ReadStoredTag reads and parses a tag object by ID.
-func (repo *Repository) ReadStoredTag(id objectid.ObjectID) (*stored.StoredTag, error) {
-	s, err := repo.ReadStored(id)
-	if err != nil {
-		return nil, err
-	}
-
-	tag, ok := s.(*stored.StoredTag)
-	if !ok {
-		return nil, fmt.Errorf("repository: expected tag object %s, got %v", id, s.Object().ObjectType())
-	}
-
-	return tag, nil
+func (repo *Repository) ReadStoredTag(id objectid.ObjectID) (*stored.Stored[*object.Tag], error) {
+	return readStoredAs[*object.Tag](repo, id)
 }
 
 // readParsedObject reads bytes content from storage and parses one object.
@@ -112,4 +59,18 @@
 	}
 
 	return parsed, nil
+}
+
+func readStoredAs[T object.Object](repo *Repository, id objectid.ObjectID) (*stored.Stored[T], error) {
+	parsed, err := repo.readParsedObject(id)
+	if err != nil {
+		return nil, err
+	}
+
+	typed, ok := parsed.(T)
+	if !ok {
+		return nil, fmt.Errorf("repository: expected %T object %s, got %v", *new(T), id, parsed.ObjectType())
+	}
+
+	return stored.New(id, typed), nil
 }
--- a/repository/stored_test.go
+++ b/repository/stored_test.go
@@ -33,8 +33,8 @@
 			t.Fatalf("blob ID = %s, want %s", blob.ID(), blobID)
 		}
 
-		if string(blob.Blob().Data) != "commit-body\n" {
-			t.Fatalf("blob body = %q, want %q", blob.Blob().Data, "commit-body\n")
+		if string(blob.Object().Data) != "commit-body\n" {
+			t.Fatalf("blob body = %q, want %q", blob.Object().Data, "commit-body\n")
 		}
 
 		tree, err := repo.ReadStoredTree(treeID)
@@ -46,8 +46,8 @@
 			t.Fatalf("tree ID = %s, want %s", tree.ID(), treeID)
 		}
 
-		if len(tree.Tree().Entries) != 1 {
-			t.Fatalf("tree entries = %d, want 1", len(tree.Tree().Entries))
+		if len(tree.Object().Entries) != 1 {
+			t.Fatalf("tree entries = %d, want 1", len(tree.Object().Entries))
 		}
 
 		commit, err := repo.ReadStoredCommit(commitID)
@@ -59,8 +59,8 @@
 			t.Fatalf("commit ID = %s, want %s", commit.ID(), commitID)
 		}
 
-		if commit.Commit().Tree != treeID {
-			t.Fatalf("commit tree = %s, want %s", commit.Commit().Tree, treeID)
+		if commit.Object().Tree != treeID {
+			t.Fatalf("commit tree = %s, want %s", commit.Object().Tree, treeID)
 		}
 	})
 }
@@ -240,7 +240,7 @@
 		}
 
 		for name, wantMode := range expect {
-			entry := rootTree.Tree().Entry([]byte(name))
+			entry := rootTree.Object().Entry([]byte(name))
 
 			if entry == nil {
 				t.Fatalf("Entry(%q) returned nil", name)
--- a/repository/tree.go
+++ b/repository/tree.go
@@ -12,7 +12,7 @@
 //
 // parts must contain at least one path segment. Intermediate segments must be
 // tree entries.
-func (repo *Repository) ResolveTreeEntry(tree *stored.StoredTree, parts [][]byte) (object.TreeEntry, error) {
+func (repo *Repository) ResolveTreeEntry(tree *stored.Stored[*object.Tree], parts [][]byte) (object.TreeEntry, error) {
 	if tree == nil {
 		return object.TreeEntry{}, errors.New("repository: nil root tree")
 	}
@@ -28,7 +28,7 @@
 			return object.TreeEntry{}, errors.New("repository: empty tree path segment")
 		}
 
-		entry := current.Tree().Entry(part)
+		entry := current.Object().Entry(part)
 		if entry == nil {
 			return object.TreeEntry{}, fmt.Errorf("repository: tree entry %q not found", part)
 		}
--