6161// type is not zero-value-safe, use the New function to initialize it.
6262type 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
287291func (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
306321func (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
319334func (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
332347func (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