ref: 7ddaf1eb2fde11a9e07df0215646c1dca08ccc50
parent: 803089a76171db1dd5b891fb6dfa1b7e7f3d50d2
author: Runxi Yu <runxiyu@umich.edu>
date: Sun Mar 22 18:07:39 EDT 2026
refstore, repository: Ownership/lifetimes fix
--- a/refstore/batch.go
+++ b/refstore/batch.go
@@ -34,8 +34,12 @@
// Apply validates and applies queued operations, returning one result per
// queued operation in order. Fatal backend failures are returned separately.
+ //
+ // Apply is terminal. Further use of the batch is undefined behavior.
Apply() ([]BatchResult, error)
// Abort abandons the batch and releases any resources it holds.
+ //
+ // Abort is terminal. Further use of the batch is undefined behavior.
Abort() error
}
--- a/refstore/files/close.go
+++ b/refstore/files/close.go
@@ -1,13 +1,10 @@
package files
// Close releases resources associated with the store.
+//
+// Store borrows gitRoot, so Close does not close it.
+//
+// Repeated calls to Close are undefined behavior.
func (store *Store) Close() error {- err := store.gitRoot.Close()
- commonErr := store.commonRoot.Close()
-
- if err != nil {- return err
- }
-
- return commonErr
+ return store.commonRoot.Close()
}
--- a/refstore/files/store.go
+++ b/refstore/files/store.go
@@ -14,7 +14,8 @@
// Store reads and writes one Git files ref namespace rooted at one repository
// gitdir plus its commondir.
//
-// Store owns both roots and closes them in Close.
+// Store borrows gitRoot and owns commonRoot. Close releases only resources
+// opened by the store itself.
type Store struct {gitRoot *os.Root
commonRoot *os.Root
--- a/refstore/reading.go
+++ b/refstore/reading.go
@@ -25,5 +25,8 @@
// The exact pattern language is backend-defined.
List(pattern string) ([]ref.Ref, error)
// Close releases resources associated with the store.
+ //
+ // Repeated calls to Close are undefined behavior unless the implementation
+ // explicitly documents otherwise.
Close() error
}
--- a/refstore/transaction.go
+++ b/refstore/transaction.go
@@ -37,7 +37,11 @@
VerifySymbolic(name, oldTarget string) error
// Commit validates and applies all queued operations atomically.
+ //
+ // Commit is terminal. Further use of the transaction is undefined behavior.
Commit() error
// Abort abandons the transaction and releases any resources it holds.
+ //
+ // Abort is terminal. Further use of the transaction is undefined behavior.
Abort() error
}
--- a/repository/close.go
+++ b/repository/close.go
@@ -49,5 +49,12 @@
}
}
+ if repo.refRoot != nil {+ err := repo.refRoot.Close()
+ if err != nil {+ errs = append(errs, err)
+ }
+ }
+
return errors.Join(errs...)
}
--- a/repository/open.go
+++ b/repository/open.go
@@ -1,7 +1,12 @@
package repository
-import "os"
+import (
+ "fmt"
+ "os"
+ reffiles "codeberg.org/lindenii/furgit/refstore/files"
+)
+
// Open opens a repository and wires object/ref stores from its on-disk format.
//
// Open borrows root during construction and does not close it.
@@ -39,12 +44,20 @@
repo.objectsLooseForWritingOnly = objectsLooseForWritingOnly
repo.objectsWriteRoot = objectsWriteRoot
- refs, err := openRefStore(root, algo, detectPackedRefsTimeout(cfg))
+ refRoot, err := root.OpenRoot(".") if err != nil {+ return nil, fmt.Errorf("repository: open root for refs: %w", err)+ }
+
+ refs, err := reffiles.New(refRoot, algo, detectPackedRefsTimeout(cfg))
+ if err != nil {+ _ = refRoot.Close()
+
return nil, err
}
repo.refs = refs
+ repo.refRoot = refRoot
return repo, nil
}
--- a/repository/refs.go
+++ b/repository/refs.go
@@ -1,31 +1,6 @@
package repository
-import (
- "fmt"
- "os"
- "time"
-
- "codeberg.org/lindenii/furgit/objectid"
- "codeberg.org/lindenii/furgit/refstore"
- reffiles "codeberg.org/lindenii/furgit/refstore/files"
-)
-
-//nolint:ireturn
-func openRefStore(root *os.Root, algo objectid.Algorithm, packedRefsTimeout time.Duration) (out refstore.ReadWriteStore, err error) {- refRoot, err := root.OpenRoot(".")- if err != nil {- return nil, fmt.Errorf("repository: open root for refs: %w", err)- }
-
- store, err := reffiles.New(refRoot, algo, packedRefsTimeout)
- if err != nil {- _ = refRoot.Close()
-
- return nil, err
- }
-
- return store, nil
-}
+import "codeberg.org/lindenii/furgit/refstore"
// Refs returns the configured ref store.
//
--- a/repository/repository.go
+++ b/repository/repository.go
@@ -24,5 +24,6 @@
objectsPackRoot *os.Root
objectsLooseForWritingOnly *objectloose.Store
objectsWriteRoot *os.Root
+ refRoot *os.Root
refs refstore.ReadWriteStore
}
--
⑨