aboutsummaryrefslogtreecommitdiffstats
path: root/status.go
diff options
context:
space:
mode:
authorPaulo Gomes <pjbgf@linux.com>2024-08-03 10:23:28 +0100
committerPaulo Gomes <pjbgf@linux.com>2024-08-03 10:25:23 +0100
commite2d6e8f264604b1b71dc2c958f7bdd44a90d029b (patch)
tree5212ed1117f4e655356ddd6fdf7fce5647267d52 /status.go
parent093134604cde84f51625efdcf5266a62cd5ab6e9 (diff)
downloadgo-git-e2d6e8f264604b1b71dc2c958f7bdd44a90d029b.tar.gz
git: worktree, Add StatusWithOptions
The fix for #119 improves the Worktree.Status() behaviour by preloading all existing files and setting their status to unmodified. Which makes it more reliable when doing per file status verification, however breaks backwards compatibility in two ways: - Increased execution time and space: the preloading can be slow in very large repositories and will increase memory usage when representing the state. - Behaviour: the previous behaviour returned a map with a small subset of entries. The new behaviour will include a new entry for every file within the repository. This commit introduces reverts the change in the default behaviour, and introduces StatusWithOptions so that users can opt-in the new option. Signed-off-by: Paulo Gomes <pjbgf@linux.com>
Diffstat (limited to 'status.go')
-rw-r--r--status.go69
1 files changed, 69 insertions, 0 deletions
diff --git a/status.go b/status.go
index 7f18e02..d14f7e6 100644
--- a/status.go
+++ b/status.go
@@ -4,6 +4,9 @@ import (
"bytes"
"fmt"
"path/filepath"
+
+ mindex "github.com/go-git/go-git/v5/utils/merkletrie/index"
+ "github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
// Status represents the current status of a Worktree.
@@ -77,3 +80,69 @@ const (
Copied StatusCode = 'C'
UpdatedButUnmerged StatusCode = 'U'
)
+
+// StatusStrategy defines the different types of strategies when processing
+// the worktree status.
+type StatusStrategy int
+
+const (
+ // TODO: (V6) Review the default status strategy.
+ // TODO: (V6) Review the type used to represent Status, to enable lazy
+ // processing of statuses going direct to the backing filesystem.
+ defaultStatusStrategy = Empty
+
+ // Empty starts its status map from empty. Missing entries for a given
+ // path means that the file is untracked. This causes a known issue (#119)
+ // whereby unmodified files can be incorrectly reported as untracked.
+ //
+ // This can be used when returning the changed state within a modified Worktree.
+ // For example, to check whether the current worktree is clean.
+ Empty StatusStrategy = 0
+ // Preload goes through all existing nodes from the index and add them to the
+ // status map as unmodified. This is currently the most reliable strategy
+ // although it comes at a performance cost in large repositories.
+ //
+ // This method is recommended when fetching the status of unmodified files.
+ // For example, to confirm the status of a specific file that is either
+ // untracked or unmodified.
+ Preload StatusStrategy = 1
+)
+
+func (s StatusStrategy) new(w *Worktree) (Status, error) {
+ switch s {
+ case Preload:
+ return preloadStatus(w)
+ case Empty:
+ return make(Status), nil
+ }
+ return nil, fmt.Errorf("%w: %+v", ErrUnsupportedStatusStrategy, s)
+}
+
+func preloadStatus(w *Worktree) (Status, error) {
+ idx, err := w.r.Storer.Index()
+ if err != nil {
+ return nil, err
+ }
+
+ idxRoot := mindex.NewRootNode(idx)
+ nodes := []noder.Noder{idxRoot}
+
+ status := make(Status)
+ for len(nodes) > 0 {
+ var node noder.Noder
+ node, nodes = nodes[0], nodes[1:]
+ if node.IsDir() {
+ children, err := node.Children()
+ if err != nil {
+ return nil, err
+ }
+ nodes = append(nodes, children...)
+ continue
+ }
+ fs := status.File(node.Name())
+ fs.Worktree = Unmodified
+ fs.Staging = Unmodified
+ }
+
+ return status, nil
+}