symbols: replace usage of gitserver client's DiffSymbols method with new ChangedFiles method (#62355)

Part of https://github.com/sourcegraph/sourcegraph/issues/60654

This PR builds on the new ChangedFiles method introduced in https://github.com/sourcegraph/sourcegraph/pull/62354, and changes the symbols service to use it instead of the old custom diff symbols method.

## Test plan

Existing CI pipeline
This commit is contained in:
Geoffrey Gilmore 2024-05-07 11:08:35 -07:00 committed by GitHub
parent 3a3ce68138
commit fc03ac90e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 301 additions and 341 deletions

View File

@ -32,6 +32,7 @@ go_test(
deps = [
"//cmd/symbols/gitserver",
"//internal/api",
"//internal/gitserver",
"//internal/gitserver/gitdomain",
"//internal/observation",
"//internal/search",

View File

@ -11,8 +11,9 @@ import (
"io"
"sync"
gitserver "github.com/sourcegraph/sourcegraph/cmd/symbols/gitserver"
gitserver1 "github.com/sourcegraph/sourcegraph/cmd/symbols/gitserver"
api "github.com/sourcegraph/sourcegraph/internal/api"
gitserver "github.com/sourcegraph/sourcegraph/internal/gitserver"
gitdomain "github.com/sourcegraph/sourcegraph/internal/gitserver/gitdomain"
types "github.com/sourcegraph/sourcegraph/internal/types"
)
@ -22,12 +23,12 @@ import (
// github.com/sourcegraph/sourcegraph/cmd/symbols/gitserver) used for unit
// testing.
type MockGitserverClient struct {
// ChangedFilesFunc is an instance of a mock function object controlling
// the behavior of the method ChangedFiles.
ChangedFilesFunc *GitserverClientChangedFilesFunc
// FetchTarFunc is an instance of a mock function object controlling the
// behavior of the method FetchTar.
FetchTarFunc *GitserverClientFetchTarFunc
// GitDiffFunc is an instance of a mock function object controlling the
// behavior of the method GitDiff.
GitDiffFunc *GitserverClientGitDiffFunc
// LogReverseEachFunc is an instance of a mock function object
// controlling the behavior of the method LogReverseEach.
LogReverseEachFunc *GitserverClientLogReverseEachFunc
@ -44,13 +45,13 @@ type MockGitserverClient struct {
// overwritten.
func NewMockGitserverClient() *MockGitserverClient {
return &MockGitserverClient{
FetchTarFunc: &GitserverClientFetchTarFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, []string) (r0 io.ReadCloser, r1 error) {
ChangedFilesFunc: &GitserverClientChangedFilesFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) (r0 gitserver.ChangedFilesIterator, r1 error) {
return
},
},
GitDiffFunc: &GitserverClientGitDiffFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) (r0 gitserver.Changes, r1 error) {
FetchTarFunc: &GitserverClientFetchTarFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, []string) (r0 io.ReadCloser, r1 error) {
return
},
},
@ -76,16 +77,16 @@ func NewMockGitserverClient() *MockGitserverClient {
// interface. All methods panic on invocation, unless overwritten.
func NewStrictMockGitserverClient() *MockGitserverClient {
return &MockGitserverClient{
ChangedFilesFunc: &GitserverClientChangedFilesFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error) {
panic("unexpected invocation of MockGitserverClient.ChangedFiles")
},
},
FetchTarFunc: &GitserverClientFetchTarFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, []string) (io.ReadCloser, error) {
panic("unexpected invocation of MockGitserverClient.FetchTar")
},
},
GitDiffFunc: &GitserverClientGitDiffFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error) {
panic("unexpected invocation of MockGitserverClient.GitDiff")
},
},
LogReverseEachFunc: &GitserverClientLogReverseEachFunc{
defaultHook: func(context.Context, string, string, int, func(entry gitdomain.LogEntry) error) error {
panic("unexpected invocation of MockGitserverClient.LogReverseEach")
@ -107,14 +108,14 @@ func NewStrictMockGitserverClient() *MockGitserverClient {
// NewMockGitserverClientFrom creates a new mock of the MockGitserverClient
// interface. All methods delegate to the given implementation, unless
// overwritten.
func NewMockGitserverClientFrom(i gitserver.GitserverClient) *MockGitserverClient {
func NewMockGitserverClientFrom(i gitserver1.GitserverClient) *MockGitserverClient {
return &MockGitserverClient{
ChangedFilesFunc: &GitserverClientChangedFilesFunc{
defaultHook: i.ChangedFiles,
},
FetchTarFunc: &GitserverClientFetchTarFunc{
defaultHook: i.FetchTar,
},
GitDiffFunc: &GitserverClientGitDiffFunc{
defaultHook: i.GitDiff,
},
LogReverseEachFunc: &GitserverClientLogReverseEachFunc{
defaultHook: i.LogReverseEach,
},
@ -127,6 +128,121 @@ func NewMockGitserverClientFrom(i gitserver.GitserverClient) *MockGitserverClien
}
}
// GitserverClientChangedFilesFunc describes the behavior when the
// ChangedFiles method of the parent MockGitserverClient instance is
// invoked.
type GitserverClientChangedFilesFunc struct {
defaultHook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error)
hooks []func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error)
history []GitserverClientChangedFilesFuncCall
mutex sync.Mutex
}
// ChangedFiles delegates to the next hook function in the queue and stores
// the parameter and result values of this invocation.
func (m *MockGitserverClient) ChangedFiles(v0 context.Context, v1 api.RepoName, v2 api.CommitID, v3 api.CommitID) (gitserver.ChangedFilesIterator, error) {
r0, r1 := m.ChangedFilesFunc.nextHook()(v0, v1, v2, v3)
m.ChangedFilesFunc.appendCall(GitserverClientChangedFilesFuncCall{v0, v1, v2, v3, r0, r1})
return r0, r1
}
// SetDefaultHook sets function that is called when the ChangedFiles method
// of the parent MockGitserverClient instance is invoked and the hook queue
// is empty.
func (f *GitserverClientChangedFilesFunc) SetDefaultHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error)) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// ChangedFiles method of the parent MockGitserverClient instance invokes
// the hook at the front of the queue and discards it. After the queue is
// empty, the default hook function is invoked for any future action.
func (f *GitserverClientChangedFilesFunc) PushHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error)) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *GitserverClientChangedFilesFunc) SetDefaultReturn(r0 gitserver.ChangedFilesIterator, r1 error) {
f.SetDefaultHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error) {
return r0, r1
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *GitserverClientChangedFilesFunc) PushReturn(r0 gitserver.ChangedFilesIterator, r1 error) {
f.PushHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error) {
return r0, r1
})
}
func (f *GitserverClientChangedFilesFunc) nextHook() func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error) {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *GitserverClientChangedFilesFunc) appendCall(r0 GitserverClientChangedFilesFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of GitserverClientChangedFilesFuncCall objects
// describing the invocations of this function.
func (f *GitserverClientChangedFilesFunc) History() []GitserverClientChangedFilesFuncCall {
f.mutex.Lock()
history := make([]GitserverClientChangedFilesFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// GitserverClientChangedFilesFuncCall is an object that describes an
// invocation of method ChangedFiles on an instance of MockGitserverClient.
type GitserverClientChangedFilesFuncCall struct {
// Arg0 is the value of the 1st argument passed to this method
// invocation.
Arg0 context.Context
// Arg1 is the value of the 2nd argument passed to this method
// invocation.
Arg1 api.RepoName
// Arg2 is the value of the 3rd argument passed to this method
// invocation.
Arg2 api.CommitID
// Arg3 is the value of the 4th argument passed to this method
// invocation.
Arg3 api.CommitID
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 gitserver.ChangedFilesIterator
// Result1 is the value of the 2nd result returned from this method
// invocation.
Result1 error
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c GitserverClientChangedFilesFuncCall) Args() []interface{} {
return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c GitserverClientChangedFilesFuncCall) Results() []interface{} {
return []interface{}{c.Result0, c.Result1}
}
// GitserverClientFetchTarFunc describes the behavior when the FetchTar
// method of the parent MockGitserverClient instance is invoked.
type GitserverClientFetchTarFunc struct {
@ -241,120 +357,6 @@ func (c GitserverClientFetchTarFuncCall) Results() []interface{} {
return []interface{}{c.Result0, c.Result1}
}
// GitserverClientGitDiffFunc describes the behavior when the GitDiff method
// of the parent MockGitserverClient instance is invoked.
type GitserverClientGitDiffFunc struct {
defaultHook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error)
hooks []func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error)
history []GitserverClientGitDiffFuncCall
mutex sync.Mutex
}
// GitDiff delegates to the next hook function in the queue and stores the
// parameter and result values of this invocation.
func (m *MockGitserverClient) GitDiff(v0 context.Context, v1 api.RepoName, v2 api.CommitID, v3 api.CommitID) (gitserver.Changes, error) {
r0, r1 := m.GitDiffFunc.nextHook()(v0, v1, v2, v3)
m.GitDiffFunc.appendCall(GitserverClientGitDiffFuncCall{v0, v1, v2, v3, r0, r1})
return r0, r1
}
// SetDefaultHook sets function that is called when the GitDiff method of
// the parent MockGitserverClient instance is invoked and the hook queue is
// empty.
func (f *GitserverClientGitDiffFunc) SetDefaultHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error)) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// GitDiff method of the parent MockGitserverClient instance invokes the
// hook at the front of the queue and discards it. After the queue is empty,
// the default hook function is invoked for any future action.
func (f *GitserverClientGitDiffFunc) PushHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error)) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *GitserverClientGitDiffFunc) SetDefaultReturn(r0 gitserver.Changes, r1 error) {
f.SetDefaultHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error) {
return r0, r1
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *GitserverClientGitDiffFunc) PushReturn(r0 gitserver.Changes, r1 error) {
f.PushHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error) {
return r0, r1
})
}
func (f *GitserverClientGitDiffFunc) nextHook() func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error) {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *GitserverClientGitDiffFunc) appendCall(r0 GitserverClientGitDiffFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of GitserverClientGitDiffFuncCall objects
// describing the invocations of this function.
func (f *GitserverClientGitDiffFunc) History() []GitserverClientGitDiffFuncCall {
f.mutex.Lock()
history := make([]GitserverClientGitDiffFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// GitserverClientGitDiffFuncCall is an object that describes an invocation
// of method GitDiff on an instance of MockGitserverClient.
type GitserverClientGitDiffFuncCall struct {
// Arg0 is the value of the 1st argument passed to this method
// invocation.
Arg0 context.Context
// Arg1 is the value of the 2nd argument passed to this method
// invocation.
Arg1 api.RepoName
// Arg2 is the value of the 3rd argument passed to this method
// invocation.
Arg2 api.CommitID
// Arg3 is the value of the 4th argument passed to this method
// invocation.
Arg3 api.CommitID
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 gitserver.Changes
// Result1 is the value of the 2nd result returned from this method
// invocation.
Result1 error
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c GitserverClientGitDiffFuncCall) Args() []interface{} {
return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c GitserverClientGitDiffFuncCall) Results() []interface{} {
return []interface{}{c.Result0, c.Result1}
}
// GitserverClientLogReverseEachFunc describes the behavior when the
// LogReverseEach method of the parent MockGitserverClient instance is
// invoked.

View File

@ -33,7 +33,6 @@ go_test(
"//internal/gitserver",
"//internal/gitserver/gitdomain",
"//internal/observation",
"@com_github_google_go_cmp//cmp",
"@com_github_stretchr_testify//require",
],
)

View File

@ -22,8 +22,8 @@ type GitserverClient interface {
// determine if the error is a bad request (eg invalid repo).
FetchTar(context.Context, api.RepoName, api.CommitID, []string) (io.ReadCloser, error)
// GitDiff returns the paths that have changed between two commits.
GitDiff(context.Context, api.RepoName, api.CommitID, api.CommitID) (Changes, error)
// ChangedFiles returns an iterator that yields the paths that have changed between two commits.
ChangedFiles(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error)
// NewFileReader returns an io.ReadCloser reading from the named file at commit.
// The caller should always close the reader after use.
@ -75,7 +75,7 @@ func (c *gitserverClient) FetchTar(ctx context.Context, repo api.RepoName, commi
return c.innerClient.ArchiveReader(ctx, repo, opts)
}
func (c *gitserverClient) GitDiff(ctx context.Context, repo api.RepoName, commitA, commitB api.CommitID) (_ Changes, err error) {
func (c *gitserverClient) ChangedFiles(ctx context.Context, repo api.RepoName, commitA, commitB api.CommitID) (iterator gitserver.ChangedFilesIterator, err error) {
ctx, _, endObservation := c.operations.gitDiff.With(ctx, &err, observation.Args{Attrs: []attribute.KeyValue{
repo.Attr(),
attribute.String("commitA", string(commitA)),
@ -83,14 +83,7 @@ func (c *gitserverClient) GitDiff(ctx context.Context, repo api.RepoName, commit
}})
defer endObservation(1, observation.Args{})
output, err := c.innerClient.DiffSymbols(ctx, repo, commitA, commitB)
changes, err := parseGitDiffOutput(output)
if err != nil {
return Changes{}, errors.Wrap(err, "failed to parse git diff output")
}
return changes, nil
return c.innerClient.ChangedFiles(ctx, repo, string(commitA), string(commitB))
}
func (c *gitserverClient) NewFileReader(ctx context.Context, repoCommitPath types.RepoCommitPath) (io.ReadCloser, error) {

View File

@ -4,7 +4,6 @@ import (
"context"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
"github.com/sourcegraph/sourcegraph/internal/api"
@ -13,67 +12,6 @@ import (
"github.com/sourcegraph/sourcegraph/internal/observation"
)
func TestParseGitDiffOutput(t *testing.T) {
testCases := []struct {
output []byte
expectedChanges Changes
shouldError bool
}{
{
output: combineBytes(
[]byte("A"), NUL, []byte("added1.json"), NUL,
[]byte("M"), NUL, []byte("modified1.json"), NUL,
[]byte("D"), NUL, []byte("deleted1.json"), NUL,
[]byte("A"), NUL, []byte("added2.json"), NUL,
[]byte("M"), NUL, []byte("modified2.json"), NUL,
[]byte("D"), NUL, []byte("deleted2.json"), NUL,
[]byte("A"), NUL, []byte("added3.json"), NUL,
[]byte("M"), NUL, []byte("modified3.json"), NUL,
[]byte("D"), NUL, []byte("deleted3.json"), NUL,
),
expectedChanges: Changes{
Added: []string{"added1.json", "added2.json", "added3.json"},
Modified: []string{"modified1.json", "modified2.json", "modified3.json"},
Deleted: []string{"deleted1.json", "deleted2.json", "deleted3.json"},
},
},
{
output: combineBytes(
[]byte("A"), NUL, []byte("added1.json"), NUL,
[]byte("M"), NUL, []byte("modified1.json"), NUL,
[]byte("D"), NUL,
),
shouldError: true,
},
{
output: []byte{},
},
}
for _, testCase := range testCases {
changes, err := parseGitDiffOutput(testCase.output)
if err != nil {
if !testCase.shouldError {
t.Fatalf("unexpected error parsing git diff output: %s", err)
}
} else if testCase.shouldError {
t.Fatalf("expected error, got none")
}
if diff := cmp.Diff(testCase.expectedChanges, changes); diff != "" {
t.Errorf("unexpected changes (-want +got):\n%s", diff)
}
}
}
func combineBytes(bss ...[]byte) (combined []byte) {
for _, bs := range bss {
combined = append(combined, bs...)
}
return combined
}
func TestGitserverClient_PaginatedRevList(t *testing.T) {
allCommits := []*gitdomain.Commit{
{ID: "4ac04f2761285633cd35188c696a6e08de03c00c"},

View File

@ -30,6 +30,6 @@ func newOperations(observationCtx *observation.Context) *operations {
return &operations{
fetchTar: op("FetchTar"),
gitDiff: op("GitDiff"),
gitDiff: op("ChangedFiles"),
}
}

View File

@ -58,6 +58,7 @@ go_test(
"//internal/database/dbmocks",
"//internal/diskcache",
"//internal/endpoint",
"//internal/gitserver",
"//internal/gitserver/gitdomain",
"//internal/grpc/defaults",
"//internal/observation",

View File

@ -11,8 +11,9 @@ import (
"io"
"sync"
gitserver "github.com/sourcegraph/sourcegraph/cmd/symbols/gitserver"
gitserver1 "github.com/sourcegraph/sourcegraph/cmd/symbols/gitserver"
api "github.com/sourcegraph/sourcegraph/internal/api"
gitserver "github.com/sourcegraph/sourcegraph/internal/gitserver"
gitdomain "github.com/sourcegraph/sourcegraph/internal/gitserver/gitdomain"
types "github.com/sourcegraph/sourcegraph/internal/types"
)
@ -22,12 +23,12 @@ import (
// github.com/sourcegraph/sourcegraph/cmd/symbols/gitserver) used for unit
// testing.
type MockGitserverClient struct {
// ChangedFilesFunc is an instance of a mock function object controlling
// the behavior of the method ChangedFiles.
ChangedFilesFunc *GitserverClientChangedFilesFunc
// FetchTarFunc is an instance of a mock function object controlling the
// behavior of the method FetchTar.
FetchTarFunc *GitserverClientFetchTarFunc
// GitDiffFunc is an instance of a mock function object controlling the
// behavior of the method GitDiff.
GitDiffFunc *GitserverClientGitDiffFunc
// LogReverseEachFunc is an instance of a mock function object
// controlling the behavior of the method LogReverseEach.
LogReverseEachFunc *GitserverClientLogReverseEachFunc
@ -44,13 +45,13 @@ type MockGitserverClient struct {
// overwritten.
func NewMockGitserverClient() *MockGitserverClient {
return &MockGitserverClient{
FetchTarFunc: &GitserverClientFetchTarFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, []string) (r0 io.ReadCloser, r1 error) {
ChangedFilesFunc: &GitserverClientChangedFilesFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) (r0 gitserver.ChangedFilesIterator, r1 error) {
return
},
},
GitDiffFunc: &GitserverClientGitDiffFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) (r0 gitserver.Changes, r1 error) {
FetchTarFunc: &GitserverClientFetchTarFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, []string) (r0 io.ReadCloser, r1 error) {
return
},
},
@ -76,16 +77,16 @@ func NewMockGitserverClient() *MockGitserverClient {
// interface. All methods panic on invocation, unless overwritten.
func NewStrictMockGitserverClient() *MockGitserverClient {
return &MockGitserverClient{
ChangedFilesFunc: &GitserverClientChangedFilesFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error) {
panic("unexpected invocation of MockGitserverClient.ChangedFiles")
},
},
FetchTarFunc: &GitserverClientFetchTarFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, []string) (io.ReadCloser, error) {
panic("unexpected invocation of MockGitserverClient.FetchTar")
},
},
GitDiffFunc: &GitserverClientGitDiffFunc{
defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error) {
panic("unexpected invocation of MockGitserverClient.GitDiff")
},
},
LogReverseEachFunc: &GitserverClientLogReverseEachFunc{
defaultHook: func(context.Context, string, string, int, func(entry gitdomain.LogEntry) error) error {
panic("unexpected invocation of MockGitserverClient.LogReverseEach")
@ -107,14 +108,14 @@ func NewStrictMockGitserverClient() *MockGitserverClient {
// NewMockGitserverClientFrom creates a new mock of the MockGitserverClient
// interface. All methods delegate to the given implementation, unless
// overwritten.
func NewMockGitserverClientFrom(i gitserver.GitserverClient) *MockGitserverClient {
func NewMockGitserverClientFrom(i gitserver1.GitserverClient) *MockGitserverClient {
return &MockGitserverClient{
ChangedFilesFunc: &GitserverClientChangedFilesFunc{
defaultHook: i.ChangedFiles,
},
FetchTarFunc: &GitserverClientFetchTarFunc{
defaultHook: i.FetchTar,
},
GitDiffFunc: &GitserverClientGitDiffFunc{
defaultHook: i.GitDiff,
},
LogReverseEachFunc: &GitserverClientLogReverseEachFunc{
defaultHook: i.LogReverseEach,
},
@ -127,6 +128,121 @@ func NewMockGitserverClientFrom(i gitserver.GitserverClient) *MockGitserverClien
}
}
// GitserverClientChangedFilesFunc describes the behavior when the
// ChangedFiles method of the parent MockGitserverClient instance is
// invoked.
type GitserverClientChangedFilesFunc struct {
defaultHook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error)
hooks []func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error)
history []GitserverClientChangedFilesFuncCall
mutex sync.Mutex
}
// ChangedFiles delegates to the next hook function in the queue and stores
// the parameter and result values of this invocation.
func (m *MockGitserverClient) ChangedFiles(v0 context.Context, v1 api.RepoName, v2 api.CommitID, v3 api.CommitID) (gitserver.ChangedFilesIterator, error) {
r0, r1 := m.ChangedFilesFunc.nextHook()(v0, v1, v2, v3)
m.ChangedFilesFunc.appendCall(GitserverClientChangedFilesFuncCall{v0, v1, v2, v3, r0, r1})
return r0, r1
}
// SetDefaultHook sets function that is called when the ChangedFiles method
// of the parent MockGitserverClient instance is invoked and the hook queue
// is empty.
func (f *GitserverClientChangedFilesFunc) SetDefaultHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error)) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// ChangedFiles method of the parent MockGitserverClient instance invokes
// the hook at the front of the queue and discards it. After the queue is
// empty, the default hook function is invoked for any future action.
func (f *GitserverClientChangedFilesFunc) PushHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error)) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *GitserverClientChangedFilesFunc) SetDefaultReturn(r0 gitserver.ChangedFilesIterator, r1 error) {
f.SetDefaultHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error) {
return r0, r1
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *GitserverClientChangedFilesFunc) PushReturn(r0 gitserver.ChangedFilesIterator, r1 error) {
f.PushHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error) {
return r0, r1
})
}
func (f *GitserverClientChangedFilesFunc) nextHook() func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.ChangedFilesIterator, error) {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *GitserverClientChangedFilesFunc) appendCall(r0 GitserverClientChangedFilesFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of GitserverClientChangedFilesFuncCall objects
// describing the invocations of this function.
func (f *GitserverClientChangedFilesFunc) History() []GitserverClientChangedFilesFuncCall {
f.mutex.Lock()
history := make([]GitserverClientChangedFilesFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// GitserverClientChangedFilesFuncCall is an object that describes an
// invocation of method ChangedFiles on an instance of MockGitserverClient.
type GitserverClientChangedFilesFuncCall struct {
// Arg0 is the value of the 1st argument passed to this method
// invocation.
Arg0 context.Context
// Arg1 is the value of the 2nd argument passed to this method
// invocation.
Arg1 api.RepoName
// Arg2 is the value of the 3rd argument passed to this method
// invocation.
Arg2 api.CommitID
// Arg3 is the value of the 4th argument passed to this method
// invocation.
Arg3 api.CommitID
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 gitserver.ChangedFilesIterator
// Result1 is the value of the 2nd result returned from this method
// invocation.
Result1 error
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c GitserverClientChangedFilesFuncCall) Args() []interface{} {
return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c GitserverClientChangedFilesFuncCall) Results() []interface{} {
return []interface{}{c.Result0, c.Result1}
}
// GitserverClientFetchTarFunc describes the behavior when the FetchTar
// method of the parent MockGitserverClient instance is invoked.
type GitserverClientFetchTarFunc struct {
@ -241,120 +357,6 @@ func (c GitserverClientFetchTarFuncCall) Results() []interface{} {
return []interface{}{c.Result0, c.Result1}
}
// GitserverClientGitDiffFunc describes the behavior when the GitDiff method
// of the parent MockGitserverClient instance is invoked.
type GitserverClientGitDiffFunc struct {
defaultHook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error)
hooks []func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error)
history []GitserverClientGitDiffFuncCall
mutex sync.Mutex
}
// GitDiff delegates to the next hook function in the queue and stores the
// parameter and result values of this invocation.
func (m *MockGitserverClient) GitDiff(v0 context.Context, v1 api.RepoName, v2 api.CommitID, v3 api.CommitID) (gitserver.Changes, error) {
r0, r1 := m.GitDiffFunc.nextHook()(v0, v1, v2, v3)
m.GitDiffFunc.appendCall(GitserverClientGitDiffFuncCall{v0, v1, v2, v3, r0, r1})
return r0, r1
}
// SetDefaultHook sets function that is called when the GitDiff method of
// the parent MockGitserverClient instance is invoked and the hook queue is
// empty.
func (f *GitserverClientGitDiffFunc) SetDefaultHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error)) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// GitDiff method of the parent MockGitserverClient instance invokes the
// hook at the front of the queue and discards it. After the queue is empty,
// the default hook function is invoked for any future action.
func (f *GitserverClientGitDiffFunc) PushHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error)) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *GitserverClientGitDiffFunc) SetDefaultReturn(r0 gitserver.Changes, r1 error) {
f.SetDefaultHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error) {
return r0, r1
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *GitserverClientGitDiffFunc) PushReturn(r0 gitserver.Changes, r1 error) {
f.PushHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error) {
return r0, r1
})
}
func (f *GitserverClientGitDiffFunc) nextHook() func(context.Context, api.RepoName, api.CommitID, api.CommitID) (gitserver.Changes, error) {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *GitserverClientGitDiffFunc) appendCall(r0 GitserverClientGitDiffFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of GitserverClientGitDiffFuncCall objects
// describing the invocations of this function.
func (f *GitserverClientGitDiffFunc) History() []GitserverClientGitDiffFuncCall {
f.mutex.Lock()
history := make([]GitserverClientGitDiffFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// GitserverClientGitDiffFuncCall is an object that describes an invocation
// of method GitDiff on an instance of MockGitserverClient.
type GitserverClientGitDiffFuncCall struct {
// Arg0 is the value of the 1st argument passed to this method
// invocation.
Arg0 context.Context
// Arg1 is the value of the 2nd argument passed to this method
// invocation.
Arg1 api.RepoName
// Arg2 is the value of the 3rd argument passed to this method
// invocation.
Arg2 api.CommitID
// Arg3 is the value of the 4th argument passed to this method
// invocation.
Arg3 api.CommitID
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 gitserver.Changes
// Result1 is the value of the 2nd result returned from this method
// invocation.
Result1 error
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c GitserverClientGitDiffFuncCall) Args() []interface{} {
return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c GitserverClientGitDiffFuncCall) Results() []interface{} {
return []interface{}{c.Result0, c.Result1}
}
// GitserverClientLogReverseEachFunc describes the behavior when the
// LogReverseEach method of the parent MockGitserverClient instance is
// invoked.

View File

@ -16,6 +16,7 @@ go_library(
"//cmd/symbols/parser",
"//internal/api",
"//internal/diskcache",
"//internal/gitserver/gitdomain",
"//internal/observation",
"//internal/search",
"//lib/errors",

View File

@ -2,6 +2,7 @@ package writer
import (
"context"
"io"
"path/filepath"
"golang.org/x/sync/semaphore"
@ -12,6 +13,7 @@ import (
"github.com/sourcegraph/sourcegraph/cmd/symbols/parser"
"github.com/sourcegraph/sourcegraph/internal/api"
"github.com/sourcegraph/sourcegraph/internal/diskcache"
"github.com/sourcegraph/sourcegraph/internal/gitserver/gitdomain"
"github.com/sourcegraph/sourcegraph/internal/observation"
"github.com/sourcegraph/sourcegraph/internal/search"
"github.com/sourcegraph/sourcegraph/lib/errors"
@ -111,16 +113,36 @@ func (w *databaseWriter) writeDBFile(ctx context.Context, args search.SymbolsPar
func (w *databaseWriter) writeFileIncrementally(ctx context.Context, args search.SymbolsParameters, dbFile, newestDBFile, oldCommit string) (bool, error) {
observability.SetParseAmount(ctx, observability.PartialParse)
changes, err := w.gitserverClient.GitDiff(ctx, args.Repo, api.CommitID(oldCommit), args.CommitID)
changedFilesIterator, err := w.gitserverClient.ChangedFiles(ctx, args.Repo, api.CommitID(oldCommit), args.CommitID)
if err != nil {
return false, errors.Wrap(err, "gitserverClient.GitDiff")
return false, errors.Wrap(err, "gitserverClient.ChangedFiles")
}
defer changedFilesIterator.Close()
// Paths to re-parse
addedOrModifiedPaths := append(changes.Added, changes.Modified...)
var addedOrModifiedPaths []string
// Paths to modify in the database
addedModifiedOrDeletedPaths := append(addedOrModifiedPaths, changes.Deleted...)
var addedModifiedOrDeletedPaths []string
for {
c, err := changedFilesIterator.Next()
if err == io.EOF {
break
}
if err != nil {
return false, errors.Wrap(err, "iterating over changed files in git diff")
}
switch c.Status {
case gitdomain.AddedAMD, gitdomain.ModifiedAMD:
addedOrModifiedPaths = append(addedOrModifiedPaths, c.Path)
addedModifiedOrDeletedPaths = append(addedModifiedOrDeletedPaths, c.Path)
case gitdomain.DeletedAMD:
addedModifiedOrDeletedPaths = append(addedModifiedOrDeletedPaths, c.Path)
}
}
if err := copyFile(newestDBFile, dbFile); err != nil {
return false, err

View File

@ -377,6 +377,7 @@ type changedFilesIterator struct {
closeChan chan struct{}
buffer []gitdomain.PathStatus
index int
}
func (i *changedFilesIterator) Next() (gitdomain.PathStatus, error) {