Change AllLocalObjects to return Pointers so we have access to size

This commit is contained in:
Steve Streeting 2015-09-11 12:54:41 +01:00
parent 3288c9d160
commit 0965b58dea
4 changed files with 40 additions and 46 deletions

@ -34,7 +34,7 @@ func pruneCommand(cmd *cobra.Command, args []string) {
}
func prune(verifyRemote, dryRun, verbose bool) {
localObjects := make([]string, 0, 100)
localObjects := make([]*lfs.Pointer, 0, 100)
retainedObjects := lfs.NewStringSetWithCapacity(100)
var reachableObjects lfs.StringSet
var taskwait sync.WaitGroup
@ -106,12 +106,12 @@ func prune(verifyRemote, dryRun, verbose bool) {
}
// Background task, must call waitg.Done() once at end
func pruneTaskGetLocalObjects(outLocalObjects *[]string, waitg *sync.WaitGroup) {
func pruneTaskGetLocalObjects(outLocalObjects *[]*lfs.Pointer, waitg *sync.WaitGroup) {
defer waitg.Done()
localObjectsChan := lfs.AllLocalObjectsChan()
for oid := range localObjectsChan {
*outLocalObjects = append(*outLocalObjects, oid)
for p := range localObjectsChan {
*outLocalObjects = append(*outLocalObjects, p)
}
}

@ -289,69 +289,56 @@ const (
gitPtrPrefix = "gitdir: "
)
// AllLocalObjects returns a slice of the oids all the objects stored in the local LFS store
// AllLocalObjects returns a slice of the the objects stored in the local LFS store
// This does not necessarily mean referenced by commits, just stored
func AllLocalObjects() []string {
// Note: reports final SHA only, extensions are ignored
func AllLocalObjects() []*Pointer {
c := AllLocalObjectsChan()
ret := make([]string, 0, 100)
for oid := range c {
ret = append(ret, oid)
ret := make([]*Pointer, 0, 100)
for p := range c {
ret = append(ret, p)
}
return ret
}
// AllLocalObjectsChan returns a channel of the oids all the objects stored in the local LFS store
// AllLocalObjectsChan returns a channel of all the objects stored in the local LFS store
// This does not necessarily mean referenced by commits, just stored
// You should not alter the store until this channel is closed
func AllLocalObjectsChan() <-chan string {
ret := make(chan string, chanBufSize)
// Note: reports final SHA only, extensions are ignored
func AllLocalObjectsChan() <-chan *Pointer {
ret := make(chan *Pointer, chanBufSize)
go func() {
defer close(ret)
scanStorageDir(LocalMediaDir, 0, ret)
scanStorageDir(LocalMediaDir, ret)
}()
return ret
}
func scanStorageDir(dir string, level int, c chan string) {
func scanStorageDir(dir string, c chan *Pointer) {
// ioutil.ReadDir and filepath.Walk do sorting which is unnecessary & inefficient
// We only need to support a 2-folder structure here & know that all files are at the bottom level
// So explicitly track level and use Readdirnames at the bottom for efficiency
dirf, err := os.Open(dir)
if err != nil {
return
}
defer dirf.Close()
if level >= 2 {
// It's just files now
// Readdirnames is the fastest way to simply scan names
names, err := dirf.Readdirnames(0)
if err != nil {
tracerx.Printf("Problem with Readdirnames in %v: %v", dir, err)
return
}
for _, oid := range names {
direntries, err := dirf.Readdir(0)
if err != nil {
tracerx.Printf("Problem with Readdir in %v: %v", dir, err)
return
}
for _, dirfi := range direntries {
if dirfi.IsDir() {
subpath := filepath.Join(dir, dirfi.Name())
scanStorageDir(subpath, c)
} else {
// Make sure it's really an object file & not .DS_Store etc
if oidRE.MatchString(oid) {
c <- oid
if oidRE.MatchString(dirfi.Name()) {
c <- NewPointer(dirfi.Name(), dirfi.Size(), nil)
}
}
} else {
// Readdir because we're looking for nested folders
direntries, err := dirf.Readdir(0)
if err != nil {
tracerx.Printf("Problem with Readdir in %v: %v", dir, err)
return
}
for _, dirfi := range direntries {
if dirfi.IsDir() {
subpath := filepath.Join(dir, dirfi.Name())
scanStorageDir(subpath, level+1, c)
}
}
}
}

@ -20,7 +20,7 @@ func TestAllCurrentObjectsNone(t *testing.T) {
actual := AllLocalObjects()
assert.Equal(t, []string{}, actual, "Should be no objects")
assert.Equal(t, []*Pointer{}, actual, "Should be no objects")
}
func TestAllCurrentObjectsSome(t *testing.T) {
@ -47,15 +47,15 @@ func TestAllCurrentObjectsSome(t *testing.T) {
outputs := repo.AddCommits(inputs)
expected := make([]string, 0, numFiles)
expected := make([]*Pointer, 0, numFiles)
for _, f := range outputs[0].Files {
expected = append(expected, f.Oid)
expected = append(expected, f)
}
actual := AllLocalObjects()
// sort to ensure comparison is equal
sort.Strings(expected)
sort.Strings(actual)
sort.Sort(test.PointersByOid(expected))
sort.Sort(test.PointersByOid(actual))
assert.Equal(t, expected, actual, "Oids from disk should be the same as in commits")
}

@ -418,3 +418,10 @@ type WrappedPointersByOid []*lfs.WrappedPointer
func (a WrappedPointersByOid) Len() int { return len(a) }
func (a WrappedPointersByOid) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a WrappedPointersByOid) Less(i, j int) bool { return a[i].Pointer.Oid < a[j].Pointer.Oid }
// PointersByOid implements sort.Interface for []*lfs.Pointer based on oid
type PointersByOid []*lfs.Pointer
func (a PointersByOid) Len() int { return len(a) }
func (a PointersByOid) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a PointersByOid) Less(i, j int) bool { return a[i].Oid < a[j].Oid }