@@ -32,42 +32,81 @@ func (d *defaultOps) path(args ...string) (string, error) {
3232}
3333
3434func (d * defaultOps ) CommonDir () (string , error ) {
35- return d .path ( "rev-parse" , "--path-format=absolute" , "--git-common-dir" )
35+ return d .directory ( "--git-common-dir" )
3636}
3737
38- func (d * defaultOps ) gitClient () (* cligit.Client , error ) {
38+ type validatedGitClient struct {
39+ client * cligit.Client
40+ gitDir string
41+ commonDir string
42+ }
43+
44+ func (d * defaultOps ) inspectGitClient () (validatedGitClient , error ) {
3945 c := d .client
4046 if c == nil {
4147 c = client
4248 }
49+ validated := validatedGitClient {client : c }
4350 for _ , directory := range []struct {
4451 option string
4552 info os.FileInfo
53+ path * string
4654 }{
47- {"--absolute-git-dir" , d .gitDir },
48- {"--git-common-dir" , d .commonDir },
55+ {"--absolute-git-dir" , d .gitDir , & validated . gitDir },
56+ {"--git-common-dir" , d .commonDir , & validated . commonDir },
4957 } {
5058 if directory .info == nil {
5159 continue
5260 }
5361 cmd , err := c .Command (context .Background (), "rev-parse" , "--path-format=absolute" , directory .option )
5462 if err != nil {
55- return nil , err
63+ return validatedGitClient {} , err
5664 }
5765 d .configureCommand (cmd )
5866 out , err := cmd .Output ()
5967 if err != nil {
60- return nil , fmt .Errorf ("inspecting worktree %q: %w" , c .RepoDir , err )
68+ return validatedGitClient {} , fmt .Errorf ("inspecting worktree %q: %w" , c .RepoDir , err )
6169 }
62- info , err := os .Stat (strings .TrimSuffix (string (out ), "\n " ))
70+ path := strings .TrimSuffix (string (out ), "\n " )
71+ info , err := os .Stat (path )
6372 if err != nil {
64- return nil , fmt .Errorf ("inspecting worktree %q: %w" , c .RepoDir , err )
73+ return validatedGitClient {} , fmt .Errorf ("inspecting worktree %q: %w" , c .RepoDir , err )
6574 }
6675 if ! os .SameFile (directory .info , info ) {
67- return nil , fmt .Errorf ("worktree %q no longer refers to the selected Git directory; rediscover worktrees before continuing" , c .RepoDir )
76+ return validatedGitClient {} , fmt .Errorf ("worktree %q no longer refers to the selected Git directory; rediscover worktrees before continuing" , c .RepoDir )
6877 }
78+ * directory .path = path
6979 }
70- return c , nil
80+ return validated , nil
81+ }
82+
83+ func (d * defaultOps ) gitClient () (* cligit.Client , error ) {
84+ validated , err := d .inspectGitClient ()
85+ return validated .client , err
86+ }
87+
88+ func (d * defaultOps ) directory (option string ) (string , error ) {
89+ validated , err := d .inspectGitClient ()
90+ if err != nil {
91+ return "" , err
92+ }
93+ // Reuse only paths validated by this call, never across commands.
94+ if option == "--absolute-git-dir" && validated .gitDir != "" {
95+ return validated .gitDir , nil
96+ }
97+ if option == "--git-common-dir" && validated .commonDir != "" {
98+ return validated .commonDir , nil
99+ }
100+ cmd , err := validated .client .Command (context .Background (), "rev-parse" , "--path-format=absolute" , option )
101+ if err != nil {
102+ return "" , err
103+ }
104+ d .configureCommand (cmd )
105+ out , err := cmd .Output ()
106+ if err != nil {
107+ return "" , err
108+ }
109+ return strings .TrimSuffix (string (out ), "\n " ), nil
71110}
72111
73112// ForWorktree resolves relative paths against this receiver's execution
@@ -76,13 +115,17 @@ func (d *defaultOps) ForWorktree(path string) (Ops, error) {
76115 if path == "" {
77116 return nil , errors .New ("worktree path must not be empty" )
78117 }
79- c , err := d .gitClient ()
118+ validated , err := d .inspectGitClient ()
80119 if err != nil {
81120 return nil , err
82121 }
83- common , err := d .CommonDir ()
84- if err != nil {
85- return nil , fmt .Errorf ("locating the source repository: %w" , err )
122+ c := validated .client
123+ common := validated .commonDir
124+ if common == "" {
125+ common , err = d .CommonDir ()
126+ if err != nil {
127+ return nil , fmt .Errorf ("locating the source repository: %w" , err )
128+ }
86129 }
87130 expectedCommon , err := os .Stat (common )
88131 if err != nil {
0 commit comments