Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit c7a4011

Browse files
committed
storage/dotgit: search for incoming dir only once
Search for incoming object directory was done once each time objects were accessed. This means a ReadDir of the objects path that is expensive. Now incoming directory is searched the first time an object is accessed and its name kept in DotGit to be reused. Signed-off-by: Javi Fontan <jfontan@gmail.com>
1 parent 005d5dc commit c7a4011

File tree

1 file changed

+28
-13
lines changed

1 file changed

+28
-13
lines changed

storage/filesystem/dotgit/dotgit.go

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ var (
6161
// type is not zero-value-safe, use the New function to initialize it.
6262
type DotGit struct {
6363
fs billy.Filesystem
64+
65+
// incoming object directory information
66+
incomingChecked bool
67+
incomingDirName string
6468
}
6569

6670
// New returns a DotGit value ready to be used. The path argument must
@@ -286,26 +290,37 @@ func (d *DotGit) objectPath(h plumbing.Hash) string {
286290
//More on 'quarantine'/incoming directory here : https://git-scm.com/docs/git-receive-pack
287291
func (d *DotGit) incomingObjectPath(h plumbing.Hash) string {
288292
hString := h.String()
289-
directoryContents, err := d.fs.ReadDir(objectsPath)
290-
if err != nil {
293+
294+
if d.incomingDirName == "" {
291295
return d.fs.Join(objectsPath, hString[0:2], hString[2:40])
292296
}
293-
var incomingDirName string
294-
for _, file := range directoryContents {
295-
if strings.Split(file.Name(), "-")[0] == "incoming" && file.IsDir() {
296-
incomingDirName = file.Name()
297+
298+
return d.fs.Join(objectsPath, d.incomingDirName, hString[0:2], hString[2:40])
299+
}
300+
301+
// hasIncomingObjects searches for an incoming directory and keeps its name
302+
// so it doesn't have to be found each time an object is accessed.
303+
func (d *DotGit) hasIncomingObjects() bool {
304+
if !d.incomingChecked {
305+
directoryContents, err := d.fs.ReadDir(objectsPath)
306+
if err == nil {
307+
for _, file := range directoryContents {
308+
if strings.Split(file.Name(), "-")[0] == "incoming" && file.IsDir() {
309+
d.incomingDirName = file.Name()
310+
}
311+
}
297312
}
313+
314+
d.incomingChecked = true
298315
}
299-
if incomingDirName == "" {
300-
return d.fs.Join(objectsPath, hString[0:2], hString[2:40])
301-
}
302-
return d.fs.Join(objectsPath, incomingDirName, hString[0:2], hString[2:40])
316+
317+
return d.incomingDirName != ""
303318
}
304319

305320
// Object returns a fs.File pointing the object file, if exists
306321
func (d *DotGit) Object(h plumbing.Hash) (billy.File, error) {
307322
obj1, err1 := d.fs.Open(d.objectPath(h))
308-
if os.IsNotExist(err1) {
323+
if os.IsNotExist(err1) && d.hasIncomingObjects() {
309324
obj2, err2 := d.fs.Open(d.incomingObjectPath(h))
310325
if err2 != nil {
311326
return obj1, err1
@@ -318,7 +333,7 @@ func (d *DotGit) Object(h plumbing.Hash) (billy.File, error) {
318333
// ObjectStat returns a os.FileInfo pointing the object file, if exists
319334
func (d *DotGit) ObjectStat(h plumbing.Hash) (os.FileInfo, error) {
320335
obj1, err1 := d.fs.Stat(d.objectPath(h))
321-
if os.IsNotExist(err1) {
336+
if os.IsNotExist(err1) && d.hasIncomingObjects() {
322337
obj2, err2 := d.fs.Stat(d.incomingObjectPath(h))
323338
if err2 != nil {
324339
return obj1, err1
@@ -331,7 +346,7 @@ func (d *DotGit) ObjectStat(h plumbing.Hash) (os.FileInfo, error) {
331346
// ObjectDelete removes the object file, if exists
332347
func (d *DotGit) ObjectDelete(h plumbing.Hash) error {
333348
err1 := d.fs.Remove(d.objectPath(h))
334-
if os.IsNotExist(err1) {
349+
if os.IsNotExist(err1) && d.hasIncomingObjects() {
335350
err2 := d.fs.Remove(d.incomingObjectPath(h))
336351
if err2 != nil {
337352
return err1

0 commit comments

Comments
 (0)