aboutsummaryrefslogtreecommitdiffstats
path: root/storage/filesystem/dotgit
diff options
context:
space:
mode:
authorJavi Fontan <jfontan@gmail.com>2018-08-25 19:17:45 +0200
committerJavi Fontan <jfontan@gmail.com>2018-08-25 19:23:50 +0200
commitc7a4011d78a00bd93a2f82a39bb67c2dda5453f5 (patch)
tree35eea056efb5848a29788bff9c08fd18a0c6e139 /storage/filesystem/dotgit
parent005d5dc961a7053d88da53536f4a5eb4c305529b (diff)
downloadgo-git-c7a4011d78a00bd93a2f82a39bb67c2dda5453f5.tar.gz
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>
Diffstat (limited to 'storage/filesystem/dotgit')
-rw-r--r--storage/filesystem/dotgit/dotgit.go41
1 files changed, 28 insertions, 13 deletions
diff --git a/storage/filesystem/dotgit/dotgit.go b/storage/filesystem/dotgit/dotgit.go
index d0a14ae..addb64c 100644
--- a/storage/filesystem/dotgit/dotgit.go
+++ b/storage/filesystem/dotgit/dotgit.go
@@ -61,6 +61,10 @@ var (
// type is not zero-value-safe, use the New function to initialize it.
type DotGit struct {
fs billy.Filesystem
+
+ // incoming object directory information
+ incomingChecked bool
+ incomingDirName string
}
// 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 {
//More on 'quarantine'/incoming directory here : https://git-scm.com/docs/git-receive-pack
func (d *DotGit) incomingObjectPath(h plumbing.Hash) string {
hString := h.String()
- directoryContents, err := d.fs.ReadDir(objectsPath)
- if err != nil {
+
+ if d.incomingDirName == "" {
return d.fs.Join(objectsPath, hString[0:2], hString[2:40])
}
- var incomingDirName string
- for _, file := range directoryContents {
- if strings.Split(file.Name(), "-")[0] == "incoming" && file.IsDir() {
- incomingDirName = file.Name()
+
+ return d.fs.Join(objectsPath, d.incomingDirName, hString[0:2], hString[2:40])
+}
+
+// hasIncomingObjects searches for an incoming directory and keeps its name
+// so it doesn't have to be found each time an object is accessed.
+func (d *DotGit) hasIncomingObjects() bool {
+ if !d.incomingChecked {
+ directoryContents, err := d.fs.ReadDir(objectsPath)
+ if err == nil {
+ for _, file := range directoryContents {
+ if strings.Split(file.Name(), "-")[0] == "incoming" && file.IsDir() {
+ d.incomingDirName = file.Name()
+ }
+ }
}
+
+ d.incomingChecked = true
}
- if incomingDirName == "" {
- return d.fs.Join(objectsPath, hString[0:2], hString[2:40])
- }
- return d.fs.Join(objectsPath, incomingDirName, hString[0:2], hString[2:40])
+
+ return d.incomingDirName != ""
}
// Object returns a fs.File pointing the object file, if exists
func (d *DotGit) Object(h plumbing.Hash) (billy.File, error) {
obj1, err1 := d.fs.Open(d.objectPath(h))
- if os.IsNotExist(err1) {
+ if os.IsNotExist(err1) && d.hasIncomingObjects() {
obj2, err2 := d.fs.Open(d.incomingObjectPath(h))
if err2 != nil {
return obj1, err1
@@ -318,7 +333,7 @@ func (d *DotGit) Object(h plumbing.Hash) (billy.File, error) {
// ObjectStat returns a os.FileInfo pointing the object file, if exists
func (d *DotGit) ObjectStat(h plumbing.Hash) (os.FileInfo, error) {
obj1, err1 := d.fs.Stat(d.objectPath(h))
- if os.IsNotExist(err1) {
+ if os.IsNotExist(err1) && d.hasIncomingObjects() {
obj2, err2 := d.fs.Stat(d.incomingObjectPath(h))
if err2 != nil {
return obj1, err1
@@ -331,7 +346,7 @@ func (d *DotGit) ObjectStat(h plumbing.Hash) (os.FileInfo, error) {
// ObjectDelete removes the object file, if exists
func (d *DotGit) ObjectDelete(h plumbing.Hash) error {
err1 := d.fs.Remove(d.objectPath(h))
- if os.IsNotExist(err1) {
+ if os.IsNotExist(err1) && d.hasIncomingObjects() {
err2 := d.fs.Remove(d.incomingObjectPath(h))
if err2 != nil {
return err1