extract ScanPreviousVersions

This commit is contained in:
risk danger olson 2016-11-17 15:41:19 -07:00
parent 4051dc0211
commit 7a2cbefaa7
4 changed files with 56 additions and 50 deletions

@ -322,7 +322,8 @@ func pruneTaskGetRetainedAtRef(ref string, retainChan chan string, errorChan cha
func pruneTaskGetPreviousVersionsOfRef(ref string, since time.Time, retainChan chan string, errorChan chan error, waitg *sync.WaitGroup) { func pruneTaskGetPreviousVersionsOfRef(ref string, since time.Time, retainChan chan string, errorChan chan error, waitg *sync.WaitGroup) {
defer waitg.Done() defer waitg.Done()
refchan, err := lfs.ScanPreviousVersionsToChan(ref, since) gitscanner := lfs.NewGitScanner()
refchan, err := gitscanner.ScanPreviousVersions(ref, since)
if err != nil { if err != nil {
errorChan <- err errorChan <- err
return return

@ -1,6 +1,9 @@
package lfs package lfs
import "fmt" import (
"fmt"
"time"
)
// GitScanner scans objects in a Git repository for LFS pointers. // GitScanner scans objects in a Git repository for LFS pointers.
type GitScanner struct { type GitScanner struct {
@ -65,6 +68,14 @@ func (s *GitScanner) ScanUnpushed(remote string) (*PointerChannelWrapper, error)
return scanUnpushed(remote) return scanUnpushed(remote)
} }
// ScanPreviousVersions scans changes reachable from ref (commit) back to since.
// Returns channel of pointers for *previous* versions that overlap that time.
// Does not include pointers which were still in use at ref (use ScanRefsToChan
// for that)
func (s *GitScanner) ScanPreviousVersions(ref string, since time.Time) (*PointerChannelWrapper, error) {
return logPreviousSHAs(ref, since)
}
func (s *GitScanner) opts(mode ScanningMode) *ScanRefsOptions { func (s *GitScanner) opts(mode ScanningMode) *ScanRefsOptions {
opts := newScanRefsOptions() opts := newScanRefsOptions()
opts.ScanMode = mode opts.ScanMode = mode

@ -7,7 +7,9 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"regexp" "regexp"
"time"
"github.com/git-lfs/git-lfs/git"
"github.com/git-lfs/git-lfs/tools" "github.com/git-lfs/git-lfs/tools"
"github.com/rubyist/tracerx" "github.com/rubyist/tracerx"
) )
@ -70,6 +72,44 @@ func scanUnpushed(remote string) (*PointerChannelWrapper, error) {
return NewPointerChannelWrapper(pchan, errchan), nil return NewPointerChannelWrapper(pchan, errchan), nil
} }
// logPreviousVersions scans history for all previous versions of LFS pointers
// from 'since' up to (but not including) the final state at ref
func logPreviousSHAs(ref string, since time.Time) (*PointerChannelWrapper, error) {
logArgs := []string{"log",
fmt.Sprintf("--since=%v", git.FormatGitDate(since)),
}
// Add standard search args to find lfs references
logArgs = append(logArgs, logLfsSearchArgs...)
// ending at ref
logArgs = append(logArgs, ref)
cmd, err := startCommand("git", logArgs...)
if err != nil {
return nil, err
}
cmd.Stdin.Close()
pchan := make(chan *WrappedPointer, chanBufSize)
errchan := make(chan error, 1)
// we pull out deletions, since we want the previous SHAs at commits in the range
// this means we pick up all previous versions that could have been checked
// out in the date range, not just if the commit which *introduced* them is in the range
go func() {
parseLogOutputToPointers(cmd.Stdout, LogDiffDeletions, nil, nil, pchan)
stderr, _ := ioutil.ReadAll(cmd.Stderr)
err := cmd.Wait()
if err != nil {
errchan <- fmt.Errorf("Error in git log: %v %v", err, string(stderr))
}
close(pchan)
close(errchan)
}()
return NewPointerChannelWrapper(pchan, errchan), nil
}
// parseLogOutputToPointers parses log output formatted as per logLfsSearchArgs & return pointers // parseLogOutputToPointers parses log output formatted as per logLfsSearchArgs & return pointers
// log: a stream of output from git log with at least logLfsSearchArgs specified // log: a stream of output from git log with at least logLfsSearchArgs specified
// dir: whether to include results from + or - diffs // dir: whether to include results from + or - diffs

@ -14,7 +14,6 @@ import (
"sync" "sync"
"time" "time"
"github.com/git-lfs/git-lfs/git"
"github.com/rubyist/tracerx" "github.com/rubyist/tracerx"
) )
@ -715,7 +714,8 @@ func ScanPreviousVersions(ref string, since time.Time) ([]*WrappedPointer, error
tracerx.PerformanceSince("scan", start) tracerx.PerformanceSince("scan", start)
}() }()
pointerchan, err := ScanPreviousVersionsToChan(ref, since) gitscanner := NewGitScanner()
pointerchan, err := gitscanner.ScanPreviousVersions(ref, since)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -728,52 +728,6 @@ func ScanPreviousVersions(ref string, since time.Time) ([]*WrappedPointer, error
} }
// ScanPreviousVersionsToChan scans changes reachable from ref (commit) back to since.
// Returns channel of pointers for *previous* versions that overlap that time. Does not
// include pointers which were still in use at ref (use ScanRefsToChan for that)
func ScanPreviousVersionsToChan(ref string, since time.Time) (*PointerChannelWrapper, error) {
return logPreviousSHAs(ref, since)
}
// logPreviousVersions scans history for all previous versions of LFS pointers
// from 'since' up to (but not including) the final state at ref
func logPreviousSHAs(ref string, since time.Time) (*PointerChannelWrapper, error) {
logArgs := []string{"log",
fmt.Sprintf("--since=%v", git.FormatGitDate(since)),
}
// Add standard search args to find lfs references
logArgs = append(logArgs, logLfsSearchArgs...)
// ending at ref
logArgs = append(logArgs, ref)
cmd, err := startCommand("git", logArgs...)
if err != nil {
return nil, err
}
cmd.Stdin.Close()
pchan := make(chan *WrappedPointer, chanBufSize)
errchan := make(chan error, 1)
// we pull out deletions, since we want the previous SHAs at commits in the range
// this means we pick up all previous versions that could have been checked
// out in the date range, not just if the commit which *introduced* them is in the range
go func() {
parseLogOutputToPointers(cmd.Stdout, LogDiffDeletions, nil, nil, pchan)
stderr, _ := ioutil.ReadAll(cmd.Stderr)
err := cmd.Wait()
if err != nil {
errchan <- fmt.Errorf("Error in git log: %v %v", err, string(stderr))
}
close(pchan)
close(errchan)
}()
return NewPointerChannelWrapper(pchan, errchan), nil
}
// Interface for all types of wrapper around a channel of results and an error channel // Interface for all types of wrapper around a channel of results and an error channel
// Implementors will expose a type-specific channel for results // Implementors will expose a type-specific channel for results
// Call the Wait() function after processing the results channel to catch any errors // Call the Wait() function after processing the results channel to catch any errors