Skip to content

Commit 55a1b8d

Browse files
authored
Merge pull request #16 from github/dont-join-abs
NewRepository: don't join paths if `gitDir` is already absolute
2 parents cf93294 + 7c3eb91 commit 55a1b8d

File tree

2 files changed

+170
-77
lines changed

2 files changed

+170
-77
lines changed

git/git.go

Lines changed: 61 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,8 @@ type Repository struct {
6565
}
6666

6767
func NewRepository(path string) (*Repository, error) {
68-
command := exec.Command(
69-
"git", "-C", path,
70-
"rev-parse", "--git-dir",
71-
)
72-
out, err := command.Output()
68+
cmd := exec.Command("git", "-C", path, "rev-parse", "--git-dir")
69+
out, err := cmd.Output()
7370
if err != nil {
7471
switch err := err.(type) {
7572
case *exec.Error:
@@ -90,13 +87,22 @@ func NewRepository(path string) (*Repository, error) {
9087
return nil, err
9188
}
9289
}
93-
gitDir := filepath.Join(path, string(bytes.TrimSpace(out)))
90+
gitDir := string(bytes.TrimSpace(out))
91+
if !filepath.IsAbs(gitDir) {
92+
gitDir = filepath.Join(path, gitDir)
93+
}
9494
repo := &Repository{
9595
path: gitDir,
9696
}
9797
return repo, nil
9898
}
9999

100+
func (repo *Repository) gitCommand(args ...string) *exec.Cmd {
101+
cmd := exec.Command("git", args...)
102+
cmd.Env = append(os.Environ(), "GIT_DIR="+repo.path)
103+
return cmd
104+
}
105+
100106
func (repo *Repository) Path() string {
101107
return repo.path
102108
}
@@ -113,7 +119,7 @@ type Reference struct {
113119
}
114120

115121
type ReferenceIter struct {
116-
command *exec.Cmd
122+
cmd *exec.Cmd
117123
out io.ReadCloser
118124
f *bufio.Reader
119125
errChan <-chan error
@@ -122,25 +128,24 @@ type ReferenceIter struct {
122128
// NewReferenceIter returns an iterator that iterates over all of the
123129
// references in `repo`.
124130
func (repo *Repository) NewReferenceIter() (*ReferenceIter, error) {
125-
command := exec.Command(
126-
"git", "-C", repo.path,
131+
cmd := repo.gitCommand(
127132
"for-each-ref", "--format=%(objectname) %(objecttype) %(objectsize) %(refname)",
128133
)
129134

130-
out, err := command.StdoutPipe()
135+
out, err := cmd.StdoutPipe()
131136
if err != nil {
132137
return nil, err
133138
}
134139

135-
command.Stderr = os.Stderr
140+
cmd.Stderr = os.Stderr
136141

137-
err = command.Start()
142+
err = cmd.Start()
138143
if err != nil {
139144
return nil, err
140145
}
141146

142147
return &ReferenceIter{
143-
command: command,
148+
cmd: cmd,
144149
out: out,
145150
f: bufio.NewReader(out),
146151
errChan: make(chan error, 1),
@@ -180,49 +185,46 @@ func (iter *ReferenceIter) Next() (Reference, bool, error) {
180185

181186
func (l *ReferenceIter) Close() error {
182187
err := l.out.Close()
183-
err2 := l.command.Wait()
188+
err2 := l.cmd.Wait()
184189
if err == nil {
185190
err = err2
186191
}
187192
return err
188193
}
189194

190195
type BatchObjectIter struct {
191-
command *exec.Cmd
192-
out io.ReadCloser
193-
f *bufio.Reader
196+
cmd *exec.Cmd
197+
out io.ReadCloser
198+
f *bufio.Reader
194199
}
195200

196201
// NewBatchObjectIter returns iterates over objects whose names are
197202
// fed into its stdin. The output is buffered, so it has to be closed
198203
// before you can be sure to read all of the objects.
199204
func (repo *Repository) NewBatchObjectIter() (*BatchObjectIter, io.WriteCloser, error) {
200-
command := exec.Command(
201-
"git", "-C", repo.path,
202-
"cat-file", "--batch", "--buffer",
203-
)
205+
cmd := repo.gitCommand("cat-file", "--batch", "--buffer")
204206

205-
in, err := command.StdinPipe()
207+
in, err := cmd.StdinPipe()
206208
if err != nil {
207209
return nil, nil, err
208210
}
209211

210-
out, err := command.StdoutPipe()
212+
out, err := cmd.StdoutPipe()
211213
if err != nil {
212214
return nil, nil, err
213215
}
214216

215-
command.Stderr = os.Stderr
217+
cmd.Stderr = os.Stderr
216218

217-
err = command.Start()
219+
err = cmd.Start()
218220
if err != nil {
219221
return nil, nil, err
220222
}
221223

222224
return &BatchObjectIter{
223-
command: command,
224-
out: out,
225-
f: bufio.NewReader(out),
225+
cmd: cmd,
226+
out: out,
227+
f: bufio.NewReader(out),
226228
}, in, nil
227229
}
228230

@@ -247,7 +249,7 @@ func (iter *BatchObjectIter) Next() (OID, ObjectType, counts.Count32, []byte, er
247249

248250
func (l *BatchObjectIter) Close() error {
249251
err := l.out.Close()
250-
err2 := l.command.Wait()
252+
err2 := l.cmd.Wait()
251253
if err == nil {
252254
err = err2
253255
}
@@ -355,13 +357,13 @@ func parseBatchHeader(spec string, header string) (OID, ObjectType, counts.Count
355357
}
356358

357359
type ObjectIter struct {
358-
command1 *exec.Cmd
359-
command2 *exec.Cmd
360-
in1 io.Writer
361-
out1 io.ReadCloser
362-
out2 io.ReadCloser
363-
f *bufio.Reader
364-
errChan <-chan error
360+
cmd1 *exec.Cmd
361+
cmd2 *exec.Cmd
362+
in1 io.Writer
363+
out1 io.ReadCloser
364+
out2 io.ReadCloser
365+
f *bufio.Reader
366+
errChan <-chan error
365367
}
366368

367369
// NewObjectIter returns an iterator that iterates over objects in
@@ -371,49 +373,43 @@ type ObjectIter struct {
371373
func (repo *Repository) NewObjectIter(args ...string) (
372374
*ObjectIter, io.WriteCloser, error,
373375
) {
374-
cmdArgs := []string{"-C", repo.path, "rev-list", "--objects"}
375-
cmdArgs = append(cmdArgs, args...)
376-
command1 := exec.Command("git", cmdArgs...)
377-
in1, err := command1.StdinPipe()
376+
cmd1 := repo.gitCommand(append([]string{"rev-list", "--objects"}, args...)...)
377+
in1, err := cmd1.StdinPipe()
378378
if err != nil {
379379
return nil, nil, err
380380
}
381381

382-
out1, err := command1.StdoutPipe()
382+
out1, err := cmd1.StdoutPipe()
383383
if err != nil {
384384
return nil, nil, err
385385
}
386386

387-
command1.Stderr = os.Stderr
387+
cmd1.Stderr = os.Stderr
388388

389-
err = command1.Start()
389+
err = cmd1.Start()
390390
if err != nil {
391391
return nil, nil, err
392392
}
393393

394-
command2 := exec.Command(
395-
"git", "-C", repo.path,
396-
"cat-file", "--batch-check", "--buffer",
397-
)
398-
399-
in2, err := command2.StdinPipe()
394+
cmd2 := repo.gitCommand("cat-file", "--batch-check", "--buffer")
395+
in2, err := cmd2.StdinPipe()
400396
if err != nil {
401397
out1.Close()
402-
command1.Wait()
398+
cmd1.Wait()
403399
return nil, nil, err
404400
}
405401

406-
out2, err := command2.StdoutPipe()
402+
out2, err := cmd2.StdoutPipe()
407403
if err != nil {
408404
in2.Close()
409405
out1.Close()
410-
command1.Wait()
406+
cmd1.Wait()
411407
return nil, nil, err
412408
}
413409

414-
command2.Stderr = os.Stderr
410+
cmd2.Stderr = os.Stderr
415411

416-
err = command2.Start()
412+
err = cmd2.Start()
417413
if err != nil {
418414
return nil, nil, err
419415
}
@@ -444,23 +440,20 @@ func (repo *Repository) NewObjectIter(args ...string) (
444440
}()
445441

446442
return &ObjectIter{
447-
command1: command1,
448-
command2: command2,
449-
out1: out1,
450-
out2: out2,
451-
f: bufio.NewReader(out2),
452-
errChan: errChan,
443+
cmd1: cmd1,
444+
cmd2: cmd2,
445+
out1: out1,
446+
out2: out2,
447+
f: bufio.NewReader(out2),
448+
errChan: errChan,
453449
}, in1, nil
454450
}
455451

456452
// CreateObject creates a new Git object, of the specified type, in
457453
// `Repository`. `writer` is a function that writes the object in `git
458454
// hash-object` input format. This is used for testing only.
459455
func (repo *Repository) CreateObject(t ObjectType, writer func(io.Writer) error) (OID, error) {
460-
cmd := exec.Command(
461-
"git", "-C", repo.path,
462-
"hash-object", "-w", "-t", string(t), "--stdin",
463-
)
456+
cmd := repo.gitCommand("hash-object", "-w", "-t", string(t), "--stdin")
464457
in, err := cmd.StdinPipe()
465458
if err != nil {
466459
return OID{}, err
@@ -505,15 +498,9 @@ func (repo *Repository) UpdateRef(refname string, oid OID) error {
505498
var cmd *exec.Cmd
506499

507500
if oid == NullOID {
508-
cmd = exec.Command(
509-
"git", "-C", repo.path,
510-
"update-ref", "-d", refname,
511-
)
501+
cmd = repo.gitCommand("update-ref", "-d", refname)
512502
} else {
513-
cmd = exec.Command(
514-
"git", "-C", repo.path,
515-
"update-ref", refname, oid.String(),
516-
)
503+
cmd = repo.gitCommand("update-ref", refname, oid.String())
517504
}
518505
return cmd.Run()
519506
}
@@ -532,11 +519,11 @@ func (l *ObjectIter) Close() error {
532519
l.out1.Close()
533520
err := <-l.errChan
534521
l.out2.Close()
535-
err2 := l.command1.Wait()
522+
err2 := l.cmd1.Wait()
536523
if err == nil {
537524
err = err2
538525
}
539-
err2 = l.command2.Wait()
526+
err2 = l.cmd2.Wait()
540527
if err == nil {
541528
err = err2
542529
}

0 commit comments

Comments
 (0)