diff --git a/client/web/src/enterprise/batches/settings/AddCredentialModal.tsx b/client/web/src/enterprise/batches/settings/AddCredentialModal.tsx index 2f9a253fdbf..657805e919c 100644 --- a/client/web/src/enterprise/batches/settings/AddCredentialModal.tsx +++ b/client/web/src/enterprise/batches/settings/AddCredentialModal.tsx @@ -60,6 +60,7 @@ const scopeRequirements: Record = { ), [ExternalServiceKind.GERRIT]: , + [ExternalServiceKind.PERFORCE]: with the ability to shelve changelists., // These are just for type completeness and serve as placeholders for a bright future. [ExternalServiceKind.GITOLITE]: Unsupported, [ExternalServiceKind.GOMODULES]: Unsupported, @@ -68,7 +69,6 @@ const scopeRequirements: Record = { [ExternalServiceKind.RUBYPACKAGES]: Unsupported, [ExternalServiceKind.JVMPACKAGES]: Unsupported, [ExternalServiceKind.NPMPACKAGES]: Unsupported, - [ExternalServiceKind.PERFORCE]: Unsupported, [ExternalServiceKind.PHABRICATOR]: Unsupported, [ExternalServiceKind.AWSCODECOMMIT]: Unsupported, [ExternalServiceKind.PAGURE]: Unsupported, @@ -143,7 +143,11 @@ export const AddCredentialModal: React.FunctionComponent diff --git a/cmd/gitserver/server/BUILD.bazel b/cmd/gitserver/server/BUILD.bazel index 0ada3275f9a..6c2220b36b3 100644 --- a/cmd/gitserver/server/BUILD.bazel +++ b/cmd/gitserver/server/BUILD.bazel @@ -72,6 +72,7 @@ go_library( "//internal/limiter", "//internal/metrics", "//internal/observation", + "//internal/perforce", "//internal/ratelimit", "//internal/search/streaming/http", "//internal/security", diff --git a/cmd/gitserver/server/patch.go b/cmd/gitserver/server/patch.go index 60b2669e8ba..2d5303e0f33 100644 --- a/cmd/gitserver/server/patch.go +++ b/cmd/gitserver/server/patch.go @@ -1,6 +1,7 @@ package server import ( + "bufio" "bytes" "context" "encoding/json" @@ -18,8 +19,11 @@ import ( "github.com/sourcegraph/log" "github.com/sourcegraph/sourcegraph/internal/gitserver/gitdomain" + "github.com/sourcegraph/sourcegraph/internal/lazyregexp" + "github.com/sourcegraph/sourcegraph/internal/unpack" "github.com/sourcegraph/sourcegraph/internal/gitserver/protocol" + "github.com/sourcegraph/sourcegraph/internal/perforce" "github.com/sourcegraph/sourcegraph/internal/vcs" "github.com/sourcegraph/sourcegraph/lib/errors" ) @@ -129,7 +133,7 @@ func (s *Server) createCommitFromPatch(ctx context.Context, req protocol.CreateC resp.SetError(repo, "", "", errors.Wrap(err, "gitserver: make tmp repo")) return http.StatusInternalServerError, resp } - defer cleanUpTmpRepo(logger, tmpRepoDir) + //defer cleanUpTmpRepo(logger, tmpRepoDir) argsToString := func(args []string) string { return strings.Join(args, " ") @@ -285,37 +289,49 @@ func (s *Server) createCommitFromPatch(ctx context.Context, req protocol.CreateC } if req.Push != nil { - cmd = exec.CommandContext(ctx, "git", "push", "--force", remoteURL.String(), fmt.Sprintf("%s:%s", cmtHash, ref)) - cmd.Dir = repoGitDir - - // If the protocol is SSH and a private key was given, we want to - // use it for communication with the code host. - if remoteURL.IsSSH() && req.Push.PrivateKey != "" && req.Push.Passphrase != "" { - // We set up an agent here, which sets up a socket that can be provided to - // SSH via the $SSH_AUTH_SOCK environment variable and the goroutine to drive - // it in the background. - // This is used to pass the private key to be used when pushing to the remote, - // without the need to store it on the disk. - agent, err := newSSHAgent(logger, []byte(req.Push.PrivateKey), []byte(req.Push.Passphrase)) + if remoteURL.Scheme == "perforce" { + // the remote URL is a Perforce URL + // shelve the changelist instead of pushing to a Git host + cid, err := s.shelveChangelist(ctx, req, remoteURL, tmpGitPathEnv, altObjectsEnv) if err != nil { - resp.SetError(repo, "", "", errors.Wrap(err, "gitserver: error creating ssh-agent")) + resp.SetError(repo, "", "", err) return http.StatusInternalServerError, resp } - go agent.Listen() - // Make sure we shut this down once we're done. - defer agent.Close() - cmd.Env = append( - os.Environ(), - []string{ - fmt.Sprintf("SSH_AUTH_SOCK=%s", agent.Socket()), - }..., - ) - } + resp.ChangelistId = cid + } else { + cmd = exec.CommandContext(ctx, "git", "push", "--force", remoteURL.String(), fmt.Sprintf("%s:%s", cmtHash, ref)) + cmd.Dir = repoGitDir - if out, err = run(cmd, "pushing ref"); err != nil { - logger.Error("Failed to push", log.String("commit", cmtHash), log.String("output", string(out))) - return http.StatusInternalServerError, resp + // If the protocol is SSH and a private key was given, we want to + // use it for communication with the code host. + if remoteURL.IsSSH() && req.Push.PrivateKey != "" && req.Push.Passphrase != "" { + // We set up an agent here, which sets up a socket that can be provided to + // SSH via the $SSH_AUTH_SOCK environment variable and the goroutine to drive + // it in the background. + // This is used to pass the private key to be used when pushing to the remote, + // without the need to store it on the disk. + agent, err := newSSHAgent(logger, []byte(req.Push.PrivateKey), []byte(req.Push.Passphrase)) + if err != nil { + resp.SetError(repo, "", "", errors.Wrap(err, "gitserver: error creating ssh-agent")) + return http.StatusInternalServerError, resp + } + go agent.Listen() + // Make sure we shut this down once we're done. + defer agent.Close() + + cmd.Env = append( + os.Environ(), + []string{ + fmt.Sprintf("SSH_AUTH_SOCK=%s", agent.Socket()), + }..., + ) + } + + if out, err = run(cmd, "pushing ref"); err != nil { + logger.Error("Failed to push", log.String("commit", cmtHash), log.String("output", string(out))) + return http.StatusInternalServerError, resp + } } } resp.Rev = "refs/" + strings.TrimPrefix(ref, "refs/") @@ -344,6 +360,399 @@ func styleMessage(message string) bool { return !strings.HasPrefix(message, "Change-Id: I") } +func (s *Server) shelveChangelist(ctx context.Context, req protocol.CreateCommitFromPatchRequest, remoteURL *vcs.URL, tmpGitPathEnv, altObjectsEnv string) (string, error) { + + repo := string(req.Repo) + baseCommit := string(req.BaseCommit) + + p4user, p4passwd, p4host, p4depot, _ := decomposePerforceRemoteURL(remoteURL) + + if p4depot == "" { + // the remoteURL was constructed without a path to indicate the depot + // make a db call to fill that in + remoteURL, err := s.getRemoteURL(ctx, req.Repo) + if err != nil { + return "", errors.Wrap(err, "failed getting a remote url") + } + // and decompose again + _, _, _, p4depot, _ = decomposePerforceRemoteURL(remoteURL) + } + + logger := s.Logger.Scoped("shelveChangelist", ""). + With( + log.String("repo", repo), + log.String("baseCommit", baseCommit), + log.String("targetRef", req.TargetRef), + log.String("depot", p4depot), + ) + + // use the name of the target branch as the perforce client name + p4client := strings.TrimPrefix(req.TargetRef, "refs/heads/") + + // do all work in (another) temporary directory + tmpClientDir, err := s.tempDir("perforce-client-") + if err != nil { + return "", errors.Wrap(err, "gitserver: make tmp repo for Perforce client") + } + defer cleanUpTmpRepo(logger, tmpClientDir) + + // we'll need these environment variables for subsequent commands + commonEnv := append(os.Environ(), []string{ + tmpGitPathEnv, + altObjectsEnv, + fmt.Sprintf("P4PORT=%s", p4host), + fmt.Sprintf("P4USER=%s", p4user), + fmt.Sprintf("P4PASSWD=%s", p4passwd), + fmt.Sprintf("P4CLIENT=%s", p4client), + }...) + + p4Cmd := p4Command{ + ctx: ctx, + workingDir: tmpClientDir, + env: commonEnv, + } + + // check to see if there's a changelist for this target branch already + cid, err := p4Cmd.changelistIdFromClientSpecNameP4(p4client) + if err == nil && cid != "" { + return cid, nil + } + + // get the commit message from the base commit so that we can extract the base changelist id from it + cmd := exec.CommandContext(ctx, "git", "show", "--no-patch", "--pretty=format:%B", baseCommit) + cmd.Dir = tmpClientDir + cmd.Env = commonEnv + + out, err := cmd.Output() + if err != nil { + errorMessage := "unable to retrieve base commit message" + logger.Error(errorMessage, log.String("baseCommit", baseCommit), log.Error(err)) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + // extract the base changelist id from the commit message + baseCID, err := perforce.GetP4ChangelistID(string(out)) + if err != nil { + errorMessage := "unable to retrieve base changelist id" + logger.Error(errorMessage, log.String("commitMessage", string(out)), log.Error(err)) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + // get the list of files involved in the commit + cmd = exec.CommandContext(ctx, "git", "diff-tree", "--no-commit-id", "--name-only", "-r", baseCommit) + cmd.Dir = tmpClientDir + cmd.Env = commonEnv + out, err = cmd.CombinedOutput() + if err != nil { + errorMessage := "unable to retrieve files in base commit" + logger.Error(errorMessage, log.String("output", string(out)), log.Error(err)) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + fileList := strings.Split(strings.TrimSpace(string(out)), "\n") + if len(fileList) <= 0 { + errorMessage := "no files in base commit" + logger.Error(errorMessage, log.String("output", string(out)), log.String("baseCommit", baseCommit), log.Error(err)) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + // format a description for the client spec and the changelist + // from the commit message(s) + // be sure to indent lines so that it fits the Perforce form format + desc := "batch change" + if len(req.CommitInfo.Messages) > 0 { + desc = strings.ReplaceAll(strings.Join(req.CommitInfo.Messages, "\n"), "\n", "\n\t") + } + + // parse the depot path from the repo name + // depot := strings.SplitN() + + // create a Perforce client spec to use for creating the changelist + err = p4Cmd.createClientSpecP4(p4depot, p4client, p4user, desc) + if err != nil { + errorMessage := "error creating a client spec" + logger.Error(errorMessage, log.String("output", digErrorMessage(err)), log.Error(errors.New(errorMessage))) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + // get the files from the Perforce server + // mark them for editing + err = p4Cmd.cloneAndEditFilesP4(fileList, baseCID) + if err != nil { + errorMessage := "error getting files from depot" + logger.Error(errorMessage, log.String("output", digErrorMessage(err)), log.Error(errors.New(errorMessage))) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + // delete the files involved with the batch change in case the batch change involves a file deletion + // ignore all errors for now; just assume that it's going to work + for _, fileName := range fileList { + os.RemoveAll(fileName) + } + + // overlay with files from the commit + // 1. create an archive from the commit + // 2. pipe the archive to `tar -x` to extract it into the temp dir + + // archive the commit + archiveCmd := exec.CommandContext(ctx, "git", "archive", "--format=tar", "--verbose", baseCommit) + archiveCmd.Dir = tmpClientDir + archiveCmd.Env = commonEnv + + // connect the archive to the untar process + stdout, err := archiveCmd.StdoutPipe() + if err != nil { + errorMessage := "unable to read changed files" + logger.Error(errorMessage, log.Error(err)) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + reader := bufio.NewReader(stdout) + + // start the archive; it'll send stdout (the tar archive) to `unpack.Tar` via the `io.Reader` + if err := archiveCmd.Start(); err != nil { + errorMessage := "unable to read changed files" + logger.Error(errorMessage, log.Error(err)) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + err = unpack.Tar(reader, tmpClientDir, unpack.Opts{SkipDuplicates: true}) + if err != nil { + errorMessage := "unable to read changed files" + logger.Error(errorMessage, log.Error(err)) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + // make sure the untar process completes before moving on + if err := archiveCmd.Wait(); err != nil { + errorMessage := "unable to overlay changed files" + logger.Error(errorMessage, log.Error(err)) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + // ensure that there are changes to shelve + if changes, err := p4Cmd.areThereChangedFilesP4(); err != nil { + errorMessage := "unable to verify that there are changed files" + logger.Error(errorMessage, log.String("output", digErrorMessage(err)), log.Error(errors.New(errorMessage))) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } else if !changes { + errorMessage := "no changes to shelve" + logger.Error(errorMessage, log.Error(errors.New(errorMessage))) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + // submit the changes as a shelved changelist + + // create a changelist form with the description + changeForm, err := p4Cmd.generateChangeFormP4(desc) + if err != nil { + errorMessage := "failed generating a change form" + logger.Error(errorMessage, log.String("output", digErrorMessage(err)), log.Error(errors.New(errorMessage))) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + // feed the changelist form into `p4 shelve` + // capture the output to parse for a changelist id + cid, err = p4Cmd.shelveChangelistP4(changeForm) + if err != nil { + errorMessage := "failed shelving the changelist" + logger.Error(errorMessage, log.String("output", digErrorMessage(err)), log.Error(errors.New(errorMessage))) + return "", errors.Wrap(err, "gitserver: "+errorMessage) + } + + // return the changelist id as a string - it'll be returned as a string to the caller in lieu of an int pointer + // because protobuf doesn't do scalar pointers + return cid, nil +} + +type p4Command struct { + ctx context.Context + workingDir string + env []string +} + +func (p p4Command) commandContext(args ...string) *exec.Cmd { + cmd := exec.CommandContext(p.ctx, "p4", args...) + cmd.Dir = p.workingDir + cmd.Env = p.env + return cmd +} + +// Uses `p4 changes` to see if there is a changelist already associated with the given client spec +func (p p4Command) changelistIdFromClientSpecNameP4(p4client string) (string, error) { + cmd := p.commandContext("changes", + "-r", // list in reverse order, which means that the given changelist id will be the first one listed + "-m", "1", // limit output to one record, so that the given changelist is the only one listed + "-l", // use a long listing, which includes the whole commit message + "-c", p4client, + ) + out, err := cmd.CombinedOutput() + if err != nil { + return "", errors.Wrap(err, string(out)) + } + pcl, err := perforce.ParseChangelistOutput(string(out)) + if err != nil { + return "", errors.Wrap(err, string(out)) + } + return pcl.ID, nil +} + +const clientSpecForm = `Client: %s +Owner: %s +Description: + %s +Root: %s +Options: noallwrite noclobber nocompress unlocked nomodtime normdir +SubmitOptions: submitunchanged +LineEnd: local +View: %s... //%s/... +` + +// Uses `p4 client` to create a client spec used to sync files with the depot +// Returns an error if `p4 client` fails +// error -> error from exec.Cmd +// __|- error -> combined output from `p4 client` +func (p p4Command) createClientSpecP4(p4depot, p4client, p4user, description string) error { + clientSpec := fmt.Sprintf( + clientSpecForm, + p4client, + p4user, + description, + p.workingDir, + p4depot, + p4client, + ) + cmd := p.commandContext("client", "-i") + cmd.Stdin = bytes.NewReader([]byte(clientSpec)) + out, err := cmd.CombinedOutput() + if err != nil { + return errors.Wrap(err, string(out)) + } + return nil +} + +// clones/downloads given files at the given base changelist +// returns an error if the sync or edit fails +// error -> error from exec.Cmd +// __|- error -> combined output from sync or edit +func (p p4Command) cloneAndEditFilesP4(fileList []string, baseChangelistId string) error { + // want to specify the file at the base changelist revision + // build a slice of file names with the changelist id appended + filesWithCid := append([]string(nil), fileList...) + for i := 0; i < len(filesWithCid); i++ { + filesWithCid[i] = filesWithCid[i] + "@" + baseChangelistId + } + if err := p.cloneFilesP4(filesWithCid); err != nil { + return err + } + if err := p.editFilesP4(fileList); err != nil { + return err + } + return nil +} + +// Uses `p4 sync` to copy/clone the given files from the depot to the local workspace +// Returns an error if `p4 sync` fails +// error -> error from exec.Cmd +// __|- error -> combined output from `p4 sync` +func (p p4Command) cloneFilesP4(filesWithCid []string) error { + cmd := p.commandContext("sync") + cmd.Args = append(cmd.Args, filesWithCid...) + out, err := cmd.CombinedOutput() + if err != nil { + return errors.Wrap(err, string(out)) + } + return nil +} + +// Uses `p4 edit` to mark files as being edited +// Returns an error if `p4 edit` fails +// error -> error from exec.Cmd +// __|- error -> combined output from `p4 edit` +func (p p4Command) editFilesP4(fileList []string) error { + cmd := p.commandContext("edit") + cmd.Args = append(cmd.Args, fileList...) + out, err := cmd.CombinedOutput() + if err != nil { + return errors.Wrap(err, string(out)) + } + return nil +} + +// Uses `p4 diff` to get a list of the files that have changed in the workspace +// Returns true if the file list has 1+ files in it +// Returns false if the file list is empty +// Returns an error if `p4 diff` fails +// error -> error from exec.Cmd +// __|- error -> combined output from `p4 diff` +func (p p4Command) areThereChangedFilesP4() (bool, error) { + // use p4 diff to list the changes + diffCmd := p.commandContext("diff", "-f", "-sa") + + // capture the output of `p4 diff` and count the lines + // so that the output can be returned in an error message + out, err := diffCmd.CombinedOutput() + if err != nil { + return false, errors.Wrap(err, string(out)) + } + return len(strings.Split(string(out), "\n")) > 0, nil +} + +// Uses `p4 change -o` to generate a form for the default changelist +// Injects the given `description` into the form. +// All lines of `description` after the first must begin with a tab character. +// Returns an error if `p4 change` fails +// error -> error from exec.Cmd +// __|- error -> combined output from `p4 change` +func (p p4Command) generateChangeFormP4(description string) (string, error) { + cmd := p.commandContext("change", "-o") + out, err := cmd.CombinedOutput() + if err != nil { + return "", errors.Wrap(err, string(out)) + } + // add the commit message to the change form + return strings.Replace(string(out), "", description, 1), nil +} + +var cidPattern = lazyregexp.New(`Change (\d+) files shelved`) + +// Uses `p4 shelve` to shelve a changelist with the given form +// Returns an error if `p4 shelve` fails +// error -> error from exec.Cmd +// __|- error -> combined output from `p4 shelve` +// Returns an error if the output of `p4 shelve` does not contain a changelist id +// error -> "p4 shelve output does not contain a changelist id" +// __|- error -> combined output from `p4 shelve` +func (p p4Command) shelveChangelistP4(changeForm string) (string, error) { + cmd := p.commandContext("shelve", "-i") + changeBuffer := bytes.Buffer{} + changeBuffer.Write([]byte(changeForm)) + cmd.Stdin = &changeBuffer + out, err := cmd.CombinedOutput() + if err != nil { + return "", errors.Wrap(err, string(out)) + } + matches := cidPattern.FindStringSubmatch(string(out)) + if len(matches) != 2 { + return "", errors.Wrap(errors.New("p4 shelve output does not contain a changelist id"), string(out)) + } + return matches[1], nil +} + +// return the deepest error message +// from a wrapped error +// "deepest" is somewhat facetious, as it does only one unwrap +func digErrorMessage(err error) string { + if err == nil { + return "" + } + msg := err.Error() + innerError := errors.Unwrap(err) + if innerError != nil { + msg = innerError.Error() + } + return msg +} + func cleanUpTmpRepo(logger log.Logger, path string) { err := os.RemoveAll(path) if err != nil { diff --git a/cmd/gitserver/server/server.go b/cmd/gitserver/server/server.go index 8e72d2bd19d..40ddfc461f7 100644 --- a/cmd/gitserver/server/server.go +++ b/cmd/gitserver/server/server.go @@ -1867,7 +1867,7 @@ func (s *Server) handleP4Exec(w http.ResponseWriter, r *http.Request) { } // Make sure the subcommand is explicitly allowed - allowlist := []string{"protects", "groups", "users", "group"} + allowlist := []string{"protects", "groups", "users", "group", "changes"} allowed := false for _, arg := range allowlist { if req.Args[0] == arg { diff --git a/cmd/gitserver/server/server_grpc.go b/cmd/gitserver/server/server_grpc.go index effab3d6e19..cf672ad4112 100644 --- a/cmd/gitserver/server/server_grpc.go +++ b/cmd/gitserver/server/server_grpc.go @@ -215,7 +215,7 @@ func (gs *GRPCServer) P4Exec(req *proto.P4ExecRequest, ss proto.GitserverService } // Make sure the subcommand is explicitly allowed - allowlist := []string{"protects", "groups", "users", "group"} + allowlist := []string{"protects", "groups", "users", "group", "changes"} allowed := false for _, arg := range allowlist { if req.Args[0] == arg { diff --git a/deps.bzl b/deps.bzl index 729e742bc05..cd1360bce0a 100644 --- a/deps.bzl +++ b/deps.bzl @@ -1597,62 +1597,14 @@ def go_dependencies(): version = "v1.5.0", ) - go_repository( - name = "com_github_dave_astrid", - build_file_proto_mode = "disable_global", - importpath = "github.com/dave/astrid", - sum = "h1:YI1gOOdmMk3xodBao7fehcvoZsEeOyy/cfhlpCSPgM4=", - version = "v0.0.0-20170323122508-8c2895878b14", - ) - go_repository( - name = "com_github_dave_brenda", - build_file_proto_mode = "disable_global", - importpath = "github.com/dave/brenda", - sum = "h1:Sl1LlwXnbw7xMhq3y2x11McFu43AjDcwkllxxgZ3EZw=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_dave_courtney", - build_file_proto_mode = "disable_global", - importpath = "github.com/dave/courtney", - sum = "h1:8aR1os2ImdIQf3Zj4oro+lD/L4Srb5VwGefqZ/jzz7U=", - version = "v0.3.0", - ) - go_repository( - name = "com_github_dave_gopackages", - build_file_proto_mode = "disable_global", - importpath = "github.com/dave/gopackages", - sum = "h1:l99YKCdrK4Lvb/zTupt0GMPfNbncAGf8Cv/t1sYLOg0=", - version = "v0.0.0-20170318123100-46e7023ec56e", - ) go_repository( name = "com_github_dave_jennifer", build_file_proto_mode = "disable_global", importpath = "github.com/dave/jennifer", - sum = "h1:HmgPN93bVDpkQyYbqhCHj5QlgvUkvEOzMyEvKLgCRrg=", - version = "v1.5.0", - ) - go_repository( - name = "com_github_dave_kerr", - build_file_proto_mode = "disable_global", - importpath = "github.com/dave/kerr", - sum = "h1:xURkGi4RydhyaYR6PzcyHTueQudxY4LgxN1oYEPJHa0=", - version = "v0.0.0-20170318121727-bc25dd6abe8e", - ) - go_repository( - name = "com_github_dave_patsy", - build_file_proto_mode = "disable_global", - importpath = "github.com/dave/patsy", - sum = "h1:1o36L4EKbZzazMk8iGC4kXpVnZ6TPxR2mZ9qVKjNNAs=", - version = "v0.0.0-20210517141501-957256f50cba", - ) - go_repository( - name = "com_github_dave_rebecca", - build_file_proto_mode = "disable_global", - importpath = "github.com/dave/rebecca", - sum = "h1:jxVfdOxRirbXL28vXMvUvJ1in3djwkVKXCq339qhBL0=", - version = "v0.9.1", + sum = "h1:T4T/67t6RAA5AIV6+NP8Uk/BIsXgDoqEowgycdQQLuk=", + version = "v1.6.1", ) + go_repository( name = "com_github_davecgh_go_spew", build_file_proto_mode = "disable_global", @@ -1958,8 +1910,8 @@ def go_dependencies(): name = "com_github_dustin_go_humanize", build_file_proto_mode = "disable_global", importpath = "github.com/dustin/go-humanize", - sum = "h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=", - version = "v1.0.0", + sum = "h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=", + version = "v1.0.1", ) go_repository( @@ -2545,8 +2497,8 @@ def go_dependencies(): name = "com_github_go_logr_logr", build_file_proto_mode = "disable_global", importpath = "github.com/go-logr/logr", - sum = "h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=", - version = "v1.2.3", + sum = "h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=", + version = "v1.2.4", ) go_repository( name = "com_github_go_logr_stdr", @@ -2741,8 +2693,8 @@ def go_dependencies(): name = "com_github_go_task_slim_sprig", build_file_proto_mode = "disable_global", importpath = "github.com/go-task/slim-sprig", - sum = "h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=", - version = "v0.0.0-20210107165309-348f09dbbbc0", + sum = "h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=", + version = "v0.0.0-20230315185526-52ccab3ef572", ) go_repository( @@ -5372,16 +5324,16 @@ def go_dependencies(): name = "com_github_onsi_ginkgo_v2", build_file_proto_mode = "disable_global", importpath = "github.com/onsi/ginkgo/v2", - sum = "h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU=", - version = "v2.1.6", + sum = "h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=", + version = "v2.9.7", ) go_repository( name = "com_github_onsi_gomega", build_file_proto_mode = "disable_global", importpath = "github.com/onsi/gomega", - sum = "h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=", - version = "v1.20.1", + sum = "h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=", + version = "v1.27.8", ) go_repository( @@ -9050,8 +9002,8 @@ def go_dependencies(): name = "org_golang_x_mod", build_file_proto_mode = "disable_global", importpath = "golang.org/x/mod", - sum = "h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=", - version = "v0.8.0", + sum = "h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=", + version = "v0.10.0", ) go_repository( name = "org_golang_x_net", @@ -9072,8 +9024,8 @@ def go_dependencies(): name = "org_golang_x_sync", build_file_proto_mode = "disable_global", importpath = "golang.org/x/sync", - sum = "h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=", - version = "v0.1.0", + sum = "h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=", + version = "v0.2.0", ) go_repository( name = "org_golang_x_sys", @@ -9107,8 +9059,8 @@ def go_dependencies(): name = "org_golang_x_tools", build_file_proto_mode = "disable_global", importpath = "golang.org/x/tools", - sum = "h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=", - version = "v0.6.0", + sum = "h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=", + version = "v0.9.3", ) go_repository( name = "org_golang_x_xerrors", diff --git a/enterprise/cmd/frontend/internal/batches/resolvers/code_host.go b/enterprise/cmd/frontend/internal/batches/resolvers/code_host.go index d173310b19f..56cbc2cfd80 100644 --- a/enterprise/cmd/frontend/internal/batches/resolvers/code_host.go +++ b/enterprise/cmd/frontend/internal/batches/resolvers/code_host.go @@ -66,7 +66,7 @@ func (c *batchChangesCodeHostResolver) RequiresSSH() bool { func (c *batchChangesCodeHostResolver) RequiresUsername() bool { switch c.codeHost.ExternalServiceType { - case extsvc.TypeBitbucketCloud, extsvc.TypeAzureDevOps, extsvc.TypeGerrit: + case extsvc.TypeBitbucketCloud, extsvc.TypeAzureDevOps, extsvc.TypePerforce: return true } diff --git a/enterprise/cmd/frontend/internal/batches/resolvers/resolver.go b/enterprise/cmd/frontend/internal/batches/resolvers/resolver.go index 9d34f81fc19..d8783265c3d 100644 --- a/enterprise/cmd/frontend/internal/batches/resolvers/resolver.go +++ b/enterprise/cmd/frontend/internal/batches/resolvers/resolver.go @@ -1231,6 +1231,13 @@ func (r *Resolver) generateAuthenticatorForCredential(ctx context.Context, exter PublicKey: keypair.PublicKey, Passphrase: keypair.Passphrase, } + } else if externalServiceType == extsvc.TypePerforce { + a = &extsvcauth.BasicAuthWithSSH{ + BasicAuth: extsvcauth.BasicAuth{Username: *username, Password: credential}, + PrivateKey: keypair.PrivateKey, + PublicKey: keypair.PublicKey, + Passphrase: keypair.Passphrase, + } } else { a = &extsvcauth.OAuthBearerTokenWithSSH{ OAuthBearerToken: extsvcauth.OAuthBearerToken{Token: credential}, diff --git a/enterprise/internal/batches/reconciler/executor.go b/enterprise/internal/batches/reconciler/executor.go index 19ed29cbf3c..12c46100050 100644 --- a/enterprise/internal/batches/reconciler/executor.go +++ b/enterprise/internal/batches/reconciler/executor.go @@ -181,6 +181,7 @@ func (e *executor) pushChangesetPatch(ctx context.Context, triggerUpdateWebhook // Create a commit and push it // Figure out which authenticator we should use to modify the changeset. css, err := e.changesetSource(ctx) + if err != nil { return afterDone, err } @@ -213,6 +214,12 @@ func (e *executor) pushChangesetPatch(ctx context.Context, triggerUpdateWebhook } } + // update the changeset's external_id column if a changelist id is returned + // because that's going to make it back to the UI so that the user can see the changelist id and take action on it + if resp != nil && resp.ChangelistId != "" { + e.ch.ExternalID = resp.ChangelistId + } + if err = e.runAfterCommit(ctx, css, resp, remoteRepo, opts); err != nil { return afterDone, errors.Wrap(err, "running after commit routine") } diff --git a/enterprise/internal/batches/sources/BUILD.bazel b/enterprise/internal/batches/sources/BUILD.bazel index 062b3ad4d54..5ba7af496cc 100644 --- a/enterprise/internal/batches/sources/BUILD.bazel +++ b/enterprise/internal/batches/sources/BUILD.bazel @@ -11,6 +11,7 @@ go_library( "gerrit.go", "github.go", "gitlab.go", + "perforce.go", "sources.go", "util.go", ], @@ -39,6 +40,7 @@ go_library( "//internal/extsvc/github/auth", "//internal/extsvc/gitlab", "//internal/extsvc/versions", + "//internal/gitserver", "//internal/gitserver/gitdomain", "//internal/gitserver/protocol", "//internal/httpcli", @@ -64,6 +66,7 @@ go_test( "gitlab_test.go", "main_test.go", "mocks_test.go", + "perforce_test.go", "sources_test.go", ], data = glob(["testdata/**"]), @@ -77,6 +80,7 @@ go_test( "//enterprise/internal/github_apps/store", "//enterprise/internal/github_apps/types", "//internal/api", + "//internal/authz", "//internal/conf", "//internal/database", "//internal/errcode", @@ -89,6 +93,8 @@ go_test( "//internal/extsvc/github", "//internal/extsvc/gitlab", "//internal/extsvc/versions", + "//internal/gitserver", + "//internal/gitserver/gitdomain", "//internal/gitserver/protocol", "//internal/httpcli", "//internal/httptestutil", @@ -105,6 +111,7 @@ go_test( "@com_github_grafana_regexp//:regexp", "@com_github_inconshreveable_log15//:log15", "@com_github_masterminds_semver//:semver", + "@com_github_sourcegraph_go_diff//diff", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//mock", "@com_github_stretchr_testify//require", diff --git a/enterprise/internal/batches/sources/mocks_test.go b/enterprise/internal/batches/sources/mocks_test.go index fa9c2753d7d..59cd65727f4 100644 --- a/enterprise/internal/batches/sources/mocks_test.go +++ b/enterprise/internal/batches/sources/mocks_test.go @@ -8,17 +8,26 @@ package sources import ( "context" + "io" + "io/fs" + "net/http" "net/url" "sync" + "time" + diff "github.com/sourcegraph/go-diff/diff" store "github.com/sourcegraph/sourcegraph/enterprise/internal/batches/store" types1 "github.com/sourcegraph/sourcegraph/enterprise/internal/batches/types" store1 "github.com/sourcegraph/sourcegraph/enterprise/internal/github_apps/store" + api "github.com/sourcegraph/sourcegraph/internal/api" + authz "github.com/sourcegraph/sourcegraph/internal/authz" database "github.com/sourcegraph/sourcegraph/internal/database" auth "github.com/sourcegraph/sourcegraph/internal/extsvc/auth" azuredevops "github.com/sourcegraph/sourcegraph/internal/extsvc/azuredevops" bitbucketcloud "github.com/sourcegraph/sourcegraph/internal/extsvc/bitbucketcloud" gerrit "github.com/sourcegraph/sourcegraph/internal/extsvc/gerrit" + gitserver "github.com/sourcegraph/sourcegraph/internal/gitserver" + gitdomain "github.com/sourcegraph/sourcegraph/internal/gitserver/gitdomain" protocol "github.com/sourcegraph/sourcegraph/internal/gitserver/protocol" types "github.com/sourcegraph/sourcegraph/internal/types" ) @@ -10228,3 +10237,6940 @@ func (c GerritClientWriteReviewCommentFuncCall) Args() []interface{} { func (c GerritClientWriteReviewCommentFuncCall) Results() []interface{} { return []interface{}{c.Result0} } + +// MockGitserverClient is a mock implementation of the Client interface +// (from the package github.com/sourcegraph/sourcegraph/internal/gitserver) +// used for unit testing. +type MockGitserverClient struct { + // AddrForRepoFunc is an instance of a mock function object controlling + // the behavior of the method AddrForRepo. + AddrForRepoFunc *GitserverClientAddrForRepoFunc + // AddrsFunc is an instance of a mock function object controlling the + // behavior of the method Addrs. + AddrsFunc *GitserverClientAddrsFunc + // ArchiveReaderFunc is an instance of a mock function object + // controlling the behavior of the method ArchiveReader. + ArchiveReaderFunc *GitserverClientArchiveReaderFunc + // BatchLogFunc is an instance of a mock function object controlling the + // behavior of the method BatchLog. + BatchLogFunc *GitserverClientBatchLogFunc + // BlameFileFunc is an instance of a mock function object controlling + // the behavior of the method BlameFile. + BlameFileFunc *GitserverClientBlameFileFunc + // BranchesContainingFunc is an instance of a mock function object + // controlling the behavior of the method BranchesContaining. + BranchesContainingFunc *GitserverClientBranchesContainingFunc + // CommitDateFunc is an instance of a mock function object controlling + // the behavior of the method CommitDate. + CommitDateFunc *GitserverClientCommitDateFunc + // CommitExistsFunc is an instance of a mock function object controlling + // the behavior of the method CommitExists. + CommitExistsFunc *GitserverClientCommitExistsFunc + // CommitGraphFunc is an instance of a mock function object controlling + // the behavior of the method CommitGraph. + CommitGraphFunc *GitserverClientCommitGraphFunc + // CommitLogFunc is an instance of a mock function object controlling + // the behavior of the method CommitLog. + CommitLogFunc *GitserverClientCommitLogFunc + // CommitsFunc is an instance of a mock function object controlling the + // behavior of the method Commits. + CommitsFunc *GitserverClientCommitsFunc + // CommitsExistFunc is an instance of a mock function object controlling + // the behavior of the method CommitsExist. + CommitsExistFunc *GitserverClientCommitsExistFunc + // CommitsUniqueToBranchFunc is an instance of a mock function object + // controlling the behavior of the method CommitsUniqueToBranch. + CommitsUniqueToBranchFunc *GitserverClientCommitsUniqueToBranchFunc + // ContributorCountFunc is an instance of a mock function object + // controlling the behavior of the method ContributorCount. + ContributorCountFunc *GitserverClientContributorCountFunc + // CreateCommitFromPatchFunc is an instance of a mock function object + // controlling the behavior of the method CreateCommitFromPatch. + CreateCommitFromPatchFunc *GitserverClientCreateCommitFromPatchFunc + // DiffFunc is an instance of a mock function object controlling the + // behavior of the method Diff. + DiffFunc *GitserverClientDiffFunc + // DiffPathFunc is an instance of a mock function object controlling the + // behavior of the method DiffPath. + DiffPathFunc *GitserverClientDiffPathFunc + // DiffSymbolsFunc is an instance of a mock function object controlling + // the behavior of the method DiffSymbols. + DiffSymbolsFunc *GitserverClientDiffSymbolsFunc + // FirstEverCommitFunc is an instance of a mock function object + // controlling the behavior of the method FirstEverCommit. + FirstEverCommitFunc *GitserverClientFirstEverCommitFunc + // GetBehindAheadFunc is an instance of a mock function object + // controlling the behavior of the method GetBehindAhead. + GetBehindAheadFunc *GitserverClientGetBehindAheadFunc + // GetCommitFunc is an instance of a mock function object controlling + // the behavior of the method GetCommit. + GetCommitFunc *GitserverClientGetCommitFunc + // GetCommitsFunc is an instance of a mock function object controlling + // the behavior of the method GetCommits. + GetCommitsFunc *GitserverClientGetCommitsFunc + // GetDefaultBranchFunc is an instance of a mock function object + // controlling the behavior of the method GetDefaultBranch. + GetDefaultBranchFunc *GitserverClientGetDefaultBranchFunc + // GetObjectFunc is an instance of a mock function object controlling + // the behavior of the method GetObject. + GetObjectFunc *GitserverClientGetObjectFunc + // HasCommitAfterFunc is an instance of a mock function object + // controlling the behavior of the method HasCommitAfter. + HasCommitAfterFunc *GitserverClientHasCommitAfterFunc + // HeadFunc is an instance of a mock function object controlling the + // behavior of the method Head. + HeadFunc *GitserverClientHeadFunc + // IsRepoCloneableFunc is an instance of a mock function object + // controlling the behavior of the method IsRepoCloneable. + IsRepoCloneableFunc *GitserverClientIsRepoCloneableFunc + // ListBranchesFunc is an instance of a mock function object controlling + // the behavior of the method ListBranches. + ListBranchesFunc *GitserverClientListBranchesFunc + // ListDirectoryChildrenFunc is an instance of a mock function object + // controlling the behavior of the method ListDirectoryChildren. + ListDirectoryChildrenFunc *GitserverClientListDirectoryChildrenFunc + // ListFilesFunc is an instance of a mock function object controlling + // the behavior of the method ListFiles. + ListFilesFunc *GitserverClientListFilesFunc + // ListRefsFunc is an instance of a mock function object controlling the + // behavior of the method ListRefs. + ListRefsFunc *GitserverClientListRefsFunc + // ListTagsFunc is an instance of a mock function object controlling the + // behavior of the method ListTags. + ListTagsFunc *GitserverClientListTagsFunc + // LogReverseEachFunc is an instance of a mock function object + // controlling the behavior of the method LogReverseEach. + LogReverseEachFunc *GitserverClientLogReverseEachFunc + // LsFilesFunc is an instance of a mock function object controlling the + // behavior of the method LsFiles. + LsFilesFunc *GitserverClientLsFilesFunc + // MergeBaseFunc is an instance of a mock function object controlling + // the behavior of the method MergeBase. + MergeBaseFunc *GitserverClientMergeBaseFunc + // NewFileReaderFunc is an instance of a mock function object + // controlling the behavior of the method NewFileReader. + NewFileReaderFunc *GitserverClientNewFileReaderFunc + // P4ExecFunc is an instance of a mock function object controlling the + // behavior of the method P4Exec. + P4ExecFunc *GitserverClientP4ExecFunc + // P4GetChangelistFunc is an instance of a mock function object + // controlling the behavior of the method P4GetChangelist. + P4GetChangelistFunc *GitserverClientP4GetChangelistFunc + // ReadDirFunc is an instance of a mock function object controlling the + // behavior of the method ReadDir. + ReadDirFunc *GitserverClientReadDirFunc + // ReadFileFunc is an instance of a mock function object controlling the + // behavior of the method ReadFile. + ReadFileFunc *GitserverClientReadFileFunc + // RefDescriptionsFunc is an instance of a mock function object + // controlling the behavior of the method RefDescriptions. + RefDescriptionsFunc *GitserverClientRefDescriptionsFunc + // RemoveFunc is an instance of a mock function object controlling the + // behavior of the method Remove. + RemoveFunc *GitserverClientRemoveFunc + // RemoveFromFunc is an instance of a mock function object controlling + // the behavior of the method RemoveFrom. + RemoveFromFunc *GitserverClientRemoveFromFunc + // RepoCloneProgressFunc is an instance of a mock function object + // controlling the behavior of the method RepoCloneProgress. + RepoCloneProgressFunc *GitserverClientRepoCloneProgressFunc + // ReposStatsFunc is an instance of a mock function object controlling + // the behavior of the method ReposStats. + ReposStatsFunc *GitserverClientReposStatsFunc + // RequestRepoCloneFunc is an instance of a mock function object + // controlling the behavior of the method RequestRepoClone. + RequestRepoCloneFunc *GitserverClientRequestRepoCloneFunc + // RequestRepoUpdateFunc is an instance of a mock function object + // controlling the behavior of the method RequestRepoUpdate. + RequestRepoUpdateFunc *GitserverClientRequestRepoUpdateFunc + // ResolveRevisionFunc is an instance of a mock function object + // controlling the behavior of the method ResolveRevision. + ResolveRevisionFunc *GitserverClientResolveRevisionFunc + // ResolveRevisionsFunc is an instance of a mock function object + // controlling the behavior of the method ResolveRevisions. + ResolveRevisionsFunc *GitserverClientResolveRevisionsFunc + // RevListFunc is an instance of a mock function object controlling the + // behavior of the method RevList. + RevListFunc *GitserverClientRevListFunc + // SearchFunc is an instance of a mock function object controlling the + // behavior of the method Search. + SearchFunc *GitserverClientSearchFunc + // StatFunc is an instance of a mock function object controlling the + // behavior of the method Stat. + StatFunc *GitserverClientStatFunc + // StreamBlameFileFunc is an instance of a mock function object + // controlling the behavior of the method StreamBlameFile. + StreamBlameFileFunc *GitserverClientStreamBlameFileFunc +} + +// NewMockGitserverClient creates a new mock of the Client interface. All +// methods return zero values for all results, unless overwritten. +func NewMockGitserverClient() *MockGitserverClient { + return &MockGitserverClient{ + AddrForRepoFunc: &GitserverClientAddrForRepoFunc{ + defaultHook: func(api.RepoName) (r0 string) { + return + }, + }, + AddrsFunc: &GitserverClientAddrsFunc{ + defaultHook: func() (r0 []string) { + return + }, + }, + ArchiveReaderFunc: &GitserverClientArchiveReaderFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.ArchiveOptions) (r0 io.ReadCloser, r1 error) { + return + }, + }, + BatchLogFunc: &GitserverClientBatchLogFunc{ + defaultHook: func(context.Context, gitserver.BatchLogOptions, gitserver.BatchLogCallback) (r0 error) { + return + }, + }, + BlameFileFunc: &GitserverClientBlameFileFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) (r0 []*gitserver.Hunk, r1 error) { + return + }, + }, + BranchesContainingFunc: &GitserverClientBranchesContainingFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (r0 []string, r1 error) { + return + }, + }, + CommitDateFunc: &GitserverClientCommitDateFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (r0 string, r1 time.Time, r2 bool, r3 error) { + return + }, + }, + CommitExistsFunc: &GitserverClientCommitExistsFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (r0 bool, r1 error) { + return + }, + }, + CommitGraphFunc: &GitserverClientCommitGraphFunc{ + defaultHook: func(context.Context, api.RepoName, gitserver.CommitGraphOptions) (r0 *gitdomain.CommitGraph, r1 error) { + return + }, + }, + CommitLogFunc: &GitserverClientCommitLogFunc{ + defaultHook: func(context.Context, api.RepoName, time.Time) (r0 []gitserver.CommitLog, r1 error) { + return + }, + }, + CommitsFunc: &GitserverClientCommitsFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.CommitsOptions) (r0 []*gitdomain.Commit, r1 error) { + return + }, + }, + CommitsExistFunc: &GitserverClientCommitsExistFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit) (r0 []bool, r1 error) { + return + }, + }, + CommitsUniqueToBranchFunc: &GitserverClientCommitsUniqueToBranchFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, bool, *time.Time) (r0 map[string]time.Time, r1 error) { + return + }, + }, + ContributorCountFunc: &GitserverClientContributorCountFunc{ + defaultHook: func(context.Context, api.RepoName, gitserver.ContributorOptions) (r0 []*gitdomain.ContributorCount, r1 error) { + return + }, + }, + CreateCommitFromPatchFunc: &GitserverClientCreateCommitFromPatchFunc{ + defaultHook: func(context.Context, protocol.CreateCommitFromPatchRequest) (r0 *protocol.CreateCommitFromPatchResponse, r1 error) { + return + }, + }, + DiffFunc: &GitserverClientDiffFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, gitserver.DiffOptions) (r0 *gitserver.DiffFileIterator, r1 error) { + return + }, + }, + DiffPathFunc: &GitserverClientDiffPathFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string, string) (r0 []*diff.Hunk, r1 error) { + return + }, + }, + DiffSymbolsFunc: &GitserverClientDiffSymbolsFunc{ + defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) (r0 []byte, r1 error) { + return + }, + }, + FirstEverCommitFunc: &GitserverClientFirstEverCommitFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (r0 *gitdomain.Commit, r1 error) { + return + }, + }, + GetBehindAheadFunc: &GitserverClientGetBehindAheadFunc{ + defaultHook: func(context.Context, api.RepoName, string, string) (r0 *gitdomain.BehindAhead, r1 error) { + return + }, + }, + GetCommitFunc: &GitserverClientGetCommitFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, gitserver.ResolveRevisionOptions) (r0 *gitdomain.Commit, r1 error) { + return + }, + }, + GetCommitsFunc: &GitserverClientGetCommitsFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit, bool) (r0 []*gitdomain.Commit, r1 error) { + return + }, + }, + GetDefaultBranchFunc: &GitserverClientGetDefaultBranchFunc{ + defaultHook: func(context.Context, api.RepoName, bool) (r0 string, r1 api.CommitID, r2 error) { + return + }, + }, + GetObjectFunc: &GitserverClientGetObjectFunc{ + defaultHook: func(context.Context, api.RepoName, string) (r0 *gitdomain.GitObject, r1 error) { + return + }, + }, + HasCommitAfterFunc: &GitserverClientHasCommitAfterFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string) (r0 bool, r1 error) { + return + }, + }, + HeadFunc: &GitserverClientHeadFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (r0 string, r1 bool, r2 error) { + return + }, + }, + IsRepoCloneableFunc: &GitserverClientIsRepoCloneableFunc{ + defaultHook: func(context.Context, api.RepoName) (r0 error) { + return + }, + }, + ListBranchesFunc: &GitserverClientListBranchesFunc{ + defaultHook: func(context.Context, api.RepoName, gitserver.BranchesOptions) (r0 []*gitdomain.Branch, r1 error) { + return + }, + }, + ListDirectoryChildrenFunc: &GitserverClientListDirectoryChildrenFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, []string) (r0 map[string][]string, r1 error) { + return + }, + }, + ListFilesFunc: &GitserverClientListFilesFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, *protocol.ListFilesOpts) (r0 []string, r1 error) { + return + }, + }, + ListRefsFunc: &GitserverClientListRefsFunc{ + defaultHook: func(context.Context, api.RepoName) (r0 []gitdomain.Ref, r1 error) { + return + }, + }, + ListTagsFunc: &GitserverClientListTagsFunc{ + defaultHook: func(context.Context, api.RepoName, ...string) (r0 []*gitdomain.Tag, r1 error) { + return + }, + }, + LogReverseEachFunc: &GitserverClientLogReverseEachFunc{ + defaultHook: func(context.Context, string, string, int, func(entry gitdomain.LogEntry) error) (r0 error) { + return + }, + }, + LsFilesFunc: &GitserverClientLsFilesFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, ...gitdomain.Pathspec) (r0 []string, r1 error) { + return + }, + }, + MergeBaseFunc: &GitserverClientMergeBaseFunc{ + defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) (r0 api.CommitID, r1 error) { + return + }, + }, + NewFileReaderFunc: &GitserverClientNewFileReaderFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (r0 io.ReadCloser, r1 error) { + return + }, + }, + P4ExecFunc: &GitserverClientP4ExecFunc{ + defaultHook: func(context.Context, string, string, string, ...string) (r0 io.ReadCloser, r1 http.Header, r2 error) { + return + }, + }, + P4GetChangelistFunc: &GitserverClientP4GetChangelistFunc{ + defaultHook: func(context.Context, string, gitserver.PerforceCredentials) (r0 *protocol.PerforceChangelist, r1 error) { + return + }, + }, + ReadDirFunc: &GitserverClientReadDirFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string, bool) (r0 []fs.FileInfo, r1 error) { + return + }, + }, + ReadFileFunc: &GitserverClientReadFileFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (r0 []byte, r1 error) { + return + }, + }, + RefDescriptionsFunc: &GitserverClientRefDescriptionsFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, ...string) (r0 map[string][]gitdomain.RefDescription, r1 error) { + return + }, + }, + RemoveFunc: &GitserverClientRemoveFunc{ + defaultHook: func(context.Context, api.RepoName) (r0 error) { + return + }, + }, + RemoveFromFunc: &GitserverClientRemoveFromFunc{ + defaultHook: func(context.Context, api.RepoName, string) (r0 error) { + return + }, + }, + RepoCloneProgressFunc: &GitserverClientRepoCloneProgressFunc{ + defaultHook: func(context.Context, ...api.RepoName) (r0 *protocol.RepoCloneProgressResponse, r1 error) { + return + }, + }, + ReposStatsFunc: &GitserverClientReposStatsFunc{ + defaultHook: func(context.Context) (r0 map[string]*protocol.ReposStats, r1 error) { + return + }, + }, + RequestRepoCloneFunc: &GitserverClientRequestRepoCloneFunc{ + defaultHook: func(context.Context, api.RepoName) (r0 *protocol.RepoCloneResponse, r1 error) { + return + }, + }, + RequestRepoUpdateFunc: &GitserverClientRequestRepoUpdateFunc{ + defaultHook: func(context.Context, api.RepoName, time.Duration) (r0 *protocol.RepoUpdateResponse, r1 error) { + return + }, + }, + ResolveRevisionFunc: &GitserverClientResolveRevisionFunc{ + defaultHook: func(context.Context, api.RepoName, string, gitserver.ResolveRevisionOptions) (r0 api.CommitID, r1 error) { + return + }, + }, + ResolveRevisionsFunc: &GitserverClientResolveRevisionsFunc{ + defaultHook: func(context.Context, api.RepoName, []protocol.RevisionSpecifier) (r0 []string, r1 error) { + return + }, + }, + RevListFunc: &GitserverClientRevListFunc{ + defaultHook: func(context.Context, string, string, func(commit string) (bool, error)) (r0 error) { + return + }, + }, + SearchFunc: &GitserverClientSearchFunc{ + defaultHook: func(context.Context, *protocol.SearchRequest, func([]protocol.CommitMatch)) (r0 bool, r1 error) { + return + }, + }, + StatFunc: &GitserverClientStatFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (r0 fs.FileInfo, r1 error) { + return + }, + }, + StreamBlameFileFunc: &GitserverClientStreamBlameFileFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) (r0 gitserver.HunkReader, r1 error) { + return + }, + }, + } +} + +// NewStrictMockGitserverClient creates a new mock of the Client interface. +// All methods panic on invocation, unless overwritten. +func NewStrictMockGitserverClient() *MockGitserverClient { + return &MockGitserverClient{ + AddrForRepoFunc: &GitserverClientAddrForRepoFunc{ + defaultHook: func(api.RepoName) string { + panic("unexpected invocation of MockGitserverClient.AddrForRepo") + }, + }, + AddrsFunc: &GitserverClientAddrsFunc{ + defaultHook: func() []string { + panic("unexpected invocation of MockGitserverClient.Addrs") + }, + }, + ArchiveReaderFunc: &GitserverClientArchiveReaderFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.ArchiveOptions) (io.ReadCloser, error) { + panic("unexpected invocation of MockGitserverClient.ArchiveReader") + }, + }, + BatchLogFunc: &GitserverClientBatchLogFunc{ + defaultHook: func(context.Context, gitserver.BatchLogOptions, gitserver.BatchLogCallback) error { + panic("unexpected invocation of MockGitserverClient.BatchLog") + }, + }, + BlameFileFunc: &GitserverClientBlameFileFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) ([]*gitserver.Hunk, error) { + panic("unexpected invocation of MockGitserverClient.BlameFile") + }, + }, + BranchesContainingFunc: &GitserverClientBranchesContainingFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) ([]string, error) { + panic("unexpected invocation of MockGitserverClient.BranchesContaining") + }, + }, + CommitDateFunc: &GitserverClientCommitDateFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (string, time.Time, bool, error) { + panic("unexpected invocation of MockGitserverClient.CommitDate") + }, + }, + CommitExistsFunc: &GitserverClientCommitExistsFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (bool, error) { + panic("unexpected invocation of MockGitserverClient.CommitExists") + }, + }, + CommitGraphFunc: &GitserverClientCommitGraphFunc{ + defaultHook: func(context.Context, api.RepoName, gitserver.CommitGraphOptions) (*gitdomain.CommitGraph, error) { + panic("unexpected invocation of MockGitserverClient.CommitGraph") + }, + }, + CommitLogFunc: &GitserverClientCommitLogFunc{ + defaultHook: func(context.Context, api.RepoName, time.Time) ([]gitserver.CommitLog, error) { + panic("unexpected invocation of MockGitserverClient.CommitLog") + }, + }, + CommitsFunc: &GitserverClientCommitsFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.CommitsOptions) ([]*gitdomain.Commit, error) { + panic("unexpected invocation of MockGitserverClient.Commits") + }, + }, + CommitsExistFunc: &GitserverClientCommitsExistFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit) ([]bool, error) { + panic("unexpected invocation of MockGitserverClient.CommitsExist") + }, + }, + CommitsUniqueToBranchFunc: &GitserverClientCommitsUniqueToBranchFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, bool, *time.Time) (map[string]time.Time, error) { + panic("unexpected invocation of MockGitserverClient.CommitsUniqueToBranch") + }, + }, + ContributorCountFunc: &GitserverClientContributorCountFunc{ + defaultHook: func(context.Context, api.RepoName, gitserver.ContributorOptions) ([]*gitdomain.ContributorCount, error) { + panic("unexpected invocation of MockGitserverClient.ContributorCount") + }, + }, + CreateCommitFromPatchFunc: &GitserverClientCreateCommitFromPatchFunc{ + defaultHook: func(context.Context, protocol.CreateCommitFromPatchRequest) (*protocol.CreateCommitFromPatchResponse, error) { + panic("unexpected invocation of MockGitserverClient.CreateCommitFromPatch") + }, + }, + DiffFunc: &GitserverClientDiffFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, gitserver.DiffOptions) (*gitserver.DiffFileIterator, error) { + panic("unexpected invocation of MockGitserverClient.Diff") + }, + }, + DiffPathFunc: &GitserverClientDiffPathFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string, string) ([]*diff.Hunk, error) { + panic("unexpected invocation of MockGitserverClient.DiffPath") + }, + }, + DiffSymbolsFunc: &GitserverClientDiffSymbolsFunc{ + defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) ([]byte, error) { + panic("unexpected invocation of MockGitserverClient.DiffSymbols") + }, + }, + FirstEverCommitFunc: &GitserverClientFirstEverCommitFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (*gitdomain.Commit, error) { + panic("unexpected invocation of MockGitserverClient.FirstEverCommit") + }, + }, + GetBehindAheadFunc: &GitserverClientGetBehindAheadFunc{ + defaultHook: func(context.Context, api.RepoName, string, string) (*gitdomain.BehindAhead, error) { + panic("unexpected invocation of MockGitserverClient.GetBehindAhead") + }, + }, + GetCommitFunc: &GitserverClientGetCommitFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, gitserver.ResolveRevisionOptions) (*gitdomain.Commit, error) { + panic("unexpected invocation of MockGitserverClient.GetCommit") + }, + }, + GetCommitsFunc: &GitserverClientGetCommitsFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit, bool) ([]*gitdomain.Commit, error) { + panic("unexpected invocation of MockGitserverClient.GetCommits") + }, + }, + GetDefaultBranchFunc: &GitserverClientGetDefaultBranchFunc{ + defaultHook: func(context.Context, api.RepoName, bool) (string, api.CommitID, error) { + panic("unexpected invocation of MockGitserverClient.GetDefaultBranch") + }, + }, + GetObjectFunc: &GitserverClientGetObjectFunc{ + defaultHook: func(context.Context, api.RepoName, string) (*gitdomain.GitObject, error) { + panic("unexpected invocation of MockGitserverClient.GetObject") + }, + }, + HasCommitAfterFunc: &GitserverClientHasCommitAfterFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string) (bool, error) { + panic("unexpected invocation of MockGitserverClient.HasCommitAfter") + }, + }, + HeadFunc: &GitserverClientHeadFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (string, bool, error) { + panic("unexpected invocation of MockGitserverClient.Head") + }, + }, + IsRepoCloneableFunc: &GitserverClientIsRepoCloneableFunc{ + defaultHook: func(context.Context, api.RepoName) error { + panic("unexpected invocation of MockGitserverClient.IsRepoCloneable") + }, + }, + ListBranchesFunc: &GitserverClientListBranchesFunc{ + defaultHook: func(context.Context, api.RepoName, gitserver.BranchesOptions) ([]*gitdomain.Branch, error) { + panic("unexpected invocation of MockGitserverClient.ListBranches") + }, + }, + ListDirectoryChildrenFunc: &GitserverClientListDirectoryChildrenFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, []string) (map[string][]string, error) { + panic("unexpected invocation of MockGitserverClient.ListDirectoryChildren") + }, + }, + ListFilesFunc: &GitserverClientListFilesFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, *protocol.ListFilesOpts) ([]string, error) { + panic("unexpected invocation of MockGitserverClient.ListFiles") + }, + }, + ListRefsFunc: &GitserverClientListRefsFunc{ + defaultHook: func(context.Context, api.RepoName) ([]gitdomain.Ref, error) { + panic("unexpected invocation of MockGitserverClient.ListRefs") + }, + }, + ListTagsFunc: &GitserverClientListTagsFunc{ + defaultHook: func(context.Context, api.RepoName, ...string) ([]*gitdomain.Tag, error) { + panic("unexpected invocation of MockGitserverClient.ListTags") + }, + }, + LogReverseEachFunc: &GitserverClientLogReverseEachFunc{ + defaultHook: func(context.Context, string, string, int, func(entry gitdomain.LogEntry) error) error { + panic("unexpected invocation of MockGitserverClient.LogReverseEach") + }, + }, + LsFilesFunc: &GitserverClientLsFilesFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, ...gitdomain.Pathspec) ([]string, error) { + panic("unexpected invocation of MockGitserverClient.LsFiles") + }, + }, + MergeBaseFunc: &GitserverClientMergeBaseFunc{ + defaultHook: func(context.Context, api.RepoName, api.CommitID, api.CommitID) (api.CommitID, error) { + panic("unexpected invocation of MockGitserverClient.MergeBase") + }, + }, + NewFileReaderFunc: &GitserverClientNewFileReaderFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (io.ReadCloser, error) { + panic("unexpected invocation of MockGitserverClient.NewFileReader") + }, + }, + P4ExecFunc: &GitserverClientP4ExecFunc{ + defaultHook: func(context.Context, string, string, string, ...string) (io.ReadCloser, http.Header, error) { + panic("unexpected invocation of MockGitserverClient.P4Exec") + }, + }, + P4GetChangelistFunc: &GitserverClientP4GetChangelistFunc{ + defaultHook: func(context.Context, string, gitserver.PerforceCredentials) (*protocol.PerforceChangelist, error) { + panic("unexpected invocation of MockGitserverClient.P4GetChangelist") + }, + }, + ReadDirFunc: &GitserverClientReadDirFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string, bool) ([]fs.FileInfo, error) { + panic("unexpected invocation of MockGitserverClient.ReadDir") + }, + }, + ReadFileFunc: &GitserverClientReadFileFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) ([]byte, error) { + panic("unexpected invocation of MockGitserverClient.ReadFile") + }, + }, + RefDescriptionsFunc: &GitserverClientRefDescriptionsFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, ...string) (map[string][]gitdomain.RefDescription, error) { + panic("unexpected invocation of MockGitserverClient.RefDescriptions") + }, + }, + RemoveFunc: &GitserverClientRemoveFunc{ + defaultHook: func(context.Context, api.RepoName) error { + panic("unexpected invocation of MockGitserverClient.Remove") + }, + }, + RemoveFromFunc: &GitserverClientRemoveFromFunc{ + defaultHook: func(context.Context, api.RepoName, string) error { + panic("unexpected invocation of MockGitserverClient.RemoveFrom") + }, + }, + RepoCloneProgressFunc: &GitserverClientRepoCloneProgressFunc{ + defaultHook: func(context.Context, ...api.RepoName) (*protocol.RepoCloneProgressResponse, error) { + panic("unexpected invocation of MockGitserverClient.RepoCloneProgress") + }, + }, + ReposStatsFunc: &GitserverClientReposStatsFunc{ + defaultHook: func(context.Context) (map[string]*protocol.ReposStats, error) { + panic("unexpected invocation of MockGitserverClient.ReposStats") + }, + }, + RequestRepoCloneFunc: &GitserverClientRequestRepoCloneFunc{ + defaultHook: func(context.Context, api.RepoName) (*protocol.RepoCloneResponse, error) { + panic("unexpected invocation of MockGitserverClient.RequestRepoClone") + }, + }, + RequestRepoUpdateFunc: &GitserverClientRequestRepoUpdateFunc{ + defaultHook: func(context.Context, api.RepoName, time.Duration) (*protocol.RepoUpdateResponse, error) { + panic("unexpected invocation of MockGitserverClient.RequestRepoUpdate") + }, + }, + ResolveRevisionFunc: &GitserverClientResolveRevisionFunc{ + defaultHook: func(context.Context, api.RepoName, string, gitserver.ResolveRevisionOptions) (api.CommitID, error) { + panic("unexpected invocation of MockGitserverClient.ResolveRevision") + }, + }, + ResolveRevisionsFunc: &GitserverClientResolveRevisionsFunc{ + defaultHook: func(context.Context, api.RepoName, []protocol.RevisionSpecifier) ([]string, error) { + panic("unexpected invocation of MockGitserverClient.ResolveRevisions") + }, + }, + RevListFunc: &GitserverClientRevListFunc{ + defaultHook: func(context.Context, string, string, func(commit string) (bool, error)) error { + panic("unexpected invocation of MockGitserverClient.RevList") + }, + }, + SearchFunc: &GitserverClientSearchFunc{ + defaultHook: func(context.Context, *protocol.SearchRequest, func([]protocol.CommitMatch)) (bool, error) { + panic("unexpected invocation of MockGitserverClient.Search") + }, + }, + StatFunc: &GitserverClientStatFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (fs.FileInfo, error) { + panic("unexpected invocation of MockGitserverClient.Stat") + }, + }, + StreamBlameFileFunc: &GitserverClientStreamBlameFileFunc{ + defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) (gitserver.HunkReader, error) { + panic("unexpected invocation of MockGitserverClient.StreamBlameFile") + }, + }, + } +} + +// NewMockGitserverClientFrom creates a new mock of the MockGitserverClient +// interface. All methods delegate to the given implementation, unless +// overwritten. +func NewMockGitserverClientFrom(i gitserver.Client) *MockGitserverClient { + return &MockGitserverClient{ + AddrForRepoFunc: &GitserverClientAddrForRepoFunc{ + defaultHook: i.AddrForRepo, + }, + AddrsFunc: &GitserverClientAddrsFunc{ + defaultHook: i.Addrs, + }, + ArchiveReaderFunc: &GitserverClientArchiveReaderFunc{ + defaultHook: i.ArchiveReader, + }, + BatchLogFunc: &GitserverClientBatchLogFunc{ + defaultHook: i.BatchLog, + }, + BlameFileFunc: &GitserverClientBlameFileFunc{ + defaultHook: i.BlameFile, + }, + BranchesContainingFunc: &GitserverClientBranchesContainingFunc{ + defaultHook: i.BranchesContaining, + }, + CommitDateFunc: &GitserverClientCommitDateFunc{ + defaultHook: i.CommitDate, + }, + CommitExistsFunc: &GitserverClientCommitExistsFunc{ + defaultHook: i.CommitExists, + }, + CommitGraphFunc: &GitserverClientCommitGraphFunc{ + defaultHook: i.CommitGraph, + }, + CommitLogFunc: &GitserverClientCommitLogFunc{ + defaultHook: i.CommitLog, + }, + CommitsFunc: &GitserverClientCommitsFunc{ + defaultHook: i.Commits, + }, + CommitsExistFunc: &GitserverClientCommitsExistFunc{ + defaultHook: i.CommitsExist, + }, + CommitsUniqueToBranchFunc: &GitserverClientCommitsUniqueToBranchFunc{ + defaultHook: i.CommitsUniqueToBranch, + }, + ContributorCountFunc: &GitserverClientContributorCountFunc{ + defaultHook: i.ContributorCount, + }, + CreateCommitFromPatchFunc: &GitserverClientCreateCommitFromPatchFunc{ + defaultHook: i.CreateCommitFromPatch, + }, + DiffFunc: &GitserverClientDiffFunc{ + defaultHook: i.Diff, + }, + DiffPathFunc: &GitserverClientDiffPathFunc{ + defaultHook: i.DiffPath, + }, + DiffSymbolsFunc: &GitserverClientDiffSymbolsFunc{ + defaultHook: i.DiffSymbols, + }, + FirstEverCommitFunc: &GitserverClientFirstEverCommitFunc{ + defaultHook: i.FirstEverCommit, + }, + GetBehindAheadFunc: &GitserverClientGetBehindAheadFunc{ + defaultHook: i.GetBehindAhead, + }, + GetCommitFunc: &GitserverClientGetCommitFunc{ + defaultHook: i.GetCommit, + }, + GetCommitsFunc: &GitserverClientGetCommitsFunc{ + defaultHook: i.GetCommits, + }, + GetDefaultBranchFunc: &GitserverClientGetDefaultBranchFunc{ + defaultHook: i.GetDefaultBranch, + }, + GetObjectFunc: &GitserverClientGetObjectFunc{ + defaultHook: i.GetObject, + }, + HasCommitAfterFunc: &GitserverClientHasCommitAfterFunc{ + defaultHook: i.HasCommitAfter, + }, + HeadFunc: &GitserverClientHeadFunc{ + defaultHook: i.Head, + }, + IsRepoCloneableFunc: &GitserverClientIsRepoCloneableFunc{ + defaultHook: i.IsRepoCloneable, + }, + ListBranchesFunc: &GitserverClientListBranchesFunc{ + defaultHook: i.ListBranches, + }, + ListDirectoryChildrenFunc: &GitserverClientListDirectoryChildrenFunc{ + defaultHook: i.ListDirectoryChildren, + }, + ListFilesFunc: &GitserverClientListFilesFunc{ + defaultHook: i.ListFiles, + }, + ListRefsFunc: &GitserverClientListRefsFunc{ + defaultHook: i.ListRefs, + }, + ListTagsFunc: &GitserverClientListTagsFunc{ + defaultHook: i.ListTags, + }, + LogReverseEachFunc: &GitserverClientLogReverseEachFunc{ + defaultHook: i.LogReverseEach, + }, + LsFilesFunc: &GitserverClientLsFilesFunc{ + defaultHook: i.LsFiles, + }, + MergeBaseFunc: &GitserverClientMergeBaseFunc{ + defaultHook: i.MergeBase, + }, + NewFileReaderFunc: &GitserverClientNewFileReaderFunc{ + defaultHook: i.NewFileReader, + }, + P4ExecFunc: &GitserverClientP4ExecFunc{ + defaultHook: i.P4Exec, + }, + P4GetChangelistFunc: &GitserverClientP4GetChangelistFunc{ + defaultHook: i.P4GetChangelist, + }, + ReadDirFunc: &GitserverClientReadDirFunc{ + defaultHook: i.ReadDir, + }, + ReadFileFunc: &GitserverClientReadFileFunc{ + defaultHook: i.ReadFile, + }, + RefDescriptionsFunc: &GitserverClientRefDescriptionsFunc{ + defaultHook: i.RefDescriptions, + }, + RemoveFunc: &GitserverClientRemoveFunc{ + defaultHook: i.Remove, + }, + RemoveFromFunc: &GitserverClientRemoveFromFunc{ + defaultHook: i.RemoveFrom, + }, + RepoCloneProgressFunc: &GitserverClientRepoCloneProgressFunc{ + defaultHook: i.RepoCloneProgress, + }, + ReposStatsFunc: &GitserverClientReposStatsFunc{ + defaultHook: i.ReposStats, + }, + RequestRepoCloneFunc: &GitserverClientRequestRepoCloneFunc{ + defaultHook: i.RequestRepoClone, + }, + RequestRepoUpdateFunc: &GitserverClientRequestRepoUpdateFunc{ + defaultHook: i.RequestRepoUpdate, + }, + ResolveRevisionFunc: &GitserverClientResolveRevisionFunc{ + defaultHook: i.ResolveRevision, + }, + ResolveRevisionsFunc: &GitserverClientResolveRevisionsFunc{ + defaultHook: i.ResolveRevisions, + }, + RevListFunc: &GitserverClientRevListFunc{ + defaultHook: i.RevList, + }, + SearchFunc: &GitserverClientSearchFunc{ + defaultHook: i.Search, + }, + StatFunc: &GitserverClientStatFunc{ + defaultHook: i.Stat, + }, + StreamBlameFileFunc: &GitserverClientStreamBlameFileFunc{ + defaultHook: i.StreamBlameFile, + }, + } +} + +// GitserverClientAddrForRepoFunc describes the behavior when the +// AddrForRepo method of the parent MockGitserverClient instance is invoked. +type GitserverClientAddrForRepoFunc struct { + defaultHook func(api.RepoName) string + hooks []func(api.RepoName) string + history []GitserverClientAddrForRepoFuncCall + mutex sync.Mutex +} + +// AddrForRepo delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) AddrForRepo(v0 api.RepoName) string { + r0 := m.AddrForRepoFunc.nextHook()(v0) + m.AddrForRepoFunc.appendCall(GitserverClientAddrForRepoFuncCall{v0, r0}) + return r0 +} + +// SetDefaultHook sets function that is called when the AddrForRepo method +// of the parent MockGitserverClient instance is invoked and the hook queue +// is empty. +func (f *GitserverClientAddrForRepoFunc) SetDefaultHook(hook func(api.RepoName) string) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// AddrForRepo 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 *GitserverClientAddrForRepoFunc) PushHook(hook func(api.RepoName) string) { + 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 *GitserverClientAddrForRepoFunc) SetDefaultReturn(r0 string) { + f.SetDefaultHook(func(api.RepoName) string { + return r0 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientAddrForRepoFunc) PushReturn(r0 string) { + f.PushHook(func(api.RepoName) string { + return r0 + }) +} + +func (f *GitserverClientAddrForRepoFunc) nextHook() func(api.RepoName) string { + 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 *GitserverClientAddrForRepoFunc) appendCall(r0 GitserverClientAddrForRepoFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientAddrForRepoFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientAddrForRepoFunc) History() []GitserverClientAddrForRepoFuncCall { + f.mutex.Lock() + history := make([]GitserverClientAddrForRepoFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientAddrForRepoFuncCall is an object that describes an +// invocation of method AddrForRepo on an instance of MockGitserverClient. +type GitserverClientAddrForRepoFuncCall struct { + // Arg0 is the value of the 1st argument passed to this method + // invocation. + Arg0 api.RepoName + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 string +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c GitserverClientAddrForRepoFuncCall) Args() []interface{} { + return []interface{}{c.Arg0} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientAddrForRepoFuncCall) Results() []interface{} { + return []interface{}{c.Result0} +} + +// GitserverClientAddrsFunc describes the behavior when the Addrs method of +// the parent MockGitserverClient instance is invoked. +type GitserverClientAddrsFunc struct { + defaultHook func() []string + hooks []func() []string + history []GitserverClientAddrsFuncCall + mutex sync.Mutex +} + +// Addrs delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) Addrs() []string { + r0 := m.AddrsFunc.nextHook()() + m.AddrsFunc.appendCall(GitserverClientAddrsFuncCall{r0}) + return r0 +} + +// SetDefaultHook sets function that is called when the Addrs method of the +// parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientAddrsFunc) SetDefaultHook(hook func() []string) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// Addrs 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 *GitserverClientAddrsFunc) PushHook(hook func() []string) { + 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 *GitserverClientAddrsFunc) SetDefaultReturn(r0 []string) { + f.SetDefaultHook(func() []string { + return r0 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientAddrsFunc) PushReturn(r0 []string) { + f.PushHook(func() []string { + return r0 + }) +} + +func (f *GitserverClientAddrsFunc) nextHook() func() []string { + 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 *GitserverClientAddrsFunc) appendCall(r0 GitserverClientAddrsFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientAddrsFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientAddrsFunc) History() []GitserverClientAddrsFuncCall { + f.mutex.Lock() + history := make([]GitserverClientAddrsFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientAddrsFuncCall is an object that describes an invocation of +// method Addrs on an instance of MockGitserverClient. +type GitserverClientAddrsFuncCall struct { + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []string +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c GitserverClientAddrsFuncCall) Args() []interface{} { + return []interface{}{} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientAddrsFuncCall) Results() []interface{} { + return []interface{}{c.Result0} +} + +// GitserverClientArchiveReaderFunc describes the behavior when the +// ArchiveReader method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientArchiveReaderFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.ArchiveOptions) (io.ReadCloser, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.ArchiveOptions) (io.ReadCloser, error) + history []GitserverClientArchiveReaderFuncCall + mutex sync.Mutex +} + +// ArchiveReader delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) ArchiveReader(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 gitserver.ArchiveOptions) (io.ReadCloser, error) { + r0, r1 := m.ArchiveReaderFunc.nextHook()(v0, v1, v2, v3) + m.ArchiveReaderFunc.appendCall(GitserverClientArchiveReaderFuncCall{v0, v1, v2, v3, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the ArchiveReader method +// of the parent MockGitserverClient instance is invoked and the hook queue +// is empty. +func (f *GitserverClientArchiveReaderFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.ArchiveOptions) (io.ReadCloser, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ArchiveReader 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 *GitserverClientArchiveReaderFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.ArchiveOptions) (io.ReadCloser, 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 *GitserverClientArchiveReaderFunc) SetDefaultReturn(r0 io.ReadCloser, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.ArchiveOptions) (io.ReadCloser, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientArchiveReaderFunc) PushReturn(r0 io.ReadCloser, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.ArchiveOptions) (io.ReadCloser, error) { + return r0, r1 + }) +} + +func (f *GitserverClientArchiveReaderFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.ArchiveOptions) (io.ReadCloser, 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 *GitserverClientArchiveReaderFunc) appendCall(r0 GitserverClientArchiveReaderFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientArchiveReaderFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientArchiveReaderFunc) History() []GitserverClientArchiveReaderFuncCall { + f.mutex.Lock() + history := make([]GitserverClientArchiveReaderFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientArchiveReaderFuncCall is an object that describes an +// invocation of method ArchiveReader on an instance of MockGitserverClient. +type GitserverClientArchiveReaderFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 gitserver.ArchiveOptions + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 io.ReadCloser + // 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 GitserverClientArchiveReaderFuncCall) 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 GitserverClientArchiveReaderFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientBatchLogFunc describes the behavior when the BatchLog +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientBatchLogFunc struct { + defaultHook func(context.Context, gitserver.BatchLogOptions, gitserver.BatchLogCallback) error + hooks []func(context.Context, gitserver.BatchLogOptions, gitserver.BatchLogCallback) error + history []GitserverClientBatchLogFuncCall + mutex sync.Mutex +} + +// BatchLog delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) BatchLog(v0 context.Context, v1 gitserver.BatchLogOptions, v2 gitserver.BatchLogCallback) error { + r0 := m.BatchLogFunc.nextHook()(v0, v1, v2) + m.BatchLogFunc.appendCall(GitserverClientBatchLogFuncCall{v0, v1, v2, r0}) + return r0 +} + +// SetDefaultHook sets function that is called when the BatchLog method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientBatchLogFunc) SetDefaultHook(hook func(context.Context, gitserver.BatchLogOptions, gitserver.BatchLogCallback) error) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// BatchLog 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 *GitserverClientBatchLogFunc) PushHook(hook func(context.Context, gitserver.BatchLogOptions, gitserver.BatchLogCallback) 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 *GitserverClientBatchLogFunc) SetDefaultReturn(r0 error) { + f.SetDefaultHook(func(context.Context, gitserver.BatchLogOptions, gitserver.BatchLogCallback) error { + return r0 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientBatchLogFunc) PushReturn(r0 error) { + f.PushHook(func(context.Context, gitserver.BatchLogOptions, gitserver.BatchLogCallback) error { + return r0 + }) +} + +func (f *GitserverClientBatchLogFunc) nextHook() func(context.Context, gitserver.BatchLogOptions, gitserver.BatchLogCallback) 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 *GitserverClientBatchLogFunc) appendCall(r0 GitserverClientBatchLogFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientBatchLogFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientBatchLogFunc) History() []GitserverClientBatchLogFuncCall { + f.mutex.Lock() + history := make([]GitserverClientBatchLogFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientBatchLogFuncCall is an object that describes an invocation +// of method BatchLog on an instance of MockGitserverClient. +type GitserverClientBatchLogFuncCall 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 gitserver.BatchLogOptions + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 gitserver.BatchLogCallback + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c GitserverClientBatchLogFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientBatchLogFuncCall) Results() []interface{} { + return []interface{}{c.Result0} +} + +// GitserverClientBlameFileFunc describes the behavior when the BlameFile +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientBlameFileFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) ([]*gitserver.Hunk, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) ([]*gitserver.Hunk, error) + history []GitserverClientBlameFileFuncCall + mutex sync.Mutex +} + +// BlameFile delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) BlameFile(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 string, v4 *gitserver.BlameOptions) ([]*gitserver.Hunk, error) { + r0, r1 := m.BlameFileFunc.nextHook()(v0, v1, v2, v3, v4) + m.BlameFileFunc.appendCall(GitserverClientBlameFileFuncCall{v0, v1, v2, v3, v4, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the BlameFile method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientBlameFileFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) ([]*gitserver.Hunk, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// BlameFile 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 *GitserverClientBlameFileFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) ([]*gitserver.Hunk, 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 *GitserverClientBlameFileFunc) SetDefaultReturn(r0 []*gitserver.Hunk, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) ([]*gitserver.Hunk, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientBlameFileFunc) PushReturn(r0 []*gitserver.Hunk, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) ([]*gitserver.Hunk, error) { + return r0, r1 + }) +} + +func (f *GitserverClientBlameFileFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) ([]*gitserver.Hunk, 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 *GitserverClientBlameFileFunc) appendCall(r0 GitserverClientBlameFileFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientBlameFileFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientBlameFileFunc) History() []GitserverClientBlameFileFuncCall { + f.mutex.Lock() + history := make([]GitserverClientBlameFileFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientBlameFileFuncCall is an object that describes an +// invocation of method BlameFile on an instance of MockGitserverClient. +type GitserverClientBlameFileFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 string + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 *gitserver.BlameOptions + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []*gitserver.Hunk + // 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 GitserverClientBlameFileFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientBlameFileFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientBranchesContainingFunc describes the behavior when the +// BranchesContaining method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientBranchesContainingFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) ([]string, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) ([]string, error) + history []GitserverClientBranchesContainingFuncCall + mutex sync.Mutex +} + +// BranchesContaining delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) BranchesContaining(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 api.CommitID) ([]string, error) { + r0, r1 := m.BranchesContainingFunc.nextHook()(v0, v1, v2, v3) + m.BranchesContainingFunc.appendCall(GitserverClientBranchesContainingFuncCall{v0, v1, v2, v3, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the BranchesContaining +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientBranchesContainingFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) ([]string, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// BranchesContaining 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 *GitserverClientBranchesContainingFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) ([]string, 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 *GitserverClientBranchesContainingFunc) SetDefaultReturn(r0 []string, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) ([]string, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientBranchesContainingFunc) PushReturn(r0 []string, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) ([]string, error) { + return r0, r1 + }) +} + +func (f *GitserverClientBranchesContainingFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) ([]string, 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 *GitserverClientBranchesContainingFunc) appendCall(r0 GitserverClientBranchesContainingFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientBranchesContainingFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientBranchesContainingFunc) History() []GitserverClientBranchesContainingFuncCall { + f.mutex.Lock() + history := make([]GitserverClientBranchesContainingFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientBranchesContainingFuncCall is an object that describes an +// invocation of method BranchesContaining on an instance of +// MockGitserverClient. +type GitserverClientBranchesContainingFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // 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 []string + // 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 GitserverClientBranchesContainingFuncCall) 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 GitserverClientBranchesContainingFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientCommitDateFunc describes the behavior when the CommitDate +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientCommitDateFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (string, time.Time, bool, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (string, time.Time, bool, error) + history []GitserverClientCommitDateFuncCall + mutex sync.Mutex +} + +// CommitDate delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) CommitDate(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 api.CommitID) (string, time.Time, bool, error) { + r0, r1, r2, r3 := m.CommitDateFunc.nextHook()(v0, v1, v2, v3) + m.CommitDateFunc.appendCall(GitserverClientCommitDateFuncCall{v0, v1, v2, v3, r0, r1, r2, r3}) + return r0, r1, r2, r3 +} + +// SetDefaultHook sets function that is called when the CommitDate method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientCommitDateFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (string, time.Time, bool, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// CommitDate 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 *GitserverClientCommitDateFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (string, time.Time, bool, 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 *GitserverClientCommitDateFunc) SetDefaultReturn(r0 string, r1 time.Time, r2 bool, r3 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (string, time.Time, bool, error) { + return r0, r1, r2, r3 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientCommitDateFunc) PushReturn(r0 string, r1 time.Time, r2 bool, r3 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (string, time.Time, bool, error) { + return r0, r1, r2, r3 + }) +} + +func (f *GitserverClientCommitDateFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (string, time.Time, bool, 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 *GitserverClientCommitDateFunc) appendCall(r0 GitserverClientCommitDateFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientCommitDateFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientCommitDateFunc) History() []GitserverClientCommitDateFuncCall { + f.mutex.Lock() + history := make([]GitserverClientCommitDateFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientCommitDateFuncCall is an object that describes an +// invocation of method CommitDate on an instance of MockGitserverClient. +type GitserverClientCommitDateFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // 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 string + // Result1 is the value of the 2nd result returned from this method + // invocation. + Result1 time.Time + // Result2 is the value of the 3rd result returned from this method + // invocation. + Result2 bool + // Result3 is the value of the 4th result returned from this method + // invocation. + Result3 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c GitserverClientCommitDateFuncCall) 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 GitserverClientCommitDateFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1, c.Result2, c.Result3} +} + +// GitserverClientCommitExistsFunc describes the behavior when the +// CommitExists method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientCommitExistsFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (bool, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (bool, error) + history []GitserverClientCommitExistsFuncCall + mutex sync.Mutex +} + +// CommitExists delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) CommitExists(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 api.CommitID) (bool, error) { + r0, r1 := m.CommitExistsFunc.nextHook()(v0, v1, v2, v3) + m.CommitExistsFunc.appendCall(GitserverClientCommitExistsFuncCall{v0, v1, v2, v3, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the CommitExists method +// of the parent MockGitserverClient instance is invoked and the hook queue +// is empty. +func (f *GitserverClientCommitExistsFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (bool, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// CommitExists 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 *GitserverClientCommitExistsFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (bool, 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 *GitserverClientCommitExistsFunc) SetDefaultReturn(r0 bool, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (bool, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientCommitExistsFunc) PushReturn(r0 bool, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (bool, error) { + return r0, r1 + }) +} + +func (f *GitserverClientCommitExistsFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID) (bool, 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 *GitserverClientCommitExistsFunc) appendCall(r0 GitserverClientCommitExistsFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientCommitExistsFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientCommitExistsFunc) History() []GitserverClientCommitExistsFuncCall { + f.mutex.Lock() + history := make([]GitserverClientCommitExistsFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientCommitExistsFuncCall is an object that describes an +// invocation of method CommitExists on an instance of MockGitserverClient. +type GitserverClientCommitExistsFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // 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 bool + // 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 GitserverClientCommitExistsFuncCall) 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 GitserverClientCommitExistsFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientCommitGraphFunc describes the behavior when the +// CommitGraph method of the parent MockGitserverClient instance is invoked. +type GitserverClientCommitGraphFunc struct { + defaultHook func(context.Context, api.RepoName, gitserver.CommitGraphOptions) (*gitdomain.CommitGraph, error) + hooks []func(context.Context, api.RepoName, gitserver.CommitGraphOptions) (*gitdomain.CommitGraph, error) + history []GitserverClientCommitGraphFuncCall + mutex sync.Mutex +} + +// CommitGraph delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) CommitGraph(v0 context.Context, v1 api.RepoName, v2 gitserver.CommitGraphOptions) (*gitdomain.CommitGraph, error) { + r0, r1 := m.CommitGraphFunc.nextHook()(v0, v1, v2) + m.CommitGraphFunc.appendCall(GitserverClientCommitGraphFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the CommitGraph method +// of the parent MockGitserverClient instance is invoked and the hook queue +// is empty. +func (f *GitserverClientCommitGraphFunc) SetDefaultHook(hook func(context.Context, api.RepoName, gitserver.CommitGraphOptions) (*gitdomain.CommitGraph, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// CommitGraph 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 *GitserverClientCommitGraphFunc) PushHook(hook func(context.Context, api.RepoName, gitserver.CommitGraphOptions) (*gitdomain.CommitGraph, 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 *GitserverClientCommitGraphFunc) SetDefaultReturn(r0 *gitdomain.CommitGraph, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, gitserver.CommitGraphOptions) (*gitdomain.CommitGraph, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientCommitGraphFunc) PushReturn(r0 *gitdomain.CommitGraph, r1 error) { + f.PushHook(func(context.Context, api.RepoName, gitserver.CommitGraphOptions) (*gitdomain.CommitGraph, error) { + return r0, r1 + }) +} + +func (f *GitserverClientCommitGraphFunc) nextHook() func(context.Context, api.RepoName, gitserver.CommitGraphOptions) (*gitdomain.CommitGraph, 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 *GitserverClientCommitGraphFunc) appendCall(r0 GitserverClientCommitGraphFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientCommitGraphFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientCommitGraphFunc) History() []GitserverClientCommitGraphFuncCall { + f.mutex.Lock() + history := make([]GitserverClientCommitGraphFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientCommitGraphFuncCall is an object that describes an +// invocation of method CommitGraph on an instance of MockGitserverClient. +type GitserverClientCommitGraphFuncCall 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 gitserver.CommitGraphOptions + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *gitdomain.CommitGraph + // 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 GitserverClientCommitGraphFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientCommitGraphFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientCommitLogFunc describes the behavior when the CommitLog +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientCommitLogFunc struct { + defaultHook func(context.Context, api.RepoName, time.Time) ([]gitserver.CommitLog, error) + hooks []func(context.Context, api.RepoName, time.Time) ([]gitserver.CommitLog, error) + history []GitserverClientCommitLogFuncCall + mutex sync.Mutex +} + +// CommitLog delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) CommitLog(v0 context.Context, v1 api.RepoName, v2 time.Time) ([]gitserver.CommitLog, error) { + r0, r1 := m.CommitLogFunc.nextHook()(v0, v1, v2) + m.CommitLogFunc.appendCall(GitserverClientCommitLogFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the CommitLog method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientCommitLogFunc) SetDefaultHook(hook func(context.Context, api.RepoName, time.Time) ([]gitserver.CommitLog, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// CommitLog 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 *GitserverClientCommitLogFunc) PushHook(hook func(context.Context, api.RepoName, time.Time) ([]gitserver.CommitLog, 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 *GitserverClientCommitLogFunc) SetDefaultReturn(r0 []gitserver.CommitLog, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, time.Time) ([]gitserver.CommitLog, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientCommitLogFunc) PushReturn(r0 []gitserver.CommitLog, r1 error) { + f.PushHook(func(context.Context, api.RepoName, time.Time) ([]gitserver.CommitLog, error) { + return r0, r1 + }) +} + +func (f *GitserverClientCommitLogFunc) nextHook() func(context.Context, api.RepoName, time.Time) ([]gitserver.CommitLog, 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 *GitserverClientCommitLogFunc) appendCall(r0 GitserverClientCommitLogFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientCommitLogFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientCommitLogFunc) History() []GitserverClientCommitLogFuncCall { + f.mutex.Lock() + history := make([]GitserverClientCommitLogFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientCommitLogFuncCall is an object that describes an +// invocation of method CommitLog on an instance of MockGitserverClient. +type GitserverClientCommitLogFuncCall 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 time.Time + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []gitserver.CommitLog + // 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 GitserverClientCommitLogFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientCommitLogFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientCommitsFunc describes the behavior when the Commits method +// of the parent MockGitserverClient instance is invoked. +type GitserverClientCommitsFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.CommitsOptions) ([]*gitdomain.Commit, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.CommitsOptions) ([]*gitdomain.Commit, error) + history []GitserverClientCommitsFuncCall + mutex sync.Mutex +} + +// Commits delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) Commits(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 gitserver.CommitsOptions) ([]*gitdomain.Commit, error) { + r0, r1 := m.CommitsFunc.nextHook()(v0, v1, v2, v3) + m.CommitsFunc.appendCall(GitserverClientCommitsFuncCall{v0, v1, v2, v3, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the Commits method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientCommitsFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.CommitsOptions) ([]*gitdomain.Commit, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// Commits 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 *GitserverClientCommitsFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.CommitsOptions) ([]*gitdomain.Commit, 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 *GitserverClientCommitsFunc) SetDefaultReturn(r0 []*gitdomain.Commit, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.CommitsOptions) ([]*gitdomain.Commit, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientCommitsFunc) PushReturn(r0 []*gitdomain.Commit, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.CommitsOptions) ([]*gitdomain.Commit, error) { + return r0, r1 + }) +} + +func (f *GitserverClientCommitsFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, gitserver.CommitsOptions) ([]*gitdomain.Commit, 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 *GitserverClientCommitsFunc) appendCall(r0 GitserverClientCommitsFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientCommitsFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientCommitsFunc) History() []GitserverClientCommitsFuncCall { + f.mutex.Lock() + history := make([]GitserverClientCommitsFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientCommitsFuncCall is an object that describes an invocation +// of method Commits on an instance of MockGitserverClient. +type GitserverClientCommitsFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 gitserver.CommitsOptions + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []*gitdomain.Commit + // 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 GitserverClientCommitsFuncCall) 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 GitserverClientCommitsFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientCommitsExistFunc describes the behavior when the +// CommitsExist method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientCommitsExistFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit) ([]bool, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit) ([]bool, error) + history []GitserverClientCommitsExistFuncCall + mutex sync.Mutex +} + +// CommitsExist delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) CommitsExist(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 []api.RepoCommit) ([]bool, error) { + r0, r1 := m.CommitsExistFunc.nextHook()(v0, v1, v2) + m.CommitsExistFunc.appendCall(GitserverClientCommitsExistFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the CommitsExist method +// of the parent MockGitserverClient instance is invoked and the hook queue +// is empty. +func (f *GitserverClientCommitsExistFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit) ([]bool, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// CommitsExist 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 *GitserverClientCommitsExistFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit) ([]bool, 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 *GitserverClientCommitsExistFunc) SetDefaultReturn(r0 []bool, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit) ([]bool, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientCommitsExistFunc) PushReturn(r0 []bool, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit) ([]bool, error) { + return r0, r1 + }) +} + +func (f *GitserverClientCommitsExistFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit) ([]bool, 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 *GitserverClientCommitsExistFunc) appendCall(r0 GitserverClientCommitsExistFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientCommitsExistFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientCommitsExistFunc) History() []GitserverClientCommitsExistFuncCall { + f.mutex.Lock() + history := make([]GitserverClientCommitsExistFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientCommitsExistFuncCall is an object that describes an +// invocation of method CommitsExist on an instance of MockGitserverClient. +type GitserverClientCommitsExistFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 []api.RepoCommit + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []bool + // 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 GitserverClientCommitsExistFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientCommitsExistFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientCommitsUniqueToBranchFunc describes the behavior when the +// CommitsUniqueToBranch method of the parent MockGitserverClient instance +// is invoked. +type GitserverClientCommitsUniqueToBranchFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, bool, *time.Time) (map[string]time.Time, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, bool, *time.Time) (map[string]time.Time, error) + history []GitserverClientCommitsUniqueToBranchFuncCall + mutex sync.Mutex +} + +// CommitsUniqueToBranch delegates to the next hook function in the queue +// and stores the parameter and result values of this invocation. +func (m *MockGitserverClient) CommitsUniqueToBranch(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 string, v4 bool, v5 *time.Time) (map[string]time.Time, error) { + r0, r1 := m.CommitsUniqueToBranchFunc.nextHook()(v0, v1, v2, v3, v4, v5) + m.CommitsUniqueToBranchFunc.appendCall(GitserverClientCommitsUniqueToBranchFuncCall{v0, v1, v2, v3, v4, v5, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the +// CommitsUniqueToBranch method of the parent MockGitserverClient instance +// is invoked and the hook queue is empty. +func (f *GitserverClientCommitsUniqueToBranchFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, bool, *time.Time) (map[string]time.Time, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// CommitsUniqueToBranch 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 *GitserverClientCommitsUniqueToBranchFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, bool, *time.Time) (map[string]time.Time, 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 *GitserverClientCommitsUniqueToBranchFunc) SetDefaultReturn(r0 map[string]time.Time, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, bool, *time.Time) (map[string]time.Time, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientCommitsUniqueToBranchFunc) PushReturn(r0 map[string]time.Time, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, bool, *time.Time) (map[string]time.Time, error) { + return r0, r1 + }) +} + +func (f *GitserverClientCommitsUniqueToBranchFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, bool, *time.Time) (map[string]time.Time, 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 *GitserverClientCommitsUniqueToBranchFunc) appendCall(r0 GitserverClientCommitsUniqueToBranchFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of +// GitserverClientCommitsUniqueToBranchFuncCall objects describing the +// invocations of this function. +func (f *GitserverClientCommitsUniqueToBranchFunc) History() []GitserverClientCommitsUniqueToBranchFuncCall { + f.mutex.Lock() + history := make([]GitserverClientCommitsUniqueToBranchFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientCommitsUniqueToBranchFuncCall is an object that describes +// an invocation of method CommitsUniqueToBranch on an instance of +// MockGitserverClient. +type GitserverClientCommitsUniqueToBranchFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 string + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 bool + // Arg5 is the value of the 6th argument passed to this method + // invocation. + Arg5 *time.Time + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 map[string]time.Time + // 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 GitserverClientCommitsUniqueToBranchFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4, c.Arg5} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientCommitsUniqueToBranchFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientContributorCountFunc describes the behavior when the +// ContributorCount method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientContributorCountFunc struct { + defaultHook func(context.Context, api.RepoName, gitserver.ContributorOptions) ([]*gitdomain.ContributorCount, error) + hooks []func(context.Context, api.RepoName, gitserver.ContributorOptions) ([]*gitdomain.ContributorCount, error) + history []GitserverClientContributorCountFuncCall + mutex sync.Mutex +} + +// ContributorCount delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) ContributorCount(v0 context.Context, v1 api.RepoName, v2 gitserver.ContributorOptions) ([]*gitdomain.ContributorCount, error) { + r0, r1 := m.ContributorCountFunc.nextHook()(v0, v1, v2) + m.ContributorCountFunc.appendCall(GitserverClientContributorCountFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the ContributorCount +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientContributorCountFunc) SetDefaultHook(hook func(context.Context, api.RepoName, gitserver.ContributorOptions) ([]*gitdomain.ContributorCount, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ContributorCount 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 *GitserverClientContributorCountFunc) PushHook(hook func(context.Context, api.RepoName, gitserver.ContributorOptions) ([]*gitdomain.ContributorCount, 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 *GitserverClientContributorCountFunc) SetDefaultReturn(r0 []*gitdomain.ContributorCount, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, gitserver.ContributorOptions) ([]*gitdomain.ContributorCount, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientContributorCountFunc) PushReturn(r0 []*gitdomain.ContributorCount, r1 error) { + f.PushHook(func(context.Context, api.RepoName, gitserver.ContributorOptions) ([]*gitdomain.ContributorCount, error) { + return r0, r1 + }) +} + +func (f *GitserverClientContributorCountFunc) nextHook() func(context.Context, api.RepoName, gitserver.ContributorOptions) ([]*gitdomain.ContributorCount, 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 *GitserverClientContributorCountFunc) appendCall(r0 GitserverClientContributorCountFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientContributorCountFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientContributorCountFunc) History() []GitserverClientContributorCountFuncCall { + f.mutex.Lock() + history := make([]GitserverClientContributorCountFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientContributorCountFuncCall is an object that describes an +// invocation of method ContributorCount on an instance of +// MockGitserverClient. +type GitserverClientContributorCountFuncCall 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 gitserver.ContributorOptions + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []*gitdomain.ContributorCount + // 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 GitserverClientContributorCountFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientContributorCountFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientCreateCommitFromPatchFunc describes the behavior when the +// CreateCommitFromPatch method of the parent MockGitserverClient instance +// is invoked. +type GitserverClientCreateCommitFromPatchFunc struct { + defaultHook func(context.Context, protocol.CreateCommitFromPatchRequest) (*protocol.CreateCommitFromPatchResponse, error) + hooks []func(context.Context, protocol.CreateCommitFromPatchRequest) (*protocol.CreateCommitFromPatchResponse, error) + history []GitserverClientCreateCommitFromPatchFuncCall + mutex sync.Mutex +} + +// CreateCommitFromPatch delegates to the next hook function in the queue +// and stores the parameter and result values of this invocation. +func (m *MockGitserverClient) CreateCommitFromPatch(v0 context.Context, v1 protocol.CreateCommitFromPatchRequest) (*protocol.CreateCommitFromPatchResponse, error) { + r0, r1 := m.CreateCommitFromPatchFunc.nextHook()(v0, v1) + m.CreateCommitFromPatchFunc.appendCall(GitserverClientCreateCommitFromPatchFuncCall{v0, v1, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the +// CreateCommitFromPatch method of the parent MockGitserverClient instance +// is invoked and the hook queue is empty. +func (f *GitserverClientCreateCommitFromPatchFunc) SetDefaultHook(hook func(context.Context, protocol.CreateCommitFromPatchRequest) (*protocol.CreateCommitFromPatchResponse, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// CreateCommitFromPatch 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 *GitserverClientCreateCommitFromPatchFunc) PushHook(hook func(context.Context, protocol.CreateCommitFromPatchRequest) (*protocol.CreateCommitFromPatchResponse, 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 *GitserverClientCreateCommitFromPatchFunc) SetDefaultReturn(r0 *protocol.CreateCommitFromPatchResponse, r1 error) { + f.SetDefaultHook(func(context.Context, protocol.CreateCommitFromPatchRequest) (*protocol.CreateCommitFromPatchResponse, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientCreateCommitFromPatchFunc) PushReturn(r0 *protocol.CreateCommitFromPatchResponse, r1 error) { + f.PushHook(func(context.Context, protocol.CreateCommitFromPatchRequest) (*protocol.CreateCommitFromPatchResponse, error) { + return r0, r1 + }) +} + +func (f *GitserverClientCreateCommitFromPatchFunc) nextHook() func(context.Context, protocol.CreateCommitFromPatchRequest) (*protocol.CreateCommitFromPatchResponse, 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 *GitserverClientCreateCommitFromPatchFunc) appendCall(r0 GitserverClientCreateCommitFromPatchFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of +// GitserverClientCreateCommitFromPatchFuncCall objects describing the +// invocations of this function. +func (f *GitserverClientCreateCommitFromPatchFunc) History() []GitserverClientCreateCommitFromPatchFuncCall { + f.mutex.Lock() + history := make([]GitserverClientCreateCommitFromPatchFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientCreateCommitFromPatchFuncCall is an object that describes +// an invocation of method CreateCommitFromPatch on an instance of +// MockGitserverClient. +type GitserverClientCreateCommitFromPatchFuncCall 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 protocol.CreateCommitFromPatchRequest + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *protocol.CreateCommitFromPatchResponse + // 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 GitserverClientCreateCommitFromPatchFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientCreateCommitFromPatchFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientDiffFunc describes the behavior when the Diff method of +// the parent MockGitserverClient instance is invoked. +type GitserverClientDiffFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, gitserver.DiffOptions) (*gitserver.DiffFileIterator, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, gitserver.DiffOptions) (*gitserver.DiffFileIterator, error) + history []GitserverClientDiffFuncCall + mutex sync.Mutex +} + +// Diff delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) Diff(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 gitserver.DiffOptions) (*gitserver.DiffFileIterator, error) { + r0, r1 := m.DiffFunc.nextHook()(v0, v1, v2) + m.DiffFunc.appendCall(GitserverClientDiffFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the Diff method of the +// parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientDiffFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, gitserver.DiffOptions) (*gitserver.DiffFileIterator, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// Diff 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 *GitserverClientDiffFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, gitserver.DiffOptions) (*gitserver.DiffFileIterator, 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 *GitserverClientDiffFunc) SetDefaultReturn(r0 *gitserver.DiffFileIterator, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, gitserver.DiffOptions) (*gitserver.DiffFileIterator, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientDiffFunc) PushReturn(r0 *gitserver.DiffFileIterator, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, gitserver.DiffOptions) (*gitserver.DiffFileIterator, error) { + return r0, r1 + }) +} + +func (f *GitserverClientDiffFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, gitserver.DiffOptions) (*gitserver.DiffFileIterator, 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 *GitserverClientDiffFunc) appendCall(r0 GitserverClientDiffFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientDiffFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientDiffFunc) History() []GitserverClientDiffFuncCall { + f.mutex.Lock() + history := make([]GitserverClientDiffFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientDiffFuncCall is an object that describes an invocation of +// method Diff on an instance of MockGitserverClient. +type GitserverClientDiffFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 gitserver.DiffOptions + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *gitserver.DiffFileIterator + // 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 GitserverClientDiffFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientDiffFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientDiffPathFunc describes the behavior when the DiffPath +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientDiffPathFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string, string) ([]*diff.Hunk, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string, string) ([]*diff.Hunk, error) + history []GitserverClientDiffPathFuncCall + mutex sync.Mutex +} + +// DiffPath delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) DiffPath(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 string, v4 string, v5 string) ([]*diff.Hunk, error) { + r0, r1 := m.DiffPathFunc.nextHook()(v0, v1, v2, v3, v4, v5) + m.DiffPathFunc.appendCall(GitserverClientDiffPathFuncCall{v0, v1, v2, v3, v4, v5, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the DiffPath method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientDiffPathFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string, string) ([]*diff.Hunk, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// DiffPath 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 *GitserverClientDiffPathFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string, string) ([]*diff.Hunk, 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 *GitserverClientDiffPathFunc) SetDefaultReturn(r0 []*diff.Hunk, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string, string) ([]*diff.Hunk, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientDiffPathFunc) PushReturn(r0 []*diff.Hunk, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string, string) ([]*diff.Hunk, error) { + return r0, r1 + }) +} + +func (f *GitserverClientDiffPathFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string, string) ([]*diff.Hunk, 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 *GitserverClientDiffPathFunc) appendCall(r0 GitserverClientDiffPathFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientDiffPathFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientDiffPathFunc) History() []GitserverClientDiffPathFuncCall { + f.mutex.Lock() + history := make([]GitserverClientDiffPathFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientDiffPathFuncCall is an object that describes an invocation +// of method DiffPath on an instance of MockGitserverClient. +type GitserverClientDiffPathFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 string + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 string + // Arg5 is the value of the 6th argument passed to this method + // invocation. + Arg5 string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []*diff.Hunk + // 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 GitserverClientDiffPathFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4, c.Arg5} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientDiffPathFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientDiffSymbolsFunc describes the behavior when the +// DiffSymbols method of the parent MockGitserverClient instance is invoked. +type GitserverClientDiffSymbolsFunc struct { + defaultHook func(context.Context, api.RepoName, api.CommitID, api.CommitID) ([]byte, error) + hooks []func(context.Context, api.RepoName, api.CommitID, api.CommitID) ([]byte, error) + history []GitserverClientDiffSymbolsFuncCall + mutex sync.Mutex +} + +// DiffSymbols delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) DiffSymbols(v0 context.Context, v1 api.RepoName, v2 api.CommitID, v3 api.CommitID) ([]byte, error) { + r0, r1 := m.DiffSymbolsFunc.nextHook()(v0, v1, v2, v3) + m.DiffSymbolsFunc.appendCall(GitserverClientDiffSymbolsFuncCall{v0, v1, v2, v3, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the DiffSymbols method +// of the parent MockGitserverClient instance is invoked and the hook queue +// is empty. +func (f *GitserverClientDiffSymbolsFunc) SetDefaultHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) ([]byte, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// DiffSymbols 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 *GitserverClientDiffSymbolsFunc) PushHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) ([]byte, 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 *GitserverClientDiffSymbolsFunc) SetDefaultReturn(r0 []byte, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) ([]byte, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientDiffSymbolsFunc) PushReturn(r0 []byte, r1 error) { + f.PushHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) ([]byte, error) { + return r0, r1 + }) +} + +func (f *GitserverClientDiffSymbolsFunc) nextHook() func(context.Context, api.RepoName, api.CommitID, api.CommitID) ([]byte, 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 *GitserverClientDiffSymbolsFunc) appendCall(r0 GitserverClientDiffSymbolsFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientDiffSymbolsFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientDiffSymbolsFunc) History() []GitserverClientDiffSymbolsFuncCall { + f.mutex.Lock() + history := make([]GitserverClientDiffSymbolsFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientDiffSymbolsFuncCall is an object that describes an +// invocation of method DiffSymbols on an instance of MockGitserverClient. +type GitserverClientDiffSymbolsFuncCall 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 []byte + // 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 GitserverClientDiffSymbolsFuncCall) 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 GitserverClientDiffSymbolsFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientFirstEverCommitFunc describes the behavior when the +// FirstEverCommit method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientFirstEverCommitFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (*gitdomain.Commit, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (*gitdomain.Commit, error) + history []GitserverClientFirstEverCommitFuncCall + mutex sync.Mutex +} + +// FirstEverCommit delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) FirstEverCommit(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName) (*gitdomain.Commit, error) { + r0, r1 := m.FirstEverCommitFunc.nextHook()(v0, v1, v2) + m.FirstEverCommitFunc.appendCall(GitserverClientFirstEverCommitFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the FirstEverCommit +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientFirstEverCommitFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (*gitdomain.Commit, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// FirstEverCommit 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 *GitserverClientFirstEverCommitFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (*gitdomain.Commit, 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 *GitserverClientFirstEverCommitFunc) SetDefaultReturn(r0 *gitdomain.Commit, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (*gitdomain.Commit, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientFirstEverCommitFunc) PushReturn(r0 *gitdomain.Commit, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (*gitdomain.Commit, error) { + return r0, r1 + }) +} + +func (f *GitserverClientFirstEverCommitFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (*gitdomain.Commit, 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 *GitserverClientFirstEverCommitFunc) appendCall(r0 GitserverClientFirstEverCommitFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientFirstEverCommitFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientFirstEverCommitFunc) History() []GitserverClientFirstEverCommitFuncCall { + f.mutex.Lock() + history := make([]GitserverClientFirstEverCommitFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientFirstEverCommitFuncCall is an object that describes an +// invocation of method FirstEverCommit on an instance of +// MockGitserverClient. +type GitserverClientFirstEverCommitFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *gitdomain.Commit + // 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 GitserverClientFirstEverCommitFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientFirstEverCommitFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientGetBehindAheadFunc describes the behavior when the +// GetBehindAhead method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientGetBehindAheadFunc struct { + defaultHook func(context.Context, api.RepoName, string, string) (*gitdomain.BehindAhead, error) + hooks []func(context.Context, api.RepoName, string, string) (*gitdomain.BehindAhead, error) + history []GitserverClientGetBehindAheadFuncCall + mutex sync.Mutex +} + +// GetBehindAhead delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) GetBehindAhead(v0 context.Context, v1 api.RepoName, v2 string, v3 string) (*gitdomain.BehindAhead, error) { + r0, r1 := m.GetBehindAheadFunc.nextHook()(v0, v1, v2, v3) + m.GetBehindAheadFunc.appendCall(GitserverClientGetBehindAheadFuncCall{v0, v1, v2, v3, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the GetBehindAhead +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientGetBehindAheadFunc) SetDefaultHook(hook func(context.Context, api.RepoName, string, string) (*gitdomain.BehindAhead, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// GetBehindAhead 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 *GitserverClientGetBehindAheadFunc) PushHook(hook func(context.Context, api.RepoName, string, string) (*gitdomain.BehindAhead, 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 *GitserverClientGetBehindAheadFunc) SetDefaultReturn(r0 *gitdomain.BehindAhead, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, string, string) (*gitdomain.BehindAhead, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientGetBehindAheadFunc) PushReturn(r0 *gitdomain.BehindAhead, r1 error) { + f.PushHook(func(context.Context, api.RepoName, string, string) (*gitdomain.BehindAhead, error) { + return r0, r1 + }) +} + +func (f *GitserverClientGetBehindAheadFunc) nextHook() func(context.Context, api.RepoName, string, string) (*gitdomain.BehindAhead, 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 *GitserverClientGetBehindAheadFunc) appendCall(r0 GitserverClientGetBehindAheadFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientGetBehindAheadFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientGetBehindAheadFunc) History() []GitserverClientGetBehindAheadFuncCall { + f.mutex.Lock() + history := make([]GitserverClientGetBehindAheadFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientGetBehindAheadFuncCall is an object that describes an +// invocation of method GetBehindAhead on an instance of +// MockGitserverClient. +type GitserverClientGetBehindAheadFuncCall 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 string + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *gitdomain.BehindAhead + // 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 GitserverClientGetBehindAheadFuncCall) 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 GitserverClientGetBehindAheadFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientGetCommitFunc describes the behavior when the GetCommit +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientGetCommitFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, gitserver.ResolveRevisionOptions) (*gitdomain.Commit, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, gitserver.ResolveRevisionOptions) (*gitdomain.Commit, error) + history []GitserverClientGetCommitFuncCall + mutex sync.Mutex +} + +// GetCommit delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) GetCommit(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 api.CommitID, v4 gitserver.ResolveRevisionOptions) (*gitdomain.Commit, error) { + r0, r1 := m.GetCommitFunc.nextHook()(v0, v1, v2, v3, v4) + m.GetCommitFunc.appendCall(GitserverClientGetCommitFuncCall{v0, v1, v2, v3, v4, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the GetCommit method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientGetCommitFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, gitserver.ResolveRevisionOptions) (*gitdomain.Commit, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// GetCommit 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 *GitserverClientGetCommitFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, gitserver.ResolveRevisionOptions) (*gitdomain.Commit, 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 *GitserverClientGetCommitFunc) SetDefaultReturn(r0 *gitdomain.Commit, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, gitserver.ResolveRevisionOptions) (*gitdomain.Commit, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientGetCommitFunc) PushReturn(r0 *gitdomain.Commit, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, gitserver.ResolveRevisionOptions) (*gitdomain.Commit, error) { + return r0, r1 + }) +} + +func (f *GitserverClientGetCommitFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, gitserver.ResolveRevisionOptions) (*gitdomain.Commit, 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 *GitserverClientGetCommitFunc) appendCall(r0 GitserverClientGetCommitFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientGetCommitFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientGetCommitFunc) History() []GitserverClientGetCommitFuncCall { + f.mutex.Lock() + history := make([]GitserverClientGetCommitFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientGetCommitFuncCall is an object that describes an +// invocation of method GetCommit on an instance of MockGitserverClient. +type GitserverClientGetCommitFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 api.CommitID + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 gitserver.ResolveRevisionOptions + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *gitdomain.Commit + // 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 GitserverClientGetCommitFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientGetCommitFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientGetCommitsFunc describes the behavior when the GetCommits +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientGetCommitsFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit, bool) ([]*gitdomain.Commit, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit, bool) ([]*gitdomain.Commit, error) + history []GitserverClientGetCommitsFuncCall + mutex sync.Mutex +} + +// GetCommits delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) GetCommits(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 []api.RepoCommit, v3 bool) ([]*gitdomain.Commit, error) { + r0, r1 := m.GetCommitsFunc.nextHook()(v0, v1, v2, v3) + m.GetCommitsFunc.appendCall(GitserverClientGetCommitsFuncCall{v0, v1, v2, v3, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the GetCommits method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientGetCommitsFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit, bool) ([]*gitdomain.Commit, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// GetCommits 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 *GitserverClientGetCommitsFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit, bool) ([]*gitdomain.Commit, 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 *GitserverClientGetCommitsFunc) SetDefaultReturn(r0 []*gitdomain.Commit, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit, bool) ([]*gitdomain.Commit, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientGetCommitsFunc) PushReturn(r0 []*gitdomain.Commit, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit, bool) ([]*gitdomain.Commit, error) { + return r0, r1 + }) +} + +func (f *GitserverClientGetCommitsFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, []api.RepoCommit, bool) ([]*gitdomain.Commit, 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 *GitserverClientGetCommitsFunc) appendCall(r0 GitserverClientGetCommitsFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientGetCommitsFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientGetCommitsFunc) History() []GitserverClientGetCommitsFuncCall { + f.mutex.Lock() + history := make([]GitserverClientGetCommitsFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientGetCommitsFuncCall is an object that describes an +// invocation of method GetCommits on an instance of MockGitserverClient. +type GitserverClientGetCommitsFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 []api.RepoCommit + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 bool + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []*gitdomain.Commit + // 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 GitserverClientGetCommitsFuncCall) 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 GitserverClientGetCommitsFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientGetDefaultBranchFunc describes the behavior when the +// GetDefaultBranch method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientGetDefaultBranchFunc struct { + defaultHook func(context.Context, api.RepoName, bool) (string, api.CommitID, error) + hooks []func(context.Context, api.RepoName, bool) (string, api.CommitID, error) + history []GitserverClientGetDefaultBranchFuncCall + mutex sync.Mutex +} + +// GetDefaultBranch delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) GetDefaultBranch(v0 context.Context, v1 api.RepoName, v2 bool) (string, api.CommitID, error) { + r0, r1, r2 := m.GetDefaultBranchFunc.nextHook()(v0, v1, v2) + m.GetDefaultBranchFunc.appendCall(GitserverClientGetDefaultBranchFuncCall{v0, v1, v2, r0, r1, r2}) + return r0, r1, r2 +} + +// SetDefaultHook sets function that is called when the GetDefaultBranch +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientGetDefaultBranchFunc) SetDefaultHook(hook func(context.Context, api.RepoName, bool) (string, api.CommitID, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// GetDefaultBranch 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 *GitserverClientGetDefaultBranchFunc) PushHook(hook func(context.Context, api.RepoName, bool) (string, api.CommitID, 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 *GitserverClientGetDefaultBranchFunc) SetDefaultReturn(r0 string, r1 api.CommitID, r2 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, bool) (string, api.CommitID, error) { + return r0, r1, r2 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientGetDefaultBranchFunc) PushReturn(r0 string, r1 api.CommitID, r2 error) { + f.PushHook(func(context.Context, api.RepoName, bool) (string, api.CommitID, error) { + return r0, r1, r2 + }) +} + +func (f *GitserverClientGetDefaultBranchFunc) nextHook() func(context.Context, api.RepoName, bool) (string, api.CommitID, 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 *GitserverClientGetDefaultBranchFunc) appendCall(r0 GitserverClientGetDefaultBranchFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientGetDefaultBranchFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientGetDefaultBranchFunc) History() []GitserverClientGetDefaultBranchFuncCall { + f.mutex.Lock() + history := make([]GitserverClientGetDefaultBranchFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientGetDefaultBranchFuncCall is an object that describes an +// invocation of method GetDefaultBranch on an instance of +// MockGitserverClient. +type GitserverClientGetDefaultBranchFuncCall 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 bool + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 string + // Result1 is the value of the 2nd result returned from this method + // invocation. + Result1 api.CommitID + // Result2 is the value of the 3rd result returned from this method + // invocation. + Result2 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c GitserverClientGetDefaultBranchFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientGetDefaultBranchFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1, c.Result2} +} + +// GitserverClientGetObjectFunc describes the behavior when the GetObject +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientGetObjectFunc struct { + defaultHook func(context.Context, api.RepoName, string) (*gitdomain.GitObject, error) + hooks []func(context.Context, api.RepoName, string) (*gitdomain.GitObject, error) + history []GitserverClientGetObjectFuncCall + mutex sync.Mutex +} + +// GetObject delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) GetObject(v0 context.Context, v1 api.RepoName, v2 string) (*gitdomain.GitObject, error) { + r0, r1 := m.GetObjectFunc.nextHook()(v0, v1, v2) + m.GetObjectFunc.appendCall(GitserverClientGetObjectFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the GetObject method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientGetObjectFunc) SetDefaultHook(hook func(context.Context, api.RepoName, string) (*gitdomain.GitObject, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// GetObject 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 *GitserverClientGetObjectFunc) PushHook(hook func(context.Context, api.RepoName, string) (*gitdomain.GitObject, 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 *GitserverClientGetObjectFunc) SetDefaultReturn(r0 *gitdomain.GitObject, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, string) (*gitdomain.GitObject, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientGetObjectFunc) PushReturn(r0 *gitdomain.GitObject, r1 error) { + f.PushHook(func(context.Context, api.RepoName, string) (*gitdomain.GitObject, error) { + return r0, r1 + }) +} + +func (f *GitserverClientGetObjectFunc) nextHook() func(context.Context, api.RepoName, string) (*gitdomain.GitObject, 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 *GitserverClientGetObjectFunc) appendCall(r0 GitserverClientGetObjectFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientGetObjectFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientGetObjectFunc) History() []GitserverClientGetObjectFuncCall { + f.mutex.Lock() + history := make([]GitserverClientGetObjectFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientGetObjectFuncCall is an object that describes an +// invocation of method GetObject on an instance of MockGitserverClient. +type GitserverClientGetObjectFuncCall 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 string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *gitdomain.GitObject + // 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 GitserverClientGetObjectFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientGetObjectFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientHasCommitAfterFunc describes the behavior when the +// HasCommitAfter method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientHasCommitAfterFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string) (bool, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string) (bool, error) + history []GitserverClientHasCommitAfterFuncCall + mutex sync.Mutex +} + +// HasCommitAfter delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) HasCommitAfter(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 string, v4 string) (bool, error) { + r0, r1 := m.HasCommitAfterFunc.nextHook()(v0, v1, v2, v3, v4) + m.HasCommitAfterFunc.appendCall(GitserverClientHasCommitAfterFuncCall{v0, v1, v2, v3, v4, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the HasCommitAfter +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientHasCommitAfterFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string) (bool, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// HasCommitAfter 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 *GitserverClientHasCommitAfterFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string) (bool, 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 *GitserverClientHasCommitAfterFunc) SetDefaultReturn(r0 bool, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string) (bool, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientHasCommitAfterFunc) PushReturn(r0 bool, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string) (bool, error) { + return r0, r1 + }) +} + +func (f *GitserverClientHasCommitAfterFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, string) (bool, 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 *GitserverClientHasCommitAfterFunc) appendCall(r0 GitserverClientHasCommitAfterFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientHasCommitAfterFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientHasCommitAfterFunc) History() []GitserverClientHasCommitAfterFuncCall { + f.mutex.Lock() + history := make([]GitserverClientHasCommitAfterFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientHasCommitAfterFuncCall is an object that describes an +// invocation of method HasCommitAfter on an instance of +// MockGitserverClient. +type GitserverClientHasCommitAfterFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 string + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 bool + // 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 GitserverClientHasCommitAfterFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientHasCommitAfterFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientHeadFunc describes the behavior when the Head method of +// the parent MockGitserverClient instance is invoked. +type GitserverClientHeadFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (string, bool, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (string, bool, error) + history []GitserverClientHeadFuncCall + mutex sync.Mutex +} + +// Head delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) Head(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName) (string, bool, error) { + r0, r1, r2 := m.HeadFunc.nextHook()(v0, v1, v2) + m.HeadFunc.appendCall(GitserverClientHeadFuncCall{v0, v1, v2, r0, r1, r2}) + return r0, r1, r2 +} + +// SetDefaultHook sets function that is called when the Head method of the +// parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientHeadFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (string, bool, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// Head 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 *GitserverClientHeadFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (string, bool, 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 *GitserverClientHeadFunc) SetDefaultReturn(r0 string, r1 bool, r2 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (string, bool, error) { + return r0, r1, r2 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientHeadFunc) PushReturn(r0 string, r1 bool, r2 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (string, bool, error) { + return r0, r1, r2 + }) +} + +func (f *GitserverClientHeadFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName) (string, bool, 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 *GitserverClientHeadFunc) appendCall(r0 GitserverClientHeadFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientHeadFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientHeadFunc) History() []GitserverClientHeadFuncCall { + f.mutex.Lock() + history := make([]GitserverClientHeadFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientHeadFuncCall is an object that describes an invocation of +// method Head on an instance of MockGitserverClient. +type GitserverClientHeadFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 string + // Result1 is the value of the 2nd result returned from this method + // invocation. + Result1 bool + // Result2 is the value of the 3rd result returned from this method + // invocation. + Result2 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c GitserverClientHeadFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientHeadFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1, c.Result2} +} + +// GitserverClientIsRepoCloneableFunc describes the behavior when the +// IsRepoCloneable method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientIsRepoCloneableFunc struct { + defaultHook func(context.Context, api.RepoName) error + hooks []func(context.Context, api.RepoName) error + history []GitserverClientIsRepoCloneableFuncCall + mutex sync.Mutex +} + +// IsRepoCloneable delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) IsRepoCloneable(v0 context.Context, v1 api.RepoName) error { + r0 := m.IsRepoCloneableFunc.nextHook()(v0, v1) + m.IsRepoCloneableFunc.appendCall(GitserverClientIsRepoCloneableFuncCall{v0, v1, r0}) + return r0 +} + +// SetDefaultHook sets function that is called when the IsRepoCloneable +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientIsRepoCloneableFunc) SetDefaultHook(hook func(context.Context, api.RepoName) error) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// IsRepoCloneable 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 *GitserverClientIsRepoCloneableFunc) PushHook(hook func(context.Context, api.RepoName) 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 *GitserverClientIsRepoCloneableFunc) SetDefaultReturn(r0 error) { + f.SetDefaultHook(func(context.Context, api.RepoName) error { + return r0 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientIsRepoCloneableFunc) PushReturn(r0 error) { + f.PushHook(func(context.Context, api.RepoName) error { + return r0 + }) +} + +func (f *GitserverClientIsRepoCloneableFunc) nextHook() func(context.Context, api.RepoName) 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 *GitserverClientIsRepoCloneableFunc) appendCall(r0 GitserverClientIsRepoCloneableFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientIsRepoCloneableFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientIsRepoCloneableFunc) History() []GitserverClientIsRepoCloneableFuncCall { + f.mutex.Lock() + history := make([]GitserverClientIsRepoCloneableFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientIsRepoCloneableFuncCall is an object that describes an +// invocation of method IsRepoCloneable on an instance of +// MockGitserverClient. +type GitserverClientIsRepoCloneableFuncCall 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 + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c GitserverClientIsRepoCloneableFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientIsRepoCloneableFuncCall) Results() []interface{} { + return []interface{}{c.Result0} +} + +// GitserverClientListBranchesFunc describes the behavior when the +// ListBranches method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientListBranchesFunc struct { + defaultHook func(context.Context, api.RepoName, gitserver.BranchesOptions) ([]*gitdomain.Branch, error) + hooks []func(context.Context, api.RepoName, gitserver.BranchesOptions) ([]*gitdomain.Branch, error) + history []GitserverClientListBranchesFuncCall + mutex sync.Mutex +} + +// ListBranches delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) ListBranches(v0 context.Context, v1 api.RepoName, v2 gitserver.BranchesOptions) ([]*gitdomain.Branch, error) { + r0, r1 := m.ListBranchesFunc.nextHook()(v0, v1, v2) + m.ListBranchesFunc.appendCall(GitserverClientListBranchesFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the ListBranches method +// of the parent MockGitserverClient instance is invoked and the hook queue +// is empty. +func (f *GitserverClientListBranchesFunc) SetDefaultHook(hook func(context.Context, api.RepoName, gitserver.BranchesOptions) ([]*gitdomain.Branch, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ListBranches 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 *GitserverClientListBranchesFunc) PushHook(hook func(context.Context, api.RepoName, gitserver.BranchesOptions) ([]*gitdomain.Branch, 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 *GitserverClientListBranchesFunc) SetDefaultReturn(r0 []*gitdomain.Branch, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, gitserver.BranchesOptions) ([]*gitdomain.Branch, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientListBranchesFunc) PushReturn(r0 []*gitdomain.Branch, r1 error) { + f.PushHook(func(context.Context, api.RepoName, gitserver.BranchesOptions) ([]*gitdomain.Branch, error) { + return r0, r1 + }) +} + +func (f *GitserverClientListBranchesFunc) nextHook() func(context.Context, api.RepoName, gitserver.BranchesOptions) ([]*gitdomain.Branch, 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 *GitserverClientListBranchesFunc) appendCall(r0 GitserverClientListBranchesFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientListBranchesFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientListBranchesFunc) History() []GitserverClientListBranchesFuncCall { + f.mutex.Lock() + history := make([]GitserverClientListBranchesFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientListBranchesFuncCall is an object that describes an +// invocation of method ListBranches on an instance of MockGitserverClient. +type GitserverClientListBranchesFuncCall 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 gitserver.BranchesOptions + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []*gitdomain.Branch + // 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 GitserverClientListBranchesFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientListBranchesFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientListDirectoryChildrenFunc describes the behavior when the +// ListDirectoryChildren method of the parent MockGitserverClient instance +// is invoked. +type GitserverClientListDirectoryChildrenFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, []string) (map[string][]string, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, []string) (map[string][]string, error) + history []GitserverClientListDirectoryChildrenFuncCall + mutex sync.Mutex +} + +// ListDirectoryChildren delegates to the next hook function in the queue +// and stores the parameter and result values of this invocation. +func (m *MockGitserverClient) ListDirectoryChildren(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 api.CommitID, v4 []string) (map[string][]string, error) { + r0, r1 := m.ListDirectoryChildrenFunc.nextHook()(v0, v1, v2, v3, v4) + m.ListDirectoryChildrenFunc.appendCall(GitserverClientListDirectoryChildrenFuncCall{v0, v1, v2, v3, v4, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the +// ListDirectoryChildren method of the parent MockGitserverClient instance +// is invoked and the hook queue is empty. +func (f *GitserverClientListDirectoryChildrenFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, []string) (map[string][]string, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ListDirectoryChildren 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 *GitserverClientListDirectoryChildrenFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, []string) (map[string][]string, 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 *GitserverClientListDirectoryChildrenFunc) SetDefaultReturn(r0 map[string][]string, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, []string) (map[string][]string, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientListDirectoryChildrenFunc) PushReturn(r0 map[string][]string, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, []string) (map[string][]string, error) { + return r0, r1 + }) +} + +func (f *GitserverClientListDirectoryChildrenFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, []string) (map[string][]string, 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 *GitserverClientListDirectoryChildrenFunc) appendCall(r0 GitserverClientListDirectoryChildrenFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of +// GitserverClientListDirectoryChildrenFuncCall objects describing the +// invocations of this function. +func (f *GitserverClientListDirectoryChildrenFunc) History() []GitserverClientListDirectoryChildrenFuncCall { + f.mutex.Lock() + history := make([]GitserverClientListDirectoryChildrenFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientListDirectoryChildrenFuncCall is an object that describes +// an invocation of method ListDirectoryChildren on an instance of +// MockGitserverClient. +type GitserverClientListDirectoryChildrenFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 api.CommitID + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 []string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 map[string][]string + // 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 GitserverClientListDirectoryChildrenFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientListDirectoryChildrenFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientListFilesFunc describes the behavior when the ListFiles +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientListFilesFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, *protocol.ListFilesOpts) ([]string, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, *protocol.ListFilesOpts) ([]string, error) + history []GitserverClientListFilesFuncCall + mutex sync.Mutex +} + +// ListFiles delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) ListFiles(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 api.CommitID, v4 *protocol.ListFilesOpts) ([]string, error) { + r0, r1 := m.ListFilesFunc.nextHook()(v0, v1, v2, v3, v4) + m.ListFilesFunc.appendCall(GitserverClientListFilesFuncCall{v0, v1, v2, v3, v4, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the ListFiles method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientListFilesFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, *protocol.ListFilesOpts) ([]string, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ListFiles 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 *GitserverClientListFilesFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, *protocol.ListFilesOpts) ([]string, 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 *GitserverClientListFilesFunc) SetDefaultReturn(r0 []string, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, *protocol.ListFilesOpts) ([]string, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientListFilesFunc) PushReturn(r0 []string, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, *protocol.ListFilesOpts) ([]string, error) { + return r0, r1 + }) +} + +func (f *GitserverClientListFilesFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, *protocol.ListFilesOpts) ([]string, 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 *GitserverClientListFilesFunc) appendCall(r0 GitserverClientListFilesFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientListFilesFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientListFilesFunc) History() []GitserverClientListFilesFuncCall { + f.mutex.Lock() + history := make([]GitserverClientListFilesFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientListFilesFuncCall is an object that describes an +// invocation of method ListFiles on an instance of MockGitserverClient. +type GitserverClientListFilesFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 api.CommitID + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 *protocol.ListFilesOpts + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []string + // 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 GitserverClientListFilesFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientListFilesFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientListRefsFunc describes the behavior when the ListRefs +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientListRefsFunc struct { + defaultHook func(context.Context, api.RepoName) ([]gitdomain.Ref, error) + hooks []func(context.Context, api.RepoName) ([]gitdomain.Ref, error) + history []GitserverClientListRefsFuncCall + mutex sync.Mutex +} + +// ListRefs delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) ListRefs(v0 context.Context, v1 api.RepoName) ([]gitdomain.Ref, error) { + r0, r1 := m.ListRefsFunc.nextHook()(v0, v1) + m.ListRefsFunc.appendCall(GitserverClientListRefsFuncCall{v0, v1, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the ListRefs method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientListRefsFunc) SetDefaultHook(hook func(context.Context, api.RepoName) ([]gitdomain.Ref, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ListRefs 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 *GitserverClientListRefsFunc) PushHook(hook func(context.Context, api.RepoName) ([]gitdomain.Ref, 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 *GitserverClientListRefsFunc) SetDefaultReturn(r0 []gitdomain.Ref, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName) ([]gitdomain.Ref, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientListRefsFunc) PushReturn(r0 []gitdomain.Ref, r1 error) { + f.PushHook(func(context.Context, api.RepoName) ([]gitdomain.Ref, error) { + return r0, r1 + }) +} + +func (f *GitserverClientListRefsFunc) nextHook() func(context.Context, api.RepoName) ([]gitdomain.Ref, 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 *GitserverClientListRefsFunc) appendCall(r0 GitserverClientListRefsFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientListRefsFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientListRefsFunc) History() []GitserverClientListRefsFuncCall { + f.mutex.Lock() + history := make([]GitserverClientListRefsFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientListRefsFuncCall is an object that describes an invocation +// of method ListRefs on an instance of MockGitserverClient. +type GitserverClientListRefsFuncCall 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 + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []gitdomain.Ref + // 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 GitserverClientListRefsFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientListRefsFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientListTagsFunc describes the behavior when the ListTags +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientListTagsFunc struct { + defaultHook func(context.Context, api.RepoName, ...string) ([]*gitdomain.Tag, error) + hooks []func(context.Context, api.RepoName, ...string) ([]*gitdomain.Tag, error) + history []GitserverClientListTagsFuncCall + mutex sync.Mutex +} + +// ListTags delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) ListTags(v0 context.Context, v1 api.RepoName, v2 ...string) ([]*gitdomain.Tag, error) { + r0, r1 := m.ListTagsFunc.nextHook()(v0, v1, v2...) + m.ListTagsFunc.appendCall(GitserverClientListTagsFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the ListTags method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientListTagsFunc) SetDefaultHook(hook func(context.Context, api.RepoName, ...string) ([]*gitdomain.Tag, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ListTags 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 *GitserverClientListTagsFunc) PushHook(hook func(context.Context, api.RepoName, ...string) ([]*gitdomain.Tag, 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 *GitserverClientListTagsFunc) SetDefaultReturn(r0 []*gitdomain.Tag, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, ...string) ([]*gitdomain.Tag, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientListTagsFunc) PushReturn(r0 []*gitdomain.Tag, r1 error) { + f.PushHook(func(context.Context, api.RepoName, ...string) ([]*gitdomain.Tag, error) { + return r0, r1 + }) +} + +func (f *GitserverClientListTagsFunc) nextHook() func(context.Context, api.RepoName, ...string) ([]*gitdomain.Tag, 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 *GitserverClientListTagsFunc) appendCall(r0 GitserverClientListTagsFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientListTagsFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientListTagsFunc) History() []GitserverClientListTagsFuncCall { + f.mutex.Lock() + history := make([]GitserverClientListTagsFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientListTagsFuncCall is an object that describes an invocation +// of method ListTags on an instance of MockGitserverClient. +type GitserverClientListTagsFuncCall 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 a slice containing the values of the variadic arguments + // passed to this method invocation. + Arg2 []string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []*gitdomain.Tag + // 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. The variadic slice argument is flattened in this array such +// that one positional argument and three variadic arguments would result in +// a slice of four, not two. +func (c GitserverClientListTagsFuncCall) Args() []interface{} { + trailing := []interface{}{} + for _, val := range c.Arg2 { + trailing = append(trailing, val) + } + + return append([]interface{}{c.Arg0, c.Arg1}, trailing...) +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientListTagsFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientLogReverseEachFunc describes the behavior when the +// LogReverseEach method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientLogReverseEachFunc struct { + defaultHook func(context.Context, string, string, int, func(entry gitdomain.LogEntry) error) error + hooks []func(context.Context, string, string, int, func(entry gitdomain.LogEntry) error) error + history []GitserverClientLogReverseEachFuncCall + mutex sync.Mutex +} + +// LogReverseEach delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) LogReverseEach(v0 context.Context, v1 string, v2 string, v3 int, v4 func(entry gitdomain.LogEntry) error) error { + r0 := m.LogReverseEachFunc.nextHook()(v0, v1, v2, v3, v4) + m.LogReverseEachFunc.appendCall(GitserverClientLogReverseEachFuncCall{v0, v1, v2, v3, v4, r0}) + return r0 +} + +// SetDefaultHook sets function that is called when the LogReverseEach +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientLogReverseEachFunc) SetDefaultHook(hook func(context.Context, string, string, int, func(entry gitdomain.LogEntry) error) error) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// LogReverseEach 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 *GitserverClientLogReverseEachFunc) PushHook(hook func(context.Context, string, string, int, func(entry gitdomain.LogEntry) error) 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 *GitserverClientLogReverseEachFunc) SetDefaultReturn(r0 error) { + f.SetDefaultHook(func(context.Context, string, string, int, func(entry gitdomain.LogEntry) error) error { + return r0 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientLogReverseEachFunc) PushReturn(r0 error) { + f.PushHook(func(context.Context, string, string, int, func(entry gitdomain.LogEntry) error) error { + return r0 + }) +} + +func (f *GitserverClientLogReverseEachFunc) nextHook() func(context.Context, string, string, int, func(entry gitdomain.LogEntry) error) 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 *GitserverClientLogReverseEachFunc) appendCall(r0 GitserverClientLogReverseEachFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientLogReverseEachFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientLogReverseEachFunc) History() []GitserverClientLogReverseEachFuncCall { + f.mutex.Lock() + history := make([]GitserverClientLogReverseEachFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientLogReverseEachFuncCall is an object that describes an +// invocation of method LogReverseEach on an instance of +// MockGitserverClient. +type GitserverClientLogReverseEachFuncCall 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 string + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 string + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 int + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 func(entry gitdomain.LogEntry) error + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c GitserverClientLogReverseEachFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientLogReverseEachFuncCall) Results() []interface{} { + return []interface{}{c.Result0} +} + +// GitserverClientLsFilesFunc describes the behavior when the LsFiles method +// of the parent MockGitserverClient instance is invoked. +type GitserverClientLsFilesFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, ...gitdomain.Pathspec) ([]string, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, ...gitdomain.Pathspec) ([]string, error) + history []GitserverClientLsFilesFuncCall + mutex sync.Mutex +} + +// LsFiles delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) LsFiles(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 api.CommitID, v4 ...gitdomain.Pathspec) ([]string, error) { + r0, r1 := m.LsFilesFunc.nextHook()(v0, v1, v2, v3, v4...) + m.LsFilesFunc.appendCall(GitserverClientLsFilesFuncCall{v0, v1, v2, v3, v4, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the LsFiles method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientLsFilesFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, ...gitdomain.Pathspec) ([]string, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// LsFiles 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 *GitserverClientLsFilesFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, ...gitdomain.Pathspec) ([]string, 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 *GitserverClientLsFilesFunc) SetDefaultReturn(r0 []string, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, ...gitdomain.Pathspec) ([]string, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientLsFilesFunc) PushReturn(r0 []string, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, ...gitdomain.Pathspec) ([]string, error) { + return r0, r1 + }) +} + +func (f *GitserverClientLsFilesFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, ...gitdomain.Pathspec) ([]string, 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 *GitserverClientLsFilesFunc) appendCall(r0 GitserverClientLsFilesFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientLsFilesFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientLsFilesFunc) History() []GitserverClientLsFilesFuncCall { + f.mutex.Lock() + history := make([]GitserverClientLsFilesFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientLsFilesFuncCall is an object that describes an invocation +// of method LsFiles on an instance of MockGitserverClient. +type GitserverClientLsFilesFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 api.CommitID + // Arg4 is a slice containing the values of the variadic arguments + // passed to this method invocation. + Arg4 []gitdomain.Pathspec + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []string + // 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. The variadic slice argument is flattened in this array such +// that one positional argument and three variadic arguments would result in +// a slice of four, not two. +func (c GitserverClientLsFilesFuncCall) Args() []interface{} { + trailing := []interface{}{} + for _, val := range c.Arg4 { + trailing = append(trailing, val) + } + + return append([]interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3}, trailing...) +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientLsFilesFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientMergeBaseFunc describes the behavior when the MergeBase +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientMergeBaseFunc struct { + defaultHook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (api.CommitID, error) + hooks []func(context.Context, api.RepoName, api.CommitID, api.CommitID) (api.CommitID, error) + history []GitserverClientMergeBaseFuncCall + mutex sync.Mutex +} + +// MergeBase delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) MergeBase(v0 context.Context, v1 api.RepoName, v2 api.CommitID, v3 api.CommitID) (api.CommitID, error) { + r0, r1 := m.MergeBaseFunc.nextHook()(v0, v1, v2, v3) + m.MergeBaseFunc.appendCall(GitserverClientMergeBaseFuncCall{v0, v1, v2, v3, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the MergeBase method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientMergeBaseFunc) SetDefaultHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (api.CommitID, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// MergeBase 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 *GitserverClientMergeBaseFunc) PushHook(hook func(context.Context, api.RepoName, api.CommitID, api.CommitID) (api.CommitID, 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 *GitserverClientMergeBaseFunc) SetDefaultReturn(r0 api.CommitID, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) (api.CommitID, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientMergeBaseFunc) PushReturn(r0 api.CommitID, r1 error) { + f.PushHook(func(context.Context, api.RepoName, api.CommitID, api.CommitID) (api.CommitID, error) { + return r0, r1 + }) +} + +func (f *GitserverClientMergeBaseFunc) nextHook() func(context.Context, api.RepoName, api.CommitID, api.CommitID) (api.CommitID, 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 *GitserverClientMergeBaseFunc) appendCall(r0 GitserverClientMergeBaseFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientMergeBaseFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientMergeBaseFunc) History() []GitserverClientMergeBaseFuncCall { + f.mutex.Lock() + history := make([]GitserverClientMergeBaseFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientMergeBaseFuncCall is an object that describes an +// invocation of method MergeBase on an instance of MockGitserverClient. +type GitserverClientMergeBaseFuncCall 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 api.CommitID + // 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 GitserverClientMergeBaseFuncCall) 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 GitserverClientMergeBaseFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientNewFileReaderFunc describes the behavior when the +// NewFileReader method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientNewFileReaderFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (io.ReadCloser, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (io.ReadCloser, error) + history []GitserverClientNewFileReaderFuncCall + mutex sync.Mutex +} + +// NewFileReader delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) NewFileReader(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 api.CommitID, v4 string) (io.ReadCloser, error) { + r0, r1 := m.NewFileReaderFunc.nextHook()(v0, v1, v2, v3, v4) + m.NewFileReaderFunc.appendCall(GitserverClientNewFileReaderFuncCall{v0, v1, v2, v3, v4, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the NewFileReader method +// of the parent MockGitserverClient instance is invoked and the hook queue +// is empty. +func (f *GitserverClientNewFileReaderFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (io.ReadCloser, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// NewFileReader 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 *GitserverClientNewFileReaderFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (io.ReadCloser, 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 *GitserverClientNewFileReaderFunc) SetDefaultReturn(r0 io.ReadCloser, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (io.ReadCloser, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientNewFileReaderFunc) PushReturn(r0 io.ReadCloser, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (io.ReadCloser, error) { + return r0, r1 + }) +} + +func (f *GitserverClientNewFileReaderFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (io.ReadCloser, 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 *GitserverClientNewFileReaderFunc) appendCall(r0 GitserverClientNewFileReaderFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientNewFileReaderFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientNewFileReaderFunc) History() []GitserverClientNewFileReaderFuncCall { + f.mutex.Lock() + history := make([]GitserverClientNewFileReaderFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientNewFileReaderFuncCall is an object that describes an +// invocation of method NewFileReader on an instance of MockGitserverClient. +type GitserverClientNewFileReaderFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 api.CommitID + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 io.ReadCloser + // 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 GitserverClientNewFileReaderFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientNewFileReaderFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientP4ExecFunc describes the behavior when the P4Exec method +// of the parent MockGitserverClient instance is invoked. +type GitserverClientP4ExecFunc struct { + defaultHook func(context.Context, string, string, string, ...string) (io.ReadCloser, http.Header, error) + hooks []func(context.Context, string, string, string, ...string) (io.ReadCloser, http.Header, error) + history []GitserverClientP4ExecFuncCall + mutex sync.Mutex +} + +// P4Exec delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) P4Exec(v0 context.Context, v1 string, v2 string, v3 string, v4 ...string) (io.ReadCloser, http.Header, error) { + r0, r1, r2 := m.P4ExecFunc.nextHook()(v0, v1, v2, v3, v4...) + m.P4ExecFunc.appendCall(GitserverClientP4ExecFuncCall{v0, v1, v2, v3, v4, r0, r1, r2}) + return r0, r1, r2 +} + +// SetDefaultHook sets function that is called when the P4Exec method of the +// parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientP4ExecFunc) SetDefaultHook(hook func(context.Context, string, string, string, ...string) (io.ReadCloser, http.Header, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// P4Exec 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 *GitserverClientP4ExecFunc) PushHook(hook func(context.Context, string, string, string, ...string) (io.ReadCloser, http.Header, 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 *GitserverClientP4ExecFunc) SetDefaultReturn(r0 io.ReadCloser, r1 http.Header, r2 error) { + f.SetDefaultHook(func(context.Context, string, string, string, ...string) (io.ReadCloser, http.Header, error) { + return r0, r1, r2 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientP4ExecFunc) PushReturn(r0 io.ReadCloser, r1 http.Header, r2 error) { + f.PushHook(func(context.Context, string, string, string, ...string) (io.ReadCloser, http.Header, error) { + return r0, r1, r2 + }) +} + +func (f *GitserverClientP4ExecFunc) nextHook() func(context.Context, string, string, string, ...string) (io.ReadCloser, http.Header, 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 *GitserverClientP4ExecFunc) appendCall(r0 GitserverClientP4ExecFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientP4ExecFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientP4ExecFunc) History() []GitserverClientP4ExecFuncCall { + f.mutex.Lock() + history := make([]GitserverClientP4ExecFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientP4ExecFuncCall is an object that describes an invocation +// of method P4Exec on an instance of MockGitserverClient. +type GitserverClientP4ExecFuncCall 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 string + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 string + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 string + // Arg4 is a slice containing the values of the variadic arguments + // passed to this method invocation. + Arg4 []string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 io.ReadCloser + // Result1 is the value of the 2nd result returned from this method + // invocation. + Result1 http.Header + // Result2 is the value of the 3rd result returned from this method + // invocation. + Result2 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. The variadic slice argument is flattened in this array such +// that one positional argument and three variadic arguments would result in +// a slice of four, not two. +func (c GitserverClientP4ExecFuncCall) Args() []interface{} { + trailing := []interface{}{} + for _, val := range c.Arg4 { + trailing = append(trailing, val) + } + + return append([]interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3}, trailing...) +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientP4ExecFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1, c.Result2} +} + +// GitserverClientP4GetChangelistFunc describes the behavior when the +// P4GetChangelist method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientP4GetChangelistFunc struct { + defaultHook func(context.Context, string, gitserver.PerforceCredentials) (*protocol.PerforceChangelist, error) + hooks []func(context.Context, string, gitserver.PerforceCredentials) (*protocol.PerforceChangelist, error) + history []GitserverClientP4GetChangelistFuncCall + mutex sync.Mutex +} + +// P4GetChangelist delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) P4GetChangelist(v0 context.Context, v1 string, v2 gitserver.PerforceCredentials) (*protocol.PerforceChangelist, error) { + r0, r1 := m.P4GetChangelistFunc.nextHook()(v0, v1, v2) + m.P4GetChangelistFunc.appendCall(GitserverClientP4GetChangelistFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the P4GetChangelist +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientP4GetChangelistFunc) SetDefaultHook(hook func(context.Context, string, gitserver.PerforceCredentials) (*protocol.PerforceChangelist, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// P4GetChangelist 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 *GitserverClientP4GetChangelistFunc) PushHook(hook func(context.Context, string, gitserver.PerforceCredentials) (*protocol.PerforceChangelist, 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 *GitserverClientP4GetChangelistFunc) SetDefaultReturn(r0 *protocol.PerforceChangelist, r1 error) { + f.SetDefaultHook(func(context.Context, string, gitserver.PerforceCredentials) (*protocol.PerforceChangelist, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientP4GetChangelistFunc) PushReturn(r0 *protocol.PerforceChangelist, r1 error) { + f.PushHook(func(context.Context, string, gitserver.PerforceCredentials) (*protocol.PerforceChangelist, error) { + return r0, r1 + }) +} + +func (f *GitserverClientP4GetChangelistFunc) nextHook() func(context.Context, string, gitserver.PerforceCredentials) (*protocol.PerforceChangelist, 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 *GitserverClientP4GetChangelistFunc) appendCall(r0 GitserverClientP4GetChangelistFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientP4GetChangelistFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientP4GetChangelistFunc) History() []GitserverClientP4GetChangelistFuncCall { + f.mutex.Lock() + history := make([]GitserverClientP4GetChangelistFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientP4GetChangelistFuncCall is an object that describes an +// invocation of method P4GetChangelist on an instance of +// MockGitserverClient. +type GitserverClientP4GetChangelistFuncCall 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 string + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 gitserver.PerforceCredentials + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *protocol.PerforceChangelist + // 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 GitserverClientP4GetChangelistFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientP4GetChangelistFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientReadDirFunc describes the behavior when the ReadDir method +// of the parent MockGitserverClient instance is invoked. +type GitserverClientReadDirFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string, bool) ([]fs.FileInfo, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string, bool) ([]fs.FileInfo, error) + history []GitserverClientReadDirFuncCall + mutex sync.Mutex +} + +// ReadDir delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) ReadDir(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 api.CommitID, v4 string, v5 bool) ([]fs.FileInfo, error) { + r0, r1 := m.ReadDirFunc.nextHook()(v0, v1, v2, v3, v4, v5) + m.ReadDirFunc.appendCall(GitserverClientReadDirFuncCall{v0, v1, v2, v3, v4, v5, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the ReadDir method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientReadDirFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string, bool) ([]fs.FileInfo, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ReadDir 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 *GitserverClientReadDirFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string, bool) ([]fs.FileInfo, 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 *GitserverClientReadDirFunc) SetDefaultReturn(r0 []fs.FileInfo, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string, bool) ([]fs.FileInfo, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientReadDirFunc) PushReturn(r0 []fs.FileInfo, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string, bool) ([]fs.FileInfo, error) { + return r0, r1 + }) +} + +func (f *GitserverClientReadDirFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string, bool) ([]fs.FileInfo, 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 *GitserverClientReadDirFunc) appendCall(r0 GitserverClientReadDirFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientReadDirFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientReadDirFunc) History() []GitserverClientReadDirFuncCall { + f.mutex.Lock() + history := make([]GitserverClientReadDirFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientReadDirFuncCall is an object that describes an invocation +// of method ReadDir on an instance of MockGitserverClient. +type GitserverClientReadDirFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 api.CommitID + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 string + // Arg5 is the value of the 6th argument passed to this method + // invocation. + Arg5 bool + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []fs.FileInfo + // 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 GitserverClientReadDirFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4, c.Arg5} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientReadDirFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientReadFileFunc describes the behavior when the ReadFile +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientReadFileFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) ([]byte, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) ([]byte, error) + history []GitserverClientReadFileFuncCall + mutex sync.Mutex +} + +// ReadFile delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) ReadFile(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 api.CommitID, v4 string) ([]byte, error) { + r0, r1 := m.ReadFileFunc.nextHook()(v0, v1, v2, v3, v4) + m.ReadFileFunc.appendCall(GitserverClientReadFileFuncCall{v0, v1, v2, v3, v4, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the ReadFile method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientReadFileFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) ([]byte, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ReadFile 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 *GitserverClientReadFileFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) ([]byte, 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 *GitserverClientReadFileFunc) SetDefaultReturn(r0 []byte, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) ([]byte, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientReadFileFunc) PushReturn(r0 []byte, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) ([]byte, error) { + return r0, r1 + }) +} + +func (f *GitserverClientReadFileFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) ([]byte, 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 *GitserverClientReadFileFunc) appendCall(r0 GitserverClientReadFileFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientReadFileFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientReadFileFunc) History() []GitserverClientReadFileFuncCall { + f.mutex.Lock() + history := make([]GitserverClientReadFileFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientReadFileFuncCall is an object that describes an invocation +// of method ReadFile on an instance of MockGitserverClient. +type GitserverClientReadFileFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 api.CommitID + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []byte + // 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 GitserverClientReadFileFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientReadFileFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientRefDescriptionsFunc describes the behavior when the +// RefDescriptions method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientRefDescriptionsFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, ...string) (map[string][]gitdomain.RefDescription, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, ...string) (map[string][]gitdomain.RefDescription, error) + history []GitserverClientRefDescriptionsFuncCall + mutex sync.Mutex +} + +// RefDescriptions delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) RefDescriptions(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 ...string) (map[string][]gitdomain.RefDescription, error) { + r0, r1 := m.RefDescriptionsFunc.nextHook()(v0, v1, v2, v3...) + m.RefDescriptionsFunc.appendCall(GitserverClientRefDescriptionsFuncCall{v0, v1, v2, v3, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the RefDescriptions +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientRefDescriptionsFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, ...string) (map[string][]gitdomain.RefDescription, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// RefDescriptions 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 *GitserverClientRefDescriptionsFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, ...string) (map[string][]gitdomain.RefDescription, 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 *GitserverClientRefDescriptionsFunc) SetDefaultReturn(r0 map[string][]gitdomain.RefDescription, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, ...string) (map[string][]gitdomain.RefDescription, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientRefDescriptionsFunc) PushReturn(r0 map[string][]gitdomain.RefDescription, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, ...string) (map[string][]gitdomain.RefDescription, error) { + return r0, r1 + }) +} + +func (f *GitserverClientRefDescriptionsFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, ...string) (map[string][]gitdomain.RefDescription, 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 *GitserverClientRefDescriptionsFunc) appendCall(r0 GitserverClientRefDescriptionsFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientRefDescriptionsFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientRefDescriptionsFunc) History() []GitserverClientRefDescriptionsFuncCall { + f.mutex.Lock() + history := make([]GitserverClientRefDescriptionsFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientRefDescriptionsFuncCall is an object that describes an +// invocation of method RefDescriptions on an instance of +// MockGitserverClient. +type GitserverClientRefDescriptionsFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is a slice containing the values of the variadic arguments + // passed to this method invocation. + Arg3 []string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 map[string][]gitdomain.RefDescription + // 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. The variadic slice argument is flattened in this array such +// that one positional argument and three variadic arguments would result in +// a slice of four, not two. +func (c GitserverClientRefDescriptionsFuncCall) Args() []interface{} { + trailing := []interface{}{} + for _, val := range c.Arg3 { + trailing = append(trailing, val) + } + + return append([]interface{}{c.Arg0, c.Arg1, c.Arg2}, trailing...) +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientRefDescriptionsFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientRemoveFunc describes the behavior when the Remove method +// of the parent MockGitserverClient instance is invoked. +type GitserverClientRemoveFunc struct { + defaultHook func(context.Context, api.RepoName) error + hooks []func(context.Context, api.RepoName) error + history []GitserverClientRemoveFuncCall + mutex sync.Mutex +} + +// Remove delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) Remove(v0 context.Context, v1 api.RepoName) error { + r0 := m.RemoveFunc.nextHook()(v0, v1) + m.RemoveFunc.appendCall(GitserverClientRemoveFuncCall{v0, v1, r0}) + return r0 +} + +// SetDefaultHook sets function that is called when the Remove method of the +// parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientRemoveFunc) SetDefaultHook(hook func(context.Context, api.RepoName) error) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// Remove 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 *GitserverClientRemoveFunc) PushHook(hook func(context.Context, api.RepoName) 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 *GitserverClientRemoveFunc) SetDefaultReturn(r0 error) { + f.SetDefaultHook(func(context.Context, api.RepoName) error { + return r0 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientRemoveFunc) PushReturn(r0 error) { + f.PushHook(func(context.Context, api.RepoName) error { + return r0 + }) +} + +func (f *GitserverClientRemoveFunc) nextHook() func(context.Context, api.RepoName) 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 *GitserverClientRemoveFunc) appendCall(r0 GitserverClientRemoveFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientRemoveFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientRemoveFunc) History() []GitserverClientRemoveFuncCall { + f.mutex.Lock() + history := make([]GitserverClientRemoveFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientRemoveFuncCall is an object that describes an invocation +// of method Remove on an instance of MockGitserverClient. +type GitserverClientRemoveFuncCall 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 + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c GitserverClientRemoveFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientRemoveFuncCall) Results() []interface{} { + return []interface{}{c.Result0} +} + +// GitserverClientRemoveFromFunc describes the behavior when the RemoveFrom +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientRemoveFromFunc struct { + defaultHook func(context.Context, api.RepoName, string) error + hooks []func(context.Context, api.RepoName, string) error + history []GitserverClientRemoveFromFuncCall + mutex sync.Mutex +} + +// RemoveFrom delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) RemoveFrom(v0 context.Context, v1 api.RepoName, v2 string) error { + r0 := m.RemoveFromFunc.nextHook()(v0, v1, v2) + m.RemoveFromFunc.appendCall(GitserverClientRemoveFromFuncCall{v0, v1, v2, r0}) + return r0 +} + +// SetDefaultHook sets function that is called when the RemoveFrom method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientRemoveFromFunc) SetDefaultHook(hook func(context.Context, api.RepoName, string) error) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// RemoveFrom 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 *GitserverClientRemoveFromFunc) PushHook(hook func(context.Context, api.RepoName, string) 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 *GitserverClientRemoveFromFunc) SetDefaultReturn(r0 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, string) error { + return r0 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientRemoveFromFunc) PushReturn(r0 error) { + f.PushHook(func(context.Context, api.RepoName, string) error { + return r0 + }) +} + +func (f *GitserverClientRemoveFromFunc) nextHook() func(context.Context, api.RepoName, string) 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 *GitserverClientRemoveFromFunc) appendCall(r0 GitserverClientRemoveFromFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientRemoveFromFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientRemoveFromFunc) History() []GitserverClientRemoveFromFuncCall { + f.mutex.Lock() + history := make([]GitserverClientRemoveFromFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientRemoveFromFuncCall is an object that describes an +// invocation of method RemoveFrom on an instance of MockGitserverClient. +type GitserverClientRemoveFromFuncCall 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 string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c GitserverClientRemoveFromFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientRemoveFromFuncCall) Results() []interface{} { + return []interface{}{c.Result0} +} + +// GitserverClientRepoCloneProgressFunc describes the behavior when the +// RepoCloneProgress method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientRepoCloneProgressFunc struct { + defaultHook func(context.Context, ...api.RepoName) (*protocol.RepoCloneProgressResponse, error) + hooks []func(context.Context, ...api.RepoName) (*protocol.RepoCloneProgressResponse, error) + history []GitserverClientRepoCloneProgressFuncCall + mutex sync.Mutex +} + +// RepoCloneProgress delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) RepoCloneProgress(v0 context.Context, v1 ...api.RepoName) (*protocol.RepoCloneProgressResponse, error) { + r0, r1 := m.RepoCloneProgressFunc.nextHook()(v0, v1...) + m.RepoCloneProgressFunc.appendCall(GitserverClientRepoCloneProgressFuncCall{v0, v1, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the RepoCloneProgress +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientRepoCloneProgressFunc) SetDefaultHook(hook func(context.Context, ...api.RepoName) (*protocol.RepoCloneProgressResponse, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// RepoCloneProgress 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 *GitserverClientRepoCloneProgressFunc) PushHook(hook func(context.Context, ...api.RepoName) (*protocol.RepoCloneProgressResponse, 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 *GitserverClientRepoCloneProgressFunc) SetDefaultReturn(r0 *protocol.RepoCloneProgressResponse, r1 error) { + f.SetDefaultHook(func(context.Context, ...api.RepoName) (*protocol.RepoCloneProgressResponse, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientRepoCloneProgressFunc) PushReturn(r0 *protocol.RepoCloneProgressResponse, r1 error) { + f.PushHook(func(context.Context, ...api.RepoName) (*protocol.RepoCloneProgressResponse, error) { + return r0, r1 + }) +} + +func (f *GitserverClientRepoCloneProgressFunc) nextHook() func(context.Context, ...api.RepoName) (*protocol.RepoCloneProgressResponse, 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 *GitserverClientRepoCloneProgressFunc) appendCall(r0 GitserverClientRepoCloneProgressFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientRepoCloneProgressFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientRepoCloneProgressFunc) History() []GitserverClientRepoCloneProgressFuncCall { + f.mutex.Lock() + history := make([]GitserverClientRepoCloneProgressFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientRepoCloneProgressFuncCall is an object that describes an +// invocation of method RepoCloneProgress on an instance of +// MockGitserverClient. +type GitserverClientRepoCloneProgressFuncCall struct { + // Arg0 is the value of the 1st argument passed to this method + // invocation. + Arg0 context.Context + // Arg1 is a slice containing the values of the variadic arguments + // passed to this method invocation. + Arg1 []api.RepoName + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *protocol.RepoCloneProgressResponse + // 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. The variadic slice argument is flattened in this array such +// that one positional argument and three variadic arguments would result in +// a slice of four, not two. +func (c GitserverClientRepoCloneProgressFuncCall) Args() []interface{} { + trailing := []interface{}{} + for _, val := range c.Arg1 { + trailing = append(trailing, val) + } + + return append([]interface{}{c.Arg0}, trailing...) +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientRepoCloneProgressFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientReposStatsFunc describes the behavior when the ReposStats +// method of the parent MockGitserverClient instance is invoked. +type GitserverClientReposStatsFunc struct { + defaultHook func(context.Context) (map[string]*protocol.ReposStats, error) + hooks []func(context.Context) (map[string]*protocol.ReposStats, error) + history []GitserverClientReposStatsFuncCall + mutex sync.Mutex +} + +// ReposStats delegates to the next hook function in the queue and stores +// the parameter and result values of this invocation. +func (m *MockGitserverClient) ReposStats(v0 context.Context) (map[string]*protocol.ReposStats, error) { + r0, r1 := m.ReposStatsFunc.nextHook()(v0) + m.ReposStatsFunc.appendCall(GitserverClientReposStatsFuncCall{v0, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the ReposStats method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientReposStatsFunc) SetDefaultHook(hook func(context.Context) (map[string]*protocol.ReposStats, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ReposStats 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 *GitserverClientReposStatsFunc) PushHook(hook func(context.Context) (map[string]*protocol.ReposStats, 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 *GitserverClientReposStatsFunc) SetDefaultReturn(r0 map[string]*protocol.ReposStats, r1 error) { + f.SetDefaultHook(func(context.Context) (map[string]*protocol.ReposStats, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientReposStatsFunc) PushReturn(r0 map[string]*protocol.ReposStats, r1 error) { + f.PushHook(func(context.Context) (map[string]*protocol.ReposStats, error) { + return r0, r1 + }) +} + +func (f *GitserverClientReposStatsFunc) nextHook() func(context.Context) (map[string]*protocol.ReposStats, 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 *GitserverClientReposStatsFunc) appendCall(r0 GitserverClientReposStatsFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientReposStatsFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientReposStatsFunc) History() []GitserverClientReposStatsFuncCall { + f.mutex.Lock() + history := make([]GitserverClientReposStatsFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientReposStatsFuncCall is an object that describes an +// invocation of method ReposStats on an instance of MockGitserverClient. +type GitserverClientReposStatsFuncCall struct { + // Arg0 is the value of the 1st argument passed to this method + // invocation. + Arg0 context.Context + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 map[string]*protocol.ReposStats + // 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 GitserverClientReposStatsFuncCall) Args() []interface{} { + return []interface{}{c.Arg0} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientReposStatsFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientRequestRepoCloneFunc describes the behavior when the +// RequestRepoClone method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientRequestRepoCloneFunc struct { + defaultHook func(context.Context, api.RepoName) (*protocol.RepoCloneResponse, error) + hooks []func(context.Context, api.RepoName) (*protocol.RepoCloneResponse, error) + history []GitserverClientRequestRepoCloneFuncCall + mutex sync.Mutex +} + +// RequestRepoClone delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) RequestRepoClone(v0 context.Context, v1 api.RepoName) (*protocol.RepoCloneResponse, error) { + r0, r1 := m.RequestRepoCloneFunc.nextHook()(v0, v1) + m.RequestRepoCloneFunc.appendCall(GitserverClientRequestRepoCloneFuncCall{v0, v1, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the RequestRepoClone +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientRequestRepoCloneFunc) SetDefaultHook(hook func(context.Context, api.RepoName) (*protocol.RepoCloneResponse, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// RequestRepoClone 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 *GitserverClientRequestRepoCloneFunc) PushHook(hook func(context.Context, api.RepoName) (*protocol.RepoCloneResponse, 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 *GitserverClientRequestRepoCloneFunc) SetDefaultReturn(r0 *protocol.RepoCloneResponse, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName) (*protocol.RepoCloneResponse, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientRequestRepoCloneFunc) PushReturn(r0 *protocol.RepoCloneResponse, r1 error) { + f.PushHook(func(context.Context, api.RepoName) (*protocol.RepoCloneResponse, error) { + return r0, r1 + }) +} + +func (f *GitserverClientRequestRepoCloneFunc) nextHook() func(context.Context, api.RepoName) (*protocol.RepoCloneResponse, 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 *GitserverClientRequestRepoCloneFunc) appendCall(r0 GitserverClientRequestRepoCloneFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientRequestRepoCloneFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientRequestRepoCloneFunc) History() []GitserverClientRequestRepoCloneFuncCall { + f.mutex.Lock() + history := make([]GitserverClientRequestRepoCloneFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientRequestRepoCloneFuncCall is an object that describes an +// invocation of method RequestRepoClone on an instance of +// MockGitserverClient. +type GitserverClientRequestRepoCloneFuncCall 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 + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *protocol.RepoCloneResponse + // 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 GitserverClientRequestRepoCloneFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientRequestRepoCloneFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientRequestRepoUpdateFunc describes the behavior when the +// RequestRepoUpdate method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientRequestRepoUpdateFunc struct { + defaultHook func(context.Context, api.RepoName, time.Duration) (*protocol.RepoUpdateResponse, error) + hooks []func(context.Context, api.RepoName, time.Duration) (*protocol.RepoUpdateResponse, error) + history []GitserverClientRequestRepoUpdateFuncCall + mutex sync.Mutex +} + +// RequestRepoUpdate delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) RequestRepoUpdate(v0 context.Context, v1 api.RepoName, v2 time.Duration) (*protocol.RepoUpdateResponse, error) { + r0, r1 := m.RequestRepoUpdateFunc.nextHook()(v0, v1, v2) + m.RequestRepoUpdateFunc.appendCall(GitserverClientRequestRepoUpdateFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the RequestRepoUpdate +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientRequestRepoUpdateFunc) SetDefaultHook(hook func(context.Context, api.RepoName, time.Duration) (*protocol.RepoUpdateResponse, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// RequestRepoUpdate 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 *GitserverClientRequestRepoUpdateFunc) PushHook(hook func(context.Context, api.RepoName, time.Duration) (*protocol.RepoUpdateResponse, 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 *GitserverClientRequestRepoUpdateFunc) SetDefaultReturn(r0 *protocol.RepoUpdateResponse, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, time.Duration) (*protocol.RepoUpdateResponse, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientRequestRepoUpdateFunc) PushReturn(r0 *protocol.RepoUpdateResponse, r1 error) { + f.PushHook(func(context.Context, api.RepoName, time.Duration) (*protocol.RepoUpdateResponse, error) { + return r0, r1 + }) +} + +func (f *GitserverClientRequestRepoUpdateFunc) nextHook() func(context.Context, api.RepoName, time.Duration) (*protocol.RepoUpdateResponse, 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 *GitserverClientRequestRepoUpdateFunc) appendCall(r0 GitserverClientRequestRepoUpdateFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientRequestRepoUpdateFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientRequestRepoUpdateFunc) History() []GitserverClientRequestRepoUpdateFuncCall { + f.mutex.Lock() + history := make([]GitserverClientRequestRepoUpdateFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientRequestRepoUpdateFuncCall is an object that describes an +// invocation of method RequestRepoUpdate on an instance of +// MockGitserverClient. +type GitserverClientRequestRepoUpdateFuncCall 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 time.Duration + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *protocol.RepoUpdateResponse + // 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 GitserverClientRequestRepoUpdateFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientRequestRepoUpdateFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientResolveRevisionFunc describes the behavior when the +// ResolveRevision method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientResolveRevisionFunc struct { + defaultHook func(context.Context, api.RepoName, string, gitserver.ResolveRevisionOptions) (api.CommitID, error) + hooks []func(context.Context, api.RepoName, string, gitserver.ResolveRevisionOptions) (api.CommitID, error) + history []GitserverClientResolveRevisionFuncCall + mutex sync.Mutex +} + +// ResolveRevision delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) ResolveRevision(v0 context.Context, v1 api.RepoName, v2 string, v3 gitserver.ResolveRevisionOptions) (api.CommitID, error) { + r0, r1 := m.ResolveRevisionFunc.nextHook()(v0, v1, v2, v3) + m.ResolveRevisionFunc.appendCall(GitserverClientResolveRevisionFuncCall{v0, v1, v2, v3, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the ResolveRevision +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientResolveRevisionFunc) SetDefaultHook(hook func(context.Context, api.RepoName, string, gitserver.ResolveRevisionOptions) (api.CommitID, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ResolveRevision 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 *GitserverClientResolveRevisionFunc) PushHook(hook func(context.Context, api.RepoName, string, gitserver.ResolveRevisionOptions) (api.CommitID, 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 *GitserverClientResolveRevisionFunc) SetDefaultReturn(r0 api.CommitID, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, string, gitserver.ResolveRevisionOptions) (api.CommitID, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientResolveRevisionFunc) PushReturn(r0 api.CommitID, r1 error) { + f.PushHook(func(context.Context, api.RepoName, string, gitserver.ResolveRevisionOptions) (api.CommitID, error) { + return r0, r1 + }) +} + +func (f *GitserverClientResolveRevisionFunc) nextHook() func(context.Context, api.RepoName, string, gitserver.ResolveRevisionOptions) (api.CommitID, 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 *GitserverClientResolveRevisionFunc) appendCall(r0 GitserverClientResolveRevisionFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientResolveRevisionFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientResolveRevisionFunc) History() []GitserverClientResolveRevisionFuncCall { + f.mutex.Lock() + history := make([]GitserverClientResolveRevisionFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientResolveRevisionFuncCall is an object that describes an +// invocation of method ResolveRevision on an instance of +// MockGitserverClient. +type GitserverClientResolveRevisionFuncCall 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 string + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 gitserver.ResolveRevisionOptions + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 api.CommitID + // 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 GitserverClientResolveRevisionFuncCall) 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 GitserverClientResolveRevisionFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientResolveRevisionsFunc describes the behavior when the +// ResolveRevisions method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientResolveRevisionsFunc struct { + defaultHook func(context.Context, api.RepoName, []protocol.RevisionSpecifier) ([]string, error) + hooks []func(context.Context, api.RepoName, []protocol.RevisionSpecifier) ([]string, error) + history []GitserverClientResolveRevisionsFuncCall + mutex sync.Mutex +} + +// ResolveRevisions delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) ResolveRevisions(v0 context.Context, v1 api.RepoName, v2 []protocol.RevisionSpecifier) ([]string, error) { + r0, r1 := m.ResolveRevisionsFunc.nextHook()(v0, v1, v2) + m.ResolveRevisionsFunc.appendCall(GitserverClientResolveRevisionsFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the ResolveRevisions +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientResolveRevisionsFunc) SetDefaultHook(hook func(context.Context, api.RepoName, []protocol.RevisionSpecifier) ([]string, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// ResolveRevisions 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 *GitserverClientResolveRevisionsFunc) PushHook(hook func(context.Context, api.RepoName, []protocol.RevisionSpecifier) ([]string, 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 *GitserverClientResolveRevisionsFunc) SetDefaultReturn(r0 []string, r1 error) { + f.SetDefaultHook(func(context.Context, api.RepoName, []protocol.RevisionSpecifier) ([]string, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientResolveRevisionsFunc) PushReturn(r0 []string, r1 error) { + f.PushHook(func(context.Context, api.RepoName, []protocol.RevisionSpecifier) ([]string, error) { + return r0, r1 + }) +} + +func (f *GitserverClientResolveRevisionsFunc) nextHook() func(context.Context, api.RepoName, []protocol.RevisionSpecifier) ([]string, 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 *GitserverClientResolveRevisionsFunc) appendCall(r0 GitserverClientResolveRevisionsFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientResolveRevisionsFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientResolveRevisionsFunc) History() []GitserverClientResolveRevisionsFuncCall { + f.mutex.Lock() + history := make([]GitserverClientResolveRevisionsFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientResolveRevisionsFuncCall is an object that describes an +// invocation of method ResolveRevisions on an instance of +// MockGitserverClient. +type GitserverClientResolveRevisionsFuncCall 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 []protocol.RevisionSpecifier + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []string + // 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 GitserverClientResolveRevisionsFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientResolveRevisionsFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientRevListFunc describes the behavior when the RevList method +// of the parent MockGitserverClient instance is invoked. +type GitserverClientRevListFunc struct { + defaultHook func(context.Context, string, string, func(commit string) (bool, error)) error + hooks []func(context.Context, string, string, func(commit string) (bool, error)) error + history []GitserverClientRevListFuncCall + mutex sync.Mutex +} + +// RevList delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) RevList(v0 context.Context, v1 string, v2 string, v3 func(commit string) (bool, error)) error { + r0 := m.RevListFunc.nextHook()(v0, v1, v2, v3) + m.RevListFunc.appendCall(GitserverClientRevListFuncCall{v0, v1, v2, v3, r0}) + return r0 +} + +// SetDefaultHook sets function that is called when the RevList method of +// the parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientRevListFunc) SetDefaultHook(hook func(context.Context, string, string, func(commit string) (bool, error)) error) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// RevList 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 *GitserverClientRevListFunc) PushHook(hook func(context.Context, string, string, func(commit string) (bool, error)) 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 *GitserverClientRevListFunc) SetDefaultReturn(r0 error) { + f.SetDefaultHook(func(context.Context, string, string, func(commit string) (bool, error)) error { + return r0 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientRevListFunc) PushReturn(r0 error) { + f.PushHook(func(context.Context, string, string, func(commit string) (bool, error)) error { + return r0 + }) +} + +func (f *GitserverClientRevListFunc) nextHook() func(context.Context, string, string, func(commit string) (bool, error)) 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 *GitserverClientRevListFunc) appendCall(r0 GitserverClientRevListFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientRevListFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientRevListFunc) History() []GitserverClientRevListFuncCall { + f.mutex.Lock() + history := make([]GitserverClientRevListFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientRevListFuncCall is an object that describes an invocation +// of method RevList on an instance of MockGitserverClient. +type GitserverClientRevListFuncCall 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 string + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 string + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 func(commit string) (bool, error) + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c GitserverClientRevListFuncCall) 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 GitserverClientRevListFuncCall) Results() []interface{} { + return []interface{}{c.Result0} +} + +// GitserverClientSearchFunc describes the behavior when the Search method +// of the parent MockGitserverClient instance is invoked. +type GitserverClientSearchFunc struct { + defaultHook func(context.Context, *protocol.SearchRequest, func([]protocol.CommitMatch)) (bool, error) + hooks []func(context.Context, *protocol.SearchRequest, func([]protocol.CommitMatch)) (bool, error) + history []GitserverClientSearchFuncCall + mutex sync.Mutex +} + +// Search delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) Search(v0 context.Context, v1 *protocol.SearchRequest, v2 func([]protocol.CommitMatch)) (bool, error) { + r0, r1 := m.SearchFunc.nextHook()(v0, v1, v2) + m.SearchFunc.appendCall(GitserverClientSearchFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the Search method of the +// parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientSearchFunc) SetDefaultHook(hook func(context.Context, *protocol.SearchRequest, func([]protocol.CommitMatch)) (bool, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// Search 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 *GitserverClientSearchFunc) PushHook(hook func(context.Context, *protocol.SearchRequest, func([]protocol.CommitMatch)) (bool, 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 *GitserverClientSearchFunc) SetDefaultReturn(r0 bool, r1 error) { + f.SetDefaultHook(func(context.Context, *protocol.SearchRequest, func([]protocol.CommitMatch)) (bool, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientSearchFunc) PushReturn(r0 bool, r1 error) { + f.PushHook(func(context.Context, *protocol.SearchRequest, func([]protocol.CommitMatch)) (bool, error) { + return r0, r1 + }) +} + +func (f *GitserverClientSearchFunc) nextHook() func(context.Context, *protocol.SearchRequest, func([]protocol.CommitMatch)) (bool, 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 *GitserverClientSearchFunc) appendCall(r0 GitserverClientSearchFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientSearchFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientSearchFunc) History() []GitserverClientSearchFuncCall { + f.mutex.Lock() + history := make([]GitserverClientSearchFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientSearchFuncCall is an object that describes an invocation +// of method Search on an instance of MockGitserverClient. +type GitserverClientSearchFuncCall 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 *protocol.SearchRequest + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 func([]protocol.CommitMatch) + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 bool + // 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 GitserverClientSearchFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientSearchFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientStatFunc describes the behavior when the Stat method of +// the parent MockGitserverClient instance is invoked. +type GitserverClientStatFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (fs.FileInfo, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (fs.FileInfo, error) + history []GitserverClientStatFuncCall + mutex sync.Mutex +} + +// Stat delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockGitserverClient) Stat(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 api.CommitID, v4 string) (fs.FileInfo, error) { + r0, r1 := m.StatFunc.nextHook()(v0, v1, v2, v3, v4) + m.StatFunc.appendCall(GitserverClientStatFuncCall{v0, v1, v2, v3, v4, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the Stat method of the +// parent MockGitserverClient instance is invoked and the hook queue is +// empty. +func (f *GitserverClientStatFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (fs.FileInfo, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// Stat 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 *GitserverClientStatFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (fs.FileInfo, 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 *GitserverClientStatFunc) SetDefaultReturn(r0 fs.FileInfo, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (fs.FileInfo, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientStatFunc) PushReturn(r0 fs.FileInfo, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (fs.FileInfo, error) { + return r0, r1 + }) +} + +func (f *GitserverClientStatFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string) (fs.FileInfo, 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 *GitserverClientStatFunc) appendCall(r0 GitserverClientStatFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientStatFuncCall objects +// describing the invocations of this function. +func (f *GitserverClientStatFunc) History() []GitserverClientStatFuncCall { + f.mutex.Lock() + history := make([]GitserverClientStatFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientStatFuncCall is an object that describes an invocation of +// method Stat on an instance of MockGitserverClient. +type GitserverClientStatFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 api.CommitID + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 fs.FileInfo + // 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 GitserverClientStatFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientStatFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// GitserverClientStreamBlameFileFunc describes the behavior when the +// StreamBlameFile method of the parent MockGitserverClient instance is +// invoked. +type GitserverClientStreamBlameFileFunc struct { + defaultHook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) (gitserver.HunkReader, error) + hooks []func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) (gitserver.HunkReader, error) + history []GitserverClientStreamBlameFileFuncCall + mutex sync.Mutex +} + +// StreamBlameFile delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockGitserverClient) StreamBlameFile(v0 context.Context, v1 authz.SubRepoPermissionChecker, v2 api.RepoName, v3 string, v4 *gitserver.BlameOptions) (gitserver.HunkReader, error) { + r0, r1 := m.StreamBlameFileFunc.nextHook()(v0, v1, v2, v3, v4) + m.StreamBlameFileFunc.appendCall(GitserverClientStreamBlameFileFuncCall{v0, v1, v2, v3, v4, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the StreamBlameFile +// method of the parent MockGitserverClient instance is invoked and the hook +// queue is empty. +func (f *GitserverClientStreamBlameFileFunc) SetDefaultHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) (gitserver.HunkReader, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// StreamBlameFile 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 *GitserverClientStreamBlameFileFunc) PushHook(hook func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) (gitserver.HunkReader, 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 *GitserverClientStreamBlameFileFunc) SetDefaultReturn(r0 gitserver.HunkReader, r1 error) { + f.SetDefaultHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) (gitserver.HunkReader, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *GitserverClientStreamBlameFileFunc) PushReturn(r0 gitserver.HunkReader, r1 error) { + f.PushHook(func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) (gitserver.HunkReader, error) { + return r0, r1 + }) +} + +func (f *GitserverClientStreamBlameFileFunc) nextHook() func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, string, *gitserver.BlameOptions) (gitserver.HunkReader, 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 *GitserverClientStreamBlameFileFunc) appendCall(r0 GitserverClientStreamBlameFileFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of GitserverClientStreamBlameFileFuncCall +// objects describing the invocations of this function. +func (f *GitserverClientStreamBlameFileFunc) History() []GitserverClientStreamBlameFileFuncCall { + f.mutex.Lock() + history := make([]GitserverClientStreamBlameFileFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// GitserverClientStreamBlameFileFuncCall is an object that describes an +// invocation of method StreamBlameFile on an instance of +// MockGitserverClient. +type GitserverClientStreamBlameFileFuncCall 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 authz.SubRepoPermissionChecker + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 api.RepoName + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 string + // Arg4 is the value of the 5th argument passed to this method + // invocation. + Arg4 *gitserver.BlameOptions + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 gitserver.HunkReader + // 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 GitserverClientStreamBlameFileFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c GitserverClientStreamBlameFileFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} diff --git a/enterprise/internal/batches/sources/perforce.go b/enterprise/internal/batches/sources/perforce.go new file mode 100644 index 00000000000..49440ca2aaa --- /dev/null +++ b/enterprise/internal/batches/sources/perforce.go @@ -0,0 +1,178 @@ +package sources + +import ( + "context" + "fmt" + "net/url" + + btypes "github.com/sourcegraph/sourcegraph/enterprise/internal/batches/types" + "github.com/sourcegraph/sourcegraph/internal/extsvc/auth" + "github.com/sourcegraph/sourcegraph/internal/gitserver" + "github.com/sourcegraph/sourcegraph/internal/gitserver/protocol" + "github.com/sourcegraph/sourcegraph/internal/httpcli" + "github.com/sourcegraph/sourcegraph/internal/jsonc" + "github.com/sourcegraph/sourcegraph/internal/types" + "github.com/sourcegraph/sourcegraph/lib/errors" + "github.com/sourcegraph/sourcegraph/schema" +) + +type PerforceSource struct { + server schema.PerforceConnection + gitServerClient gitserver.Client + perforceCreds *gitserver.PerforceCredentials +} + +func NewPerforceSource(ctx context.Context, svc *types.ExternalService, _ *httpcli.Factory) (*PerforceSource, error) { + rawConfig, err := svc.Config.Decrypt(ctx) + if err != nil { + return nil, errors.Errorf("external service id=%d config error: %s", svc.ID, err) + } + var c schema.PerforceConnection + if err := jsonc.Unmarshal(rawConfig, &c); err != nil { + return nil, errors.Wrapf(err, "external service id=%d", svc.ID) + } + + return &PerforceSource{server: c, gitServerClient: gitserver.NewClient()}, nil +} + +// GitserverPushConfig returns an authenticated push config used for pushing commits to the code host. +func (s PerforceSource) GitserverPushConfig(repo *types.Repo) (*protocol.PushConfig, error) { + // Return a PushConfig with a crafted URL that includes the Perforce scheme and the credentials + // The perforce scheme will tell `createCommitFromPatch` that this repo is a Perforce repo + // so it can handle it differently from Git repos. + // TODO: @peterguy: this seems to be the correct way to include the depot; confirm with more examples from code host configurations + depot := "" + u, err := url.Parse(repo.URI) + if err == nil { + depot = "//" + u.Path + "/" + } + remoteURL := fmt.Sprintf("perforce://%s:%s@%s%s", s.perforceCreds.Username, s.perforceCreds.Password, s.server.P4Port, depot) + return &protocol.PushConfig{ + RemoteURL: remoteURL, + }, nil +} + +// WithAuthenticator returns a copy of the original Source configured to use the +// given authenticator, provided that authenticator type is supported by the +// code host. +func (s PerforceSource) WithAuthenticator(a auth.Authenticator) (ChangesetSource, error) { + switch av := a.(type) { + case *auth.BasicAuthWithSSH: + s.perforceCreds = &gitserver.PerforceCredentials{ + Username: av.Username, + Password: av.Password, + Host: s.server.P4Port, + } + case *auth.BasicAuth: + s.perforceCreds = &gitserver.PerforceCredentials{ + Username: av.Username, + Password: av.Password, + Host: s.server.P4Port, + } + default: + return s, errors.New("unexpected auther type for Perforce Source") + } + + return s, nil +} + +// ValidateAuthenticator validates the currently set authenticator is usable. +// Returns an error, when validating the Authenticator yielded an error. +func (s PerforceSource) ValidateAuthenticator(ctx context.Context) error { + if s.perforceCreds == nil { + return errors.New("no credentials set for Perforce Source") + } + rc, _, err := s.gitServerClient.P4Exec(ctx, s.perforceCreds.Host, s.perforceCreds.Username, s.perforceCreds.Password, "users") + if err == nil { + _ = rc.Close() + return nil + } + return err +} + +// LoadChangeset loads the given Changeset from the source and updates it. If +// the Changeset could not be found on the source, a ChangesetNotFoundError is +// returned. +func (s PerforceSource) LoadChangeset(ctx context.Context, cs *Changeset) error { + if s.perforceCreds == nil { + return errors.New("no credentials set for Perforce Source") + } + cl, err := s.gitServerClient.P4GetChangelist(ctx, cs.ExternalID, *s.perforceCreds) + if err != nil { + return errors.Wrap(err, "getting changelist") + } + return errors.Wrap(s.setChangesetMetadata(cl, cs), "setting perforce changeset metadata") +} + +// CreateChangeset will create the Changeset on the source. If it already +// exists, *Changeset will be populated and the return value will be true. +func (s PerforceSource) CreateChangeset(ctx context.Context, cs *Changeset) (bool, error) { + return false, s.LoadChangeset(ctx, cs) +} + +// CreateDraftChangeset creates the given changeset on the code host in draft mode. +// Perforce does not support draft changelists +func (s PerforceSource) CreateDraftChangeset(_ context.Context, _ *Changeset) (bool, error) { + return false, errors.New("not implemented") +} + +func (s PerforceSource) setChangesetMetadata(cl *protocol.PerforceChangelist, cs *Changeset) error { + if err := cs.SetMetadata(cl); err != nil { + return errors.Wrap(err, "setting changeset metadata") + } + + return nil +} + +// UndraftChangeset will update the Changeset on the source to be not in draft mode anymore. +func (s PerforceSource) UndraftChangeset(_ context.Context, _ *Changeset) error { + // TODO: @peterguy implement this function? + // not sure what it means in Perforce - submit the changelist? + return errors.New("not implemented") +} + +// CloseChangeset will close the Changeset on the source, where "close" +// means the appropriate final state on the codehost. +// deleted on Perforce, maybe? +func (s PerforceSource) CloseChangeset(_ context.Context, _ *Changeset) error { + // TODO: @peterguy implement this function + // delete changelist? + return errors.New("not implemented") +} + +// UpdateChangeset can update Changesets. +func (s PerforceSource) UpdateChangeset(_ context.Context, _ *Changeset) error { + // TODO: @peterguy implement this function + // not sure what this means for Perforce + return errors.New("not implemented") +} + +// ReopenChangeset will reopen the Changeset on the source, if it's closed. +// If not, it's a noop. +func (s PerforceSource) ReopenChangeset(_ context.Context, _ *Changeset) error { + // TODO: @peterguy implement function + // noop for Perforce? + return errors.New("not implemented") +} + +// CreateComment posts a comment on the Changeset. +func (s PerforceSource) CreateComment(_ context.Context, _ *Changeset, _ string) error { + // TODO: @peterguy implement function + // comment on changelist? + return errors.New("not implemented") +} + +// MergeChangeset merges a Changeset on the code host, if in a mergeable state. +// If squash is true, and the code host supports squash merges, the source +// must attempt a squash merge. Otherwise, it is expected to perform a regular +// merge. If the changeset cannot be merged, because it is in an unmergeable +// state, ChangesetNotMergeableError must be returned. +func (s PerforceSource) MergeChangeset(_ context.Context, _ *Changeset, _ bool) error { + // TODO: @peterguy implement function + // submit CL? Or no-op because we want to keep CLs pending and let the Perforce users manage them in other tools? + return errors.New("not implemented") +} + +func (s PerforceSource) BuildCommitOpts(repo *types.Repo, _ *btypes.Changeset, spec *btypes.ChangesetSpec, pushOpts *protocol.PushConfig) protocol.CreateCommitFromPatchRequest { + return BuildCommitOptsCommon(repo, spec, pushOpts) +} diff --git a/enterprise/internal/batches/sources/perforce_test.go b/enterprise/internal/batches/sources/perforce_test.go new file mode 100644 index 00000000000..29f94074df9 --- /dev/null +++ b/enterprise/internal/batches/sources/perforce_test.go @@ -0,0 +1,149 @@ +package sources + +import ( + "context" + "io" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/sourcegraph/sourcegraph/internal/gitserver" + "github.com/sourcegraph/sourcegraph/internal/gitserver/protocol" + "github.com/sourcegraph/sourcegraph/schema" + + btypes "github.com/sourcegraph/sourcegraph/enterprise/internal/batches/types" + "github.com/sourcegraph/sourcegraph/internal/types" + "github.com/sourcegraph/sourcegraph/lib/errors" +) + +var ( + testPerforceProjectName = "testdepot" + testPerforceChangeID = "111" + testPerforceCredentials = gitserver.PerforceCredentials{Username: "user", Password: "pass", Host: "https://perforce.sgdev.org:1666"} +) + +func TestPerforceSource_ValidateAuthenticator(t *testing.T) { + ctx := context.Background() + + for name, want := range map[string]error{ + "nil": nil, + "error": errors.New("error"), + } { + t.Run(name, func(t *testing.T) { + s, client := mockPerforceSource() + client.P4ExecFunc.SetDefaultReturn(fakeCloser{}, http.Header{}, want) + assert.Equal(t, want, s.ValidateAuthenticator(ctx)) + }) + } +} + +func TestPerforceSource_LoadChangeset(t *testing.T) { + ctx := context.Background() + + t.Run("error getting changelist", func(t *testing.T) { + cs, _ := mockPerforceChangeset() + s, client := mockPerforceSource() + want := errors.New("error") + client.P4GetChangelistFunc.SetDefaultHook(func(ctx context.Context, changeID string, credentials gitserver.PerforceCredentials) (*protocol.PerforceChangelist, error) { + assert.Equal(t, changeID, testPerforceChangeID) + assert.Equal(t, testPerforceCredentials, credentials) + return new(protocol.PerforceChangelist), want + }) + + err := s.LoadChangeset(ctx, cs) + assert.NotNil(t, err) + assert.ErrorIs(t, err, want) + }) + + t.Run("success", func(t *testing.T) { + cs, _ := mockPerforceChangeset() + s, client := mockPerforceSource() + + change := mockPerforceChange() + client.P4GetChangelistFunc.SetDefaultHook(func(ctx context.Context, changeID string, credentials gitserver.PerforceCredentials) (*protocol.PerforceChangelist, error) { + assert.Equal(t, changeID, testPerforceChangeID) + assert.Equal(t, testPerforceCredentials, credentials) + return change, nil + }) + + err := s.LoadChangeset(ctx, cs) + assert.Nil(t, err) + }) +} + +func TestPerforceSource_CreateChangeset(t *testing.T) { + ctx := context.Background() + + t.Run("error getting pull request", func(t *testing.T) { + cs, _ := mockPerforceChangeset() + s, client := mockPerforceSource() + want := errors.New("error") + client.P4GetChangelistFunc.SetDefaultHook(func(ctx context.Context, changeID string, credentials gitserver.PerforceCredentials) (*protocol.PerforceChangelist, error) { + assert.Equal(t, changeID, testPerforceChangeID) + assert.Equal(t, testPerforceCredentials, credentials) + return new(protocol.PerforceChangelist), want + }) + + b, err := s.CreateChangeset(ctx, cs) + assert.NotNil(t, err) + assert.ErrorIs(t, err, want) + assert.False(t, b) + }) + + t.Run("success", func(t *testing.T) { + cs, _ := mockPerforceChangeset() + s, client := mockPerforceSource() + + change := mockPerforceChange() + client.P4GetChangelistFunc.SetDefaultHook(func(ctx context.Context, changeID string, credentials gitserver.PerforceCredentials) (*protocol.PerforceChangelist, error) { + assert.Equal(t, changeID, testPerforceChangeID) + assert.Equal(t, testPerforceCredentials, credentials) + return change, nil + }) + + b, err := s.CreateChangeset(ctx, cs) + assert.Nil(t, err) + assert.False(t, b) + }) +} + +// mockPerforceChangeset creates a plausible non-forked changeset, repo, +// and Perforce specific repo. +func mockPerforceChangeset() (*Changeset, *types.Repo) { + repo := &types.Repo{Metadata: &testProject} + cs := &Changeset{ + Title: "title", + Body: "description", + Changeset: &btypes.Changeset{}, + RemoteRepo: repo, + TargetRepo: repo, + BaseRef: "refs/heads/targetbranch", + } + + cs.Changeset.ExternalID = testPerforceChangeID + + return cs, repo +} + +// mockPerforceChange returns a plausible changelist that would be +// returned from Perforce. +func mockPerforceChange() *protocol.PerforceChangelist { + return &protocol.PerforceChangelist{ + ID: testPerforceChangeID, + Author: "Peter Guy", + State: protocol.PerforceChangelistStatePending, + } +} + +func mockPerforceSource() (*PerforceSource, *MockGitserverClient) { + client := NewStrictMockGitserverClient() + s := &PerforceSource{gitServerClient: client, perforceCreds: &testPerforceCredentials, server: schema.PerforceConnection{P4Port: "https://perforce.sgdev.org:1666"}} + return s, client +} + +type fakeCloser struct { + io.Reader +} + +func (fakeCloser) Close() error { return nil } diff --git a/enterprise/internal/batches/sources/sources.go b/enterprise/internal/batches/sources/sources.go index e1fa3e97a2e..2b331f7aa17 100644 --- a/enterprise/internal/batches/sources/sources.go +++ b/enterprise/internal/batches/sources/sources.go @@ -420,7 +420,8 @@ func loadExternalService(ctx context.Context, s database.ExternalServiceStore, o *schema.GitLabConnection, *schema.BitbucketCloudConnection, *schema.AzureDevOpsConnection, - *schema.GerritConnection: + *schema.GerritConnection, + *schema.PerforceConnection: return e, nil } } @@ -444,6 +445,8 @@ func buildChangesetSource(ctx context.Context, cf *httpcli.Factory, externalServ return NewAzureDevOpsSource(ctx, externalService, cf) case extsvc.KindGerrit: return NewGerritSource(ctx, externalService, cf) + case extsvc.KindPerforce: + return NewPerforceSource(ctx, externalService, cf) default: return nil, errors.Errorf("unsupported external service type %q", extsvc.KindToType(externalService.Kind)) } diff --git a/enterprise/internal/batches/state/BUILD.bazel b/enterprise/internal/batches/state/BUILD.bazel index b8db1c81184..2487cb1421c 100644 --- a/enterprise/internal/batches/state/BUILD.bazel +++ b/enterprise/internal/batches/state/BUILD.bazel @@ -28,6 +28,7 @@ go_library( "//internal/extsvc/github", "//internal/extsvc/gitlab", "//internal/gitserver", + "//internal/gitserver/protocol", "//internal/types", "//lib/errors", "@com_github_inconshreveable_log15//:log15", diff --git a/enterprise/internal/batches/state/state.go b/enterprise/internal/batches/state/state.go index 3c4387a22b8..7ce7a6d8227 100644 --- a/enterprise/internal/batches/state/state.go +++ b/enterprise/internal/batches/state/state.go @@ -12,6 +12,7 @@ import ( gerritbatches "github.com/sourcegraph/sourcegraph/enterprise/internal/batches/sources/gerrit" adobatches "github.com/sourcegraph/sourcegraph/internal/extsvc/azuredevops" "github.com/sourcegraph/sourcegraph/internal/extsvc/gerrit" + "github.com/sourcegraph/sourcegraph/internal/gitserver/protocol" "github.com/sourcegraph/go-diff/diff" @@ -120,8 +121,8 @@ func computeCheckState(c *btypes.Changeset, events ChangesetEvents) btypes.Chang return computeBitbucketCloudBuildState(c.UpdatedAt, m, events) case *azuredevops.AnnotatedPullRequest: return computeAzureDevOpsBuildState(m) - case gerritbatches.AnnotatedChange: - // Gerrit doesn't have builds built-in, I think its better to be explicit by still + case *gerritbatches.AnnotatedChange, *protocol.PerforceChangelistState: + // Gerrit and Perforce don't have builds built-in, its better to be explicit by still // including this case for clarity. return btypes.ChangesetCheckStateUnknown } @@ -585,6 +586,17 @@ func computeSingleChangesetExternalState(c *btypes.Changeset) (s btypes.Changese default: return "", errors.Errorf("unknown Gerrit Change state: %s", m.Change.Status) } + case *protocol.PerforceChangelist: + switch m.State { + case protocol.PerforceChangelistStateClosed: + s = btypes.ChangesetExternalStateClosed + case protocol.PerforceChangelistStateSubmitted: + s = btypes.ChangesetExternalStateMerged + case protocol.PerforceChangelistStatePending, protocol.PerforceChangelistStateShelved: + s = btypes.ChangesetExternalStateOpen + default: + return "", errors.Errorf("unknown Gerrit Change state: %s", m.State) + } default: return "", errors.New("unknown changeset type") } @@ -695,7 +707,8 @@ func computeSingleChangesetReviewState(c *btypes.Changeset) (s btypes.ChangesetR states[btypes.ChangesetReviewStatePending] = true } } - + case *protocol.PerforceChangelist: + states[btypes.ChangesetReviewStatePending] = true default: return "", errors.New("unknown changeset type") } diff --git a/enterprise/internal/batches/store/BUILD.bazel b/enterprise/internal/batches/store/BUILD.bazel index 197ef8296c2..7ca88b9183f 100644 --- a/enterprise/internal/batches/store/BUILD.bazel +++ b/enterprise/internal/batches/store/BUILD.bazel @@ -53,6 +53,7 @@ go_library( "//internal/extsvc/github", "//internal/extsvc/gitlab", "//internal/featureflag", + "//internal/gitserver/protocol", "//internal/metrics", "//internal/observation", "//internal/timeutil", diff --git a/enterprise/internal/batches/store/changesets.go b/enterprise/internal/batches/store/changesets.go index 719b47a70f0..2127163bb5c 100644 --- a/enterprise/internal/batches/store/changesets.go +++ b/enterprise/internal/batches/store/changesets.go @@ -16,6 +16,7 @@ import ( gerritbatches "github.com/sourcegraph/sourcegraph/enterprise/internal/batches/sources/gerrit" "github.com/sourcegraph/sourcegraph/internal/extsvc/azuredevops" "github.com/sourcegraph/sourcegraph/internal/extsvc/gerrit" + "github.com/sourcegraph/sourcegraph/internal/gitserver/protocol" "github.com/keegancsmith/sqlf" "github.com/lib/pq" @@ -1525,6 +1526,10 @@ func ScanChangeset(t *btypes.Changeset, s dbutil.Scanner) error { m := new(gerritbatches.AnnotatedChange) m.Change = &gerrit.Change{} t.Metadata = m + case extsvc.TypePerforce: + t.Metadata = new(protocol.PerforceChangelist) + case extsvc.TypeGerrit: + t.Metadata = new(gerrit.Change) default: return errors.New("unknown external service type") } diff --git a/enterprise/internal/batches/store/codehost.go b/enterprise/internal/batches/store/codehost.go index ff5fd3cfeba..238313107a4 100644 --- a/enterprise/internal/batches/store/codehost.go +++ b/enterprise/internal/batches/store/codehost.go @@ -116,7 +116,7 @@ func listCodeHostsQuery(opts ListCodeHostsOpts) *sqlf.Query { // Only show supported hosts. supportedTypes := []*sqlf.Query{} - for extSvcType := range btypes.SupportedExternalServices { + for extSvcType := range btypes.GetSupportedExternalServices() { supportedTypes = append(supportedTypes, sqlf.Sprintf("%s", extSvcType)) } repoPreds = append(repoPreds, sqlf.Sprintf("repo.external_service_type IN (%s)", sqlf.Join(supportedTypes, ", "))) diff --git a/enterprise/internal/batches/types/BUILD.bazel b/enterprise/internal/batches/types/BUILD.bazel index 559fcad80fc..5beb277ec0f 100644 --- a/enterprise/internal/batches/types/BUILD.bazel +++ b/enterprise/internal/batches/types/BUILD.bazel @@ -45,6 +45,7 @@ go_library( "//internal/extsvc/gitlab", "//internal/extsvc/gitlab/webhooks", "//internal/gitserver/gitdomain", + "//internal/gitserver/protocol", "//internal/timeutil", "//internal/types", "//lib/batches", diff --git a/enterprise/internal/batches/types/changeset.go b/enterprise/internal/batches/types/changeset.go index 319a704f18e..da46dc9481b 100644 --- a/enterprise/internal/batches/types/changeset.go +++ b/enterprise/internal/batches/types/changeset.go @@ -10,13 +10,15 @@ import ( "github.com/goware/urlx" "github.com/inconshreveable/log15" "github.com/sourcegraph/go-diff/diff" + "github.com/sourcegraph/sourcegraph/internal/gitserver/protocol" + + gerritbatches "github.com/sourcegraph/sourcegraph/enterprise/internal/batches/sources/gerrit" + "github.com/sourcegraph/sourcegraph/internal/extsvc/azuredevops" adobatches "github.com/sourcegraph/sourcegraph/enterprise/internal/batches/sources/azuredevops" bbcs "github.com/sourcegraph/sourcegraph/enterprise/internal/batches/sources/bitbucketcloud" - gerritbatches "github.com/sourcegraph/sourcegraph/enterprise/internal/batches/sources/gerrit" "github.com/sourcegraph/sourcegraph/internal/api" "github.com/sourcegraph/sourcegraph/internal/extsvc" - "github.com/sourcegraph/sourcegraph/internal/extsvc/azuredevops" "github.com/sourcegraph/sourcegraph/internal/extsvc/bitbucketcloud" "github.com/sourcegraph/sourcegraph/internal/extsvc/bitbucketserver" "github.com/sourcegraph/sourcegraph/internal/extsvc/gerrit" @@ -467,6 +469,12 @@ func (c *Changeset) SetMetadata(meta any) error { c.ExternalServiceType = extsvc.TypeGerrit c.ExternalBranch = gitdomain.EnsureRefPrefix(pr.Change.Branch) c.ExternalUpdatedAt = pr.Change.Updated + case *protocol.PerforceChangelist: + c.Metadata = pr + c.ExternalID = pr.ID + c.ExternalServiceType = extsvc.TypePerforce + // Perforce does not have a last updated at field on its CL objects, so we set the creation time. + c.ExternalUpdatedAt = pr.CreationDate default: return errors.New("setmetadata unknown changeset type") } @@ -501,6 +509,8 @@ func (c *Changeset) Title() (string, error) { // Remove extra quotes added by the commit message title = strings.TrimPrefix(strings.TrimSuffix(title, "\""), "\"") return title, nil + case *protocol.PerforceChangelist: + return m.Title, nil default: return "", errors.New("title unknown changeset type") } @@ -526,6 +536,8 @@ func (c *Changeset) AuthorName() (string, error) { return m.CreatedBy.UniqueName, nil case *gerritbatches.AnnotatedChange: return m.Change.Owner.Name, nil + case *protocol.PerforceChangelist: + return m.Author, nil default: return "", errors.New("authorname unknown changeset type") } @@ -559,6 +571,8 @@ func (c *Changeset) AuthorEmail() (string, error) { return m.CreatedBy.UniqueName, nil case *gerritbatches.AnnotatedChange: return m.Change.Owner.Email, nil + case *protocol.PerforceChangelist: + return "", nil default: return "", errors.New("author email unknown changeset type") } @@ -581,6 +595,8 @@ func (c *Changeset) ExternalCreatedAt() time.Time { return m.CreationDate case *gerritbatches.AnnotatedChange: return m.Change.Created + case *protocol.PerforceChangelist: + return m.CreationDate default: return time.Time{} } @@ -602,6 +618,8 @@ func (c *Changeset) Body() (string, error) { case *gerritbatches.AnnotatedChange: // Gerrit doesn't really differentiate between title/description. return m.Change.Subject, nil + case *protocol.PerforceChangelist: + return "", nil default: return "", errors.New("body unknown changeset type") } @@ -668,6 +686,8 @@ func (c *Changeset) URL() (s string, err error) { return returnURL.String(), nil case *gerritbatches.AnnotatedChange: return m.CodeHostURL.JoinPath("c", url.PathEscape(m.Change.Project), "+", url.PathEscape(strconv.Itoa(m.Change.ChangeNumber))).String(), nil + case *protocol.PerforceChangelist: + return "", nil default: return "", errors.New("url unknown changeset type") } @@ -886,6 +906,9 @@ func (c *Changeset) Events() (events []*ChangesetEvent, err error) { Metadata: reviewer, }) } + case *protocol.PerforceChangelist: + // We don't have any events we care about right now + break } return events, nil @@ -908,6 +931,8 @@ func (c *Changeset) HeadRefOid() (string, error) { return "", nil case *gerritbatches.AnnotatedChange: return "", nil + case *protocol.PerforceChangelist: + return "", nil default: return "", errors.New("head ref oid unknown changeset type") } @@ -929,6 +954,8 @@ func (c *Changeset) HeadRef() (string, error) { return m.SourceRefName, nil case *gerritbatches.AnnotatedChange: return "", nil + case *protocol.PerforceChangelist: + return "", nil default: return "", errors.New("headref unknown changeset type") } @@ -951,6 +978,8 @@ func (c *Changeset) BaseRefOid() (string, error) { return "", nil case *gerritbatches.AnnotatedChange: return "", nil + case *protocol.PerforceChangelist: + return "", nil default: return "", errors.New("base ref oid unknown changeset type") } @@ -972,6 +1001,9 @@ func (c *Changeset) BaseRef() (string, error) { return m.TargetRefName, nil case *gerritbatches.AnnotatedChange: return "refs/heads/" + m.Change.Branch, nil + case *protocol.PerforceChangelist: + // TODO: @peterguy we may need to change this to something. + return "", nil default: return "", errors.New(" base ref unknown changeset type") } diff --git a/enterprise/internal/batches/types/changeset_event.go b/enterprise/internal/batches/types/changeset_event.go index 3e38ffa3689..9ee924a7ce3 100644 --- a/enterprise/internal/batches/types/changeset_event.go +++ b/enterprise/internal/batches/types/changeset_event.go @@ -147,21 +147,19 @@ func (e *ChangesetEvent) Clone() *ChangesetEvent { // Returns an empty string if not a review event or the author has been deleted. func (e *ChangesetEvent) ReviewAuthor() string { switch meta := e.Metadata.(type) { + case *github.PullRequestReview: return meta.Author.Login - case *github.ReviewDismissedEvent: return meta.Review.Author.Login case *bitbucketserver.Activity: return meta.User.Name - case *bitbucketserver.ParticipantStatusEvent: return meta.User.Name case *gitlab.ReviewApprovedEvent: return meta.Author.Username - case *gitlab.ReviewUnapprovedEvent: return meta.Author.Username @@ -170,18 +168,15 @@ func (e *ChangesetEvent) ReviewAuthor() string { // for each author and isn't surfaced in the UI, we can use the UUID. case *bitbucketcloud.Participant: return meta.User.UUID - case *bitbucketcloud.PullRequestApprovedEvent: return meta.Approval.User.UUID - case *bitbucketcloud.PullRequestUnapprovedEvent: return meta.Approval.User.UUID - case *bitbucketcloud.PullRequestChangesRequestCreatedEvent: return meta.ChangesRequest.User.UUID - case *bitbucketcloud.PullRequestChangesRequestRemovedEvent: return meta.ChangesRequest.User.UUID + case *azuredevops.PullRequestApprovedEvent: if len(meta.PullRequest.Reviewers) == 0 { return meta.PullRequest.CreatedBy.UniqueName @@ -857,55 +852,42 @@ func (e *ChangesetEvent) Update(o *ChangesetEvent) error { case *bitbucketcloud.Participant: o := o.Metadata.(*bitbucketcloud.Participant) *e = *o - case *bitbucketcloud.PullRequestStatus: o := o.Metadata.(*bitbucketcloud.PullRequestStatus) *e = *o - case *bitbucketcloud.PullRequestApprovedEvent: o := o.Metadata.(*bitbucketcloud.PullRequestApprovedEvent) *e = *o - case *bitbucketcloud.PullRequestChangesRequestCreatedEvent: o := o.Metadata.(*bitbucketcloud.PullRequestChangesRequestCreatedEvent) *e = *o - case *bitbucketcloud.PullRequestChangesRequestRemovedEvent: o := o.Metadata.(*bitbucketcloud.PullRequestChangesRequestRemovedEvent) *e = *o - case *bitbucketcloud.PullRequestCommentCreatedEvent: o := o.Metadata.(*bitbucketcloud.PullRequestCommentCreatedEvent) *e = *o - case *bitbucketcloud.PullRequestCommentDeletedEvent: o := o.Metadata.(*bitbucketcloud.PullRequestCommentDeletedEvent) *e = *o - case *bitbucketcloud.PullRequestCommentUpdatedEvent: o := o.Metadata.(*bitbucketcloud.PullRequestCommentUpdatedEvent) *e = *o - case *bitbucketcloud.PullRequestFulfilledEvent: o := o.Metadata.(*bitbucketcloud.PullRequestFulfilledEvent) *e = *o - case *bitbucketcloud.PullRequestRejectedEvent: o := o.Metadata.(*bitbucketcloud.PullRequestRejectedEvent) *e = *o - case *bitbucketcloud.PullRequestUnapprovedEvent: o := o.Metadata.(*bitbucketcloud.PullRequestUnapprovedEvent) *e = *o - case *bitbucketcloud.PullRequestUpdatedEvent: o := o.Metadata.(*bitbucketcloud.PullRequestUpdatedEvent) *e = *o - case *bitbucketcloud.RepoCommitStatusCreatedEvent: o := o.Metadata.(*bitbucketcloud.RepoCommitStatusCreatedEvent) *e = *o - case *bitbucketcloud.RepoCommitStatusUpdatedEvent: o := o.Metadata.(*bitbucketcloud.RepoCommitStatusUpdatedEvent) *e = *o @@ -913,27 +895,21 @@ func (e *ChangesetEvent) Update(o *ChangesetEvent) error { case *azuredevops.PullRequestUpdatedEvent: o := o.Metadata.(*azuredevops.PullRequestUpdatedEvent) *e = *o - case *azuredevops.PullRequestMergedEvent: o := o.Metadata.(*azuredevops.PullRequestMergedEvent) *e = *o - case *azuredevops.PullRequestApprovedEvent: o := o.Metadata.(*azuredevops.PullRequestApprovedEvent) *e = *o - case *azuredevops.PullRequestApprovedWithSuggestionsEvent: o := o.Metadata.(*azuredevops.PullRequestApprovedWithSuggestionsEvent) *e = *o - case *azuredevops.PullRequestWaitingForAuthorEvent: o := o.Metadata.(*azuredevops.PullRequestWaitingForAuthorEvent) *e = *o - case *azuredevops.PullRequestRejectedEvent: o := o.Metadata.(*azuredevops.PullRequestRejectedEvent) *e = *o - default: return errors.Errorf("unknown changeset event metadata %T", e) } diff --git a/enterprise/internal/batches/types/util.go b/enterprise/internal/batches/types/util.go index 9195467c953..d8590ae5909 100644 --- a/enterprise/internal/batches/types/util.go +++ b/enterprise/internal/batches/types/util.go @@ -4,6 +4,7 @@ import ( "time" "github.com/sourcegraph/sourcegraph/internal/api" + "github.com/sourcegraph/sourcegraph/internal/conf" "github.com/sourcegraph/sourcegraph/internal/extsvc" ) @@ -16,35 +17,42 @@ const ( type CodehostCapabilities map[CodehostCapability]bool -// SupportedExternalServices are the external service types currently supported +// GetSupportedExternalServices returns the external service types currently supported // by the batch changes feature. Repos that are associated with external services // whose type is not in this list will simply be filtered out from the search // results. -var SupportedExternalServices = map[string]CodehostCapabilities{ - extsvc.TypeGitHub: {CodehostCapabilityLabels: true, CodehostCapabilityDraftChangesets: true}, - extsvc.TypeBitbucketServer: {}, - extsvc.TypeGitLab: {CodehostCapabilityLabels: true, CodehostCapabilityDraftChangesets: true}, - extsvc.TypeBitbucketCloud: {}, - extsvc.TypeAzureDevOps: {CodehostCapabilityDraftChangesets: true}, - extsvc.TypeGerrit: {CodehostCapabilityDraftChangesets: true}, +func GetSupportedExternalServices() map[string]CodehostCapabilities { + supportedExternalServices := map[string]CodehostCapabilities{ + extsvc.TypeGitHub: {CodehostCapabilityLabels: true, CodehostCapabilityDraftChangesets: true}, + extsvc.TypeBitbucketServer: {}, + extsvc.TypeGitLab: {CodehostCapabilityLabels: true, CodehostCapabilityDraftChangesets: true}, + extsvc.TypeBitbucketCloud: {}, + extsvc.TypeAzureDevOps: {CodehostCapabilityDraftChangesets: true}, + extsvc.TypeGerrit: {CodehostCapabilityDraftChangesets: true}, + } + if conf.Get().ExperimentalFeatures != nil && conf.Get().ExperimentalFeatures.BatchChangesEnablePerforce { + supportedExternalServices[extsvc.TypePerforce] = CodehostCapabilities{} + } + + return supportedExternalServices } // IsRepoSupported returns whether the given ExternalRepoSpec is supported by // the batch changes feature, based on the external service type. func IsRepoSupported(spec *api.ExternalRepoSpec) bool { - _, ok := SupportedExternalServices[spec.ServiceType] + _, ok := GetSupportedExternalServices()[spec.ServiceType] return ok } // IsKindSupported returns whether the given extsvc Kind is supported by // batch changes. func IsKindSupported(extSvcKind string) bool { - _, ok := SupportedExternalServices[extsvc.KindToType(extSvcKind)] + _, ok := GetSupportedExternalServices()[extsvc.KindToType(extSvcKind)] return ok } func ExternalServiceSupports(extSvcType string, capability CodehostCapability) bool { - if es, ok := SupportedExternalServices[extSvcType]; ok { + if es, ok := GetSupportedExternalServices()[extSvcType]; ok { val, ok := es[capability] return ok && val } diff --git a/go.mod b/go.mod index 74f11abe34d..65667b87803 100644 --- a/go.mod +++ b/go.mod @@ -242,10 +242,10 @@ require ( golang.org/x/crypto v0.7.0 golang.org/x/net v0.10.0 golang.org/x/oauth2 v0.8.0 - golang.org/x/sync v0.1.0 + golang.org/x/sync v0.2.0 golang.org/x/sys v0.8.0 golang.org/x/time v0.3.0 - golang.org/x/tools v0.6.0 + golang.org/x/tools v0.9.3 gonum.org/v1/gonum v0.12.0 google.golang.org/api v0.110.0 google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc @@ -307,6 +307,8 @@ require ( github.com/moby/sys/mountinfo v0.6.2 // indirect github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/onsi/ginkgo/v2 v2.9.7 // indirect + github.com/onsi/gomega v1.27.8 // indirect github.com/pjbgf/sha1cd v0.2.3 // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/prometheus/prometheus v0.40.5 // indirect @@ -375,7 +377,7 @@ require ( github.com/containerd/typeurl v1.0.2 // indirect github.com/coreos/go-iptables v0.6.0 github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/dave/jennifer v1.5.0 // indirect + github.com/dave/jennifer v1.6.1 // indirect github.com/di-wu/xsd-datetime v1.0.0 github.com/djherbis/buffer v1.2.0 // indirect github.com/djherbis/nio/v3 v3.0.1 // indirect @@ -383,7 +385,7 @@ require ( github.com/docker/docker v23.0.1+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/dustin/go-humanize v1.0.0 + github.com/dustin/go-humanize v1.0.1 github.com/elimity-com/scim v0.0.0-20220121082953-15165b1a61c8 github.com/emirpasic/gods v1.18.1 // indirect github.com/envoyproxy/protoc-gen-validate v0.9.1 // indirect @@ -400,7 +402,7 @@ require ( github.com/go-git/go-billy/v5 v5.4.1 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/analysis v0.21.4 // indirect github.com/go-openapi/errors v0.20.3 // indirect @@ -536,7 +538,7 @@ require ( go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.13.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 - golang.org/x/mod v0.8.0 + golang.org/x/mod v0.10.0 golang.org/x/term v0.8.0 // indirect golang.org/x/text v0.9.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect diff --git a/go.sum b/go.sum index 1314b13b82b..c12adc809a0 100644 --- a/go.sum +++ b/go.sum @@ -613,15 +613,8 @@ github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= github.com/danaugrs/go-tsne v0.0.0-20200708172100-6b7d1d577fd3/go.mod h1:tcVxJUGCaPp/YynlqJTfJtGc/LF9vn4WUZSSmaGu3dA= -github.com/dave/astrid v0.0.0-20170323122508-8c2895878b14/go.mod h1:Sth2QfxfATb/nW4EsrSi2KyJmbcniZ8TgTaji17D6ms= -github.com/dave/brenda v1.1.0/go.mod h1:4wCUr6gSlu5/1Tk7akE5X7UorwiQ8Rij0SKH3/BGMOM= -github.com/dave/courtney v0.3.0/go.mod h1:BAv3hA06AYfNUjfjQr+5gc6vxeBVOupLqrColj+QSD8= -github.com/dave/gopackages v0.0.0-20170318123100-46e7023ec56e/go.mod h1:i00+b/gKdIDIxuLDFob7ustLAVqhsZRk2qVZrArELGQ= -github.com/dave/jennifer v1.5.0 h1:HmgPN93bVDpkQyYbqhCHj5QlgvUkvEOzMyEvKLgCRrg= -github.com/dave/jennifer v1.5.0/go.mod h1:4MnyiFIlZS3l5tSDn8VnzE6ffAhYBMB2SZntBsZGUok= -github.com/dave/kerr v0.0.0-20170318121727-bc25dd6abe8e/go.mod h1:qZqlPyPvfsDJt+3wHJ1EvSXDuVjFTK0j2p/ca+gtsb8= -github.com/dave/patsy v0.0.0-20210517141501-957256f50cba/go.mod h1:qfR88CgEGLoiqDaE+xxDCi5QA5v4vUoW0UCX2Nd5Tlc= -github.com/dave/rebecca v0.9.1/go.mod h1:N6XYdMD/OKw3lkF3ywh8Z6wPGuwNFDNtWYEMFWEmXBA= +github.com/dave/jennifer v1.6.1 h1:T4T/67t6RAA5AIV6+NP8Uk/BIsXgDoqEowgycdQQLuk= +github.com/dave/jennifer v1.6.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -694,8 +687,9 @@ github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNE github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= @@ -836,8 +830,9 @@ github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= @@ -980,6 +975,7 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -1769,10 +1765,10 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= +github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= +github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -1785,7 +1781,8 @@ github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQ github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= +github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= +github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -2518,8 +2515,8 @@ golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2649,8 +2646,9 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2939,14 +2937,13 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/gitserver/BUILD.bazel b/internal/gitserver/BUILD.bazel index 53d81574df0..c401304441c 100644 --- a/internal/gitserver/BUILD.bazel +++ b/internal/gitserver/BUILD.bazel @@ -38,6 +38,7 @@ go_library( "//internal/limiter", "//internal/metrics", "//internal/observation", + "//internal/perforce", "//internal/search/streaming/http", "//internal/trace", "//lib/errors", diff --git a/internal/gitserver/client.go b/internal/gitserver/client.go index 054c1c86021..7de39354893 100644 --- a/internal/gitserver/client.go +++ b/internal/gitserver/client.go @@ -40,6 +40,7 @@ import ( "github.com/sourcegraph/sourcegraph/internal/lazyregexp" "github.com/sourcegraph/sourcegraph/internal/limiter" "github.com/sourcegraph/sourcegraph/internal/observation" + p4tools "github.com/sourcegraph/sourcegraph/internal/perforce" "github.com/sourcegraph/sourcegraph/lib/errors" ) @@ -276,6 +277,9 @@ type Client interface { // P4Exec sends a p4 command with given arguments and returns an io.ReadCloser for the output. P4Exec(_ context.Context, host, user, password string, args ...string) (io.ReadCloser, http.Header, error) + // P4GetChangelist gets the changelist specified by changelistID. + P4GetChangelist(_ context.Context, changelistID string, creds PerforceCredentials) (*protocol.PerforceChangelist, error) + // Remove removes the repository clone from gitserver. Remove(context.Context, api.RepoName) error @@ -922,6 +926,39 @@ var deadlineExceededCounter = promauto.NewCounter(prometheus.CounterOpts{ Help: "Times that Client.sendExec() returned context.DeadlineExceeded", }) +func (c *clientImplementor) P4GetChangelist(ctx context.Context, changelistID string, creds PerforceCredentials) (*protocol.PerforceChangelist, error) { + reader, _, err := c.P4Exec(ctx, creds.Host, creds.Username, creds.Password, + "changes", + "-r", // list in reverse order, which means that the given changelist id will be the first one listed + "-m", "1", // limit output to one record, so that the given changelist is the only one listed + "-l", // use a long listing, which includes the whole commit message + "-e", changelistID, // start from this changelist and go up + ) + if err != nil { + return nil, err + } + body, err := io.ReadAll(reader) + if err != nil { + return nil, errors.Wrap(err, "failed to read the output of p4 changes") + } + output := strings.TrimSpace(string(body)) + if output == "" { + return nil, errors.New("invalid changelist " + changelistID) + } + + pcl, err := p4tools.ParseChangelistOutput(output) + if err != nil { + return nil, errors.Wrap(err, "unable to parse change output") + } + return pcl, nil +} + +type PerforceCredentials struct { + Host string + Username string + Password string +} + // BatchLog invokes the given callback with the `git log` output for a batch of repository // and commit pairs. If the invoked callback returns a non-nil error, the operation will begin // to abort processing further results. diff --git a/internal/gitserver/mocks_temp.go b/internal/gitserver/mocks_temp.go index c2e263a2385..b5ca948ca8d 100644 --- a/internal/gitserver/mocks_temp.go +++ b/internal/gitserver/mocks_temp.go @@ -136,6 +136,9 @@ type MockClient struct { // P4ExecFunc is an instance of a mock function object controlling the // behavior of the method P4Exec. P4ExecFunc *ClientP4ExecFunc + // P4GetChangelistFunc is an instance of a mock function object + // controlling the behavior of the method P4GetChangelist. + P4GetChangelistFunc *ClientP4GetChangelistFunc // ReadDirFunc is an instance of a mock function object controlling the // behavior of the method ReadDir. ReadDirFunc *ClientReadDirFunc @@ -372,6 +375,11 @@ func NewMockClient() *MockClient { return }, }, + P4GetChangelistFunc: &ClientP4GetChangelistFunc{ + defaultHook: func(context.Context, string, PerforceCredentials) (r0 *protocol.PerforceChangelist, r1 error) { + return + }, + }, ReadDirFunc: &ClientReadDirFunc{ defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string, bool) (r0 []fs.FileInfo, r1 error) { return @@ -639,6 +647,11 @@ func NewStrictMockClient() *MockClient { panic("unexpected invocation of MockClient.P4Exec") }, }, + P4GetChangelistFunc: &ClientP4GetChangelistFunc{ + defaultHook: func(context.Context, string, PerforceCredentials) (*protocol.PerforceChangelist, error) { + panic("unexpected invocation of MockClient.P4GetChangelist") + }, + }, ReadDirFunc: &ClientReadDirFunc{ defaultHook: func(context.Context, authz.SubRepoPermissionChecker, api.RepoName, api.CommitID, string, bool) ([]fs.FileInfo, error) { panic("unexpected invocation of MockClient.ReadDir") @@ -832,6 +845,9 @@ func NewMockClientFrom(i Client) *MockClient { P4ExecFunc: &ClientP4ExecFunc{ defaultHook: i.P4Exec, }, + P4GetChangelistFunc: &ClientP4GetChangelistFunc{ + defaultHook: i.P4GetChangelist, + }, ReadDirFunc: &ClientReadDirFunc{ defaultHook: i.ReadDir, }, @@ -5060,6 +5076,117 @@ func (c ClientP4ExecFuncCall) Results() []interface{} { return []interface{}{c.Result0, c.Result1, c.Result2} } +// ClientP4GetChangelistFunc describes the behavior when the P4GetChangelist +// method of the parent MockClient instance is invoked. +type ClientP4GetChangelistFunc struct { + defaultHook func(context.Context, string, PerforceCredentials) (*protocol.PerforceChangelist, error) + hooks []func(context.Context, string, PerforceCredentials) (*protocol.PerforceChangelist, error) + history []ClientP4GetChangelistFuncCall + mutex sync.Mutex +} + +// P4GetChangelist delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockClient) P4GetChangelist(v0 context.Context, v1 string, v2 PerforceCredentials) (*protocol.PerforceChangelist, error) { + r0, r1 := m.P4GetChangelistFunc.nextHook()(v0, v1, v2) + m.P4GetChangelistFunc.appendCall(ClientP4GetChangelistFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the P4GetChangelist +// method of the parent MockClient instance is invoked and the hook queue is +// empty. +func (f *ClientP4GetChangelistFunc) SetDefaultHook(hook func(context.Context, string, PerforceCredentials) (*protocol.PerforceChangelist, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// P4GetChangelist method of the parent MockClient 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 *ClientP4GetChangelistFunc) PushHook(hook func(context.Context, string, PerforceCredentials) (*protocol.PerforceChangelist, 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 *ClientP4GetChangelistFunc) SetDefaultReturn(r0 *protocol.PerforceChangelist, r1 error) { + f.SetDefaultHook(func(context.Context, string, PerforceCredentials) (*protocol.PerforceChangelist, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *ClientP4GetChangelistFunc) PushReturn(r0 *protocol.PerforceChangelist, r1 error) { + f.PushHook(func(context.Context, string, PerforceCredentials) (*protocol.PerforceChangelist, error) { + return r0, r1 + }) +} + +func (f *ClientP4GetChangelistFunc) nextHook() func(context.Context, string, PerforceCredentials) (*protocol.PerforceChangelist, 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 *ClientP4GetChangelistFunc) appendCall(r0 ClientP4GetChangelistFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of ClientP4GetChangelistFuncCall objects +// describing the invocations of this function. +func (f *ClientP4GetChangelistFunc) History() []ClientP4GetChangelistFuncCall { + f.mutex.Lock() + history := make([]ClientP4GetChangelistFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// ClientP4GetChangelistFuncCall is an object that describes an invocation +// of method P4GetChangelist on an instance of MockClient. +type ClientP4GetChangelistFuncCall 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 string + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 PerforceCredentials + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *protocol.PerforceChangelist + // 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 ClientP4GetChangelistFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c ClientP4GetChangelistFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + // ClientReadDirFunc describes the behavior when the ReadDir method of the // parent MockClient instance is invoked. type ClientReadDirFunc struct { diff --git a/internal/gitserver/protocol/gitserver.go b/internal/gitserver/protocol/gitserver.go index 9f9dd9d8975..1b3d1f0176b 100644 --- a/internal/gitserver/protocol/gitserver.go +++ b/internal/gitserver/protocol/gitserver.go @@ -2,6 +2,7 @@ package protocol import ( "encoding/json" + "strings" "time" "go.opentelemetry.io/otel/attribute" @@ -778,6 +779,12 @@ type CreateCommitFromPatchResponse struct { // Error is populated only on error Error *CreateCommitFromPatchError + + // ChangelistId is the numeric ID of the changelist that is shelved for the patch. + // only supplied for Perforce code hosts. + // it's a string because it's optional, but usng a scalar pointer is not allowed in protobuf + // so blank string means not provided + ChangelistId string } func (r *CreateCommitFromPatchResponse) ToProto() *proto.CreateCommitFromPatchBinaryResponse { @@ -788,8 +795,9 @@ func (r *CreateCommitFromPatchResponse) ToProto() *proto.CreateCommitFromPatchBi err = nil } return &proto.CreateCommitFromPatchBinaryResponse{ - Rev: r.Rev, - Error: err, + Rev: r.Rev, + Error: err, + ChangelistId: r.ChangelistId, } } @@ -801,6 +809,7 @@ func (r *CreateCommitFromPatchResponse) FromProto(p *proto.CreateCommitFromPatch r.Error.FromProto(p.GetError()) } r.Rev = p.GetRev() + r.ChangelistId = p.ChangelistId } // SetError adds the supplied error related details to e. @@ -891,3 +900,37 @@ func (r *GetObjectResponse) FromProto(p *proto.GetObjectResponse) { } } + +type PerforceChangelist struct { + ID string + CreationDate time.Time + State PerforceChangelistState + Author string + Title string + Message string +} + +type PerforceChangelistState string + +const ( + PerforceChangelistStateSubmitted PerforceChangelistState = "submitted" + PerforceChangelistStatePending PerforceChangelistState = "pending" + PerforceChangelistStateShelved PerforceChangelistState = "shelved" + // Perforce doesn't actually return a state for closed changelists, so this is one we use to indicate the changelist is closed. + PerforceChangelistStateClosed PerforceChangelistState = "closed" +) + +func ParsePerforceChangelistState(state string) (PerforceChangelistState, error) { + switch strings.ToLower(strings.TrimSpace(state)) { + case "submitted": + return PerforceChangelistStateSubmitted, nil + case "pending": + return PerforceChangelistStatePending, nil + case "shelved": + return PerforceChangelistStateShelved, nil + case "closed": + return PerforceChangelistStateClosed, nil + default: + return "", errors.Newf("invalid Perforce changelist state: %s", state) + } +} diff --git a/internal/gitserver/v1/gitserver.pb.go b/internal/gitserver/v1/gitserver.pb.go index 8497b77b7de..11bb7ab4b22 100644 --- a/internal/gitserver/v1/gitserver.pb.go +++ b/internal/gitserver/v1/gitserver.pb.go @@ -656,7 +656,7 @@ type CreateCommitFromPatchError struct { RepositoryName string `protobuf:"bytes,1,opt,name=repository_name,json=repositoryName,proto3" json:"repository_name,omitempty"` // internal_error is the error that occurred on the server InternalError string `protobuf:"bytes,2,opt,name=internal_error,json=internalError,proto3" json:"internal_error,omitempty"` - // command is th git command that was attempted + // command is the git command that was attempted Command string `protobuf:"bytes,3,opt,name=command,proto3" json:"command,omitempty"` // combined_output is the combined stderr and stdout from running the command CombinedOutput string `protobuf:"bytes,4,opt,name=combined_output,json=combinedOutput,proto3" json:"combined_output,omitempty"` @@ -733,6 +733,8 @@ type CreateCommitFromPatchBinaryResponse struct { Rev string `protobuf:"bytes,1,opt,name=rev,proto3" json:"rev,omitempty"` // error is populated only on error Error *CreateCommitFromPatchError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + // changelistid is the Perforce changelist id + ChangelistId string `protobuf:"bytes,3,opt,name=changelist_id,json=changelistId,proto3" json:"changelist_id,omitempty"` } func (x *CreateCommitFromPatchBinaryResponse) Reset() { @@ -781,6 +783,13 @@ func (x *CreateCommitFromPatchBinaryResponse) GetError() *CreateCommitFromPatchE return nil } +func (x *CreateCommitFromPatchBinaryResponse) GetChangelistId() string { + if x != nil { + return x.ChangelistId + } + return "" +} + type ExecRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3649,415 +3658,417 @@ var file_gitserver_proto_rawDesc = []byte{ 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x4f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x22, 0x77, 0x0a, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x63, 0x68, 0x42, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x72, - 0x65, 0x76, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x76, 0x12, 0x3e, 0x0a, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, - 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x63, - 0x68, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x93, 0x01, - 0x0a, 0x0b, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, - 0x6f, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x6e, 0x73, 0x75, - 0x72, 0x65, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, - 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x73, 0x74, 0x64, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, - 0x74, 0x64, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6e, 0x6f, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x22, 0x22, 0x0a, 0x0c, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x78, 0x0a, 0x0f, 0x4e, 0x6f, 0x74, 0x46, 0x6f, - 0x75, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, - 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x2a, - 0x0a, 0x11, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x63, 0x6c, 0x6f, 0x6e, 0x65, - 0x49, 0x6e, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6c, - 0x6f, 0x6e, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, - 0x73, 0x22, 0x4c, 0x0a, 0x11, 0x45, 0x78, 0x65, 0x63, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x22, - 0x80, 0x02, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x3d, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x09, 0x72, 0x65, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x44, 0x69, 0x66, 0x66, 0x12, 0x34, 0x0a, - 0x16, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, - 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, - 0x6c, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x22, 0x73, 0x0a, 0x11, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x70, - 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x5f, 0x73, - 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x76, 0x53, 0x70, - 0x65, 0x63, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x65, 0x66, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x66, 0x47, 0x6c, 0x6f, 0x62, 0x12, 0x28, 0x0a, - 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x5f, 0x67, 0x6c, 0x6f, - 0x62, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x52, 0x65, 0x66, 0x47, 0x6c, 0x6f, 0x62, 0x22, 0x48, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x65, 0x78, 0x70, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, - 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x73, - 0x65, 0x22, 0x4b, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x4d, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x1f, 0x0a, - 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x73, 0x65, 0x22, 0x4c, - 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x4e, 0x6f, - 0x64, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x4b, 0x0a, 0x0f, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x12, - 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x49, 0x0a, 0x12, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, + 0x74, 0x70, 0x75, 0x74, 0x22, 0x9c, 0x01, 0x0a, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x63, 0x68, 0x42, 0x69, + 0x6e, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, + 0x72, 0x65, 0x76, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x76, 0x12, 0x3e, + 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, + 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, + 0x63, 0x68, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x23, + 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x69, 0x73, + 0x74, 0x49, 0x64, 0x22, 0x93, 0x01, 0x0a, 0x0b, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x6e, 0x73, 0x75, 0x72, + 0x65, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, + 0x61, 0x72, 0x67, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x64, 0x69, 0x6e, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x64, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, + 0x6e, 0x6f, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x22, 0x0a, 0x0c, 0x45, 0x78, 0x65, + 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x78, 0x0a, + 0x0f, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x72, 0x65, 0x70, 0x6f, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x5f, 0x69, 0x6e, + 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0f, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x49, 0x6e, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x50, + 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x22, 0x4c, 0x0a, 0x11, 0x45, 0x78, 0x65, 0x63, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1f, 0x0a, 0x0b, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, + 0x74, 0x64, 0x65, 0x72, 0x72, 0x22, 0x80, 0x02, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x3d, 0x0a, 0x09, 0x72, + 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, + 0x09, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69, 0x66, 0x66, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x44, + 0x69, 0x66, 0x66, 0x12, 0x34, 0x0a, 0x16, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x69, + 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x05, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x22, 0x73, 0x0a, 0x11, 0x52, 0x65, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x19, 0x0a, + 0x08, 0x72, 0x65, 0x76, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x72, 0x65, 0x76, 0x53, 0x70, 0x65, 0x63, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x65, 0x66, 0x5f, + 0x67, 0x6c, 0x6f, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x66, 0x47, + 0x6c, 0x6f, 0x62, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x72, + 0x65, 0x66, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, + 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x66, 0x47, 0x6c, 0x6f, 0x62, 0x22, 0x48, 0x0a, + 0x11, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, + 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, + 0x5f, 0x63, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x67, 0x6e, + 0x6f, 0x72, 0x65, 0x43, 0x61, 0x73, 0x65, 0x22, 0x4b, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, - 0x43, 0x61, 0x73, 0x65, 0x22, 0x46, 0x0a, 0x0f, 0x44, 0x69, 0x66, 0x66, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x73, 0x65, 0x22, 0x4b, 0x0a, 0x14, - 0x44, 0x69, 0x66, 0x66, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x73, 0x46, 0x69, 0x6c, 0x65, - 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x67, 0x6e, 0x6f, - 0x72, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x73, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x42, 0x6f, 0x6f, - 0x6c, 0x65, 0x61, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x73, - 0x0a, 0x0c, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x2e, - 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x67, - 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x33, - 0x0a, 0x08, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x08, 0x6f, 0x70, 0x65, 0x72, 0x61, - 0x6e, 0x64, 0x73, 0x22, 0x92, 0x05, 0x0a, 0x09, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x6f, 0x64, - 0x65, 0x12, 0x48, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6d, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x11, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x10, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x45, - 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, - 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x42, - 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x42, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, - 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, - 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x4b, 0x0a, 0x0f, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, - 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0c, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x6d, - 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, - 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x66, 0x66, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x64, - 0x69, 0x66, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x52, 0x0a, 0x12, 0x64, 0x69, - 0x66, 0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x73, 0x5f, 0x66, 0x69, 0x6c, 0x65, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x66, 0x66, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, - 0x65, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x10, 0x64, 0x69, - 0x66, 0x66, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x35, - 0x0a, 0x07, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, - 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x07, 0x62, 0x6f, - 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x12, 0x38, 0x0a, 0x08, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x4e, - 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x08, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x42, - 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x6d, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x05, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x48, 0x00, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1d, 0x0a, - 0x09, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x48, 0x00, 0x52, 0x08, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x48, 0x69, 0x74, 0x42, 0x09, 0x0a, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xa9, 0x06, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x6f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x69, 0x64, 0x12, 0x3b, 0x0a, 0x06, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, 0x69, 0x74, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x06, - 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x41, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, 0x69, 0x74, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x66, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x04, 0x72, 0x65, 0x66, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x73, 0x12, 0x41, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x69, 0x74, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x64, - 0x69, 0x66, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x69, 0x74, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x04, 0x64, 0x69, 0x66, 0x66, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x6f, 0x64, 0x69, - 0x66, 0x69, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x1a, - 0x65, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, 0x1a, 0x62, 0x0a, 0x0d, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, - 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x12, 0x37, 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x52, 0x61, 0x6e, - 0x67, 0x65, 0x52, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x1a, 0x77, 0x0a, 0x05, 0x52, 0x61, - 0x6e, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x4c, 0x6f, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x34, 0x0a, - 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x69, 0x74, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, - 0x65, 0x6e, 0x64, 0x1a, 0x4e, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, - 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x63, 0x6f, 0x6c, - 0x75, 0x6d, 0x6e, 0x22, 0x74, 0x0a, 0x0e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x65, - 0x65, 0x69, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x72, 0x65, 0x65, - 0x69, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x70, - 0x61, 0x74, 0x68, 0x73, 0x70, 0x65, 0x63, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, - 0x70, 0x61, 0x74, 0x68, 0x73, 0x70, 0x65, 0x63, 0x73, 0x22, 0x25, 0x0a, 0x0f, 0x41, 0x72, 0x63, - 0x68, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x22, 0x2c, 0x0a, 0x16, 0x49, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x61, - 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, - 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x22, 0x67, - 0x0a, 0x17, 0x49, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x61, 0x62, 0x6c, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x6f, - 0x6e, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6c, - 0x6f, 0x6e, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6c, 0x6f, 0x6e, 0x65, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x64, 0x12, - 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x26, 0x0a, 0x10, 0x52, 0x65, 0x70, 0x6f, 0x43, - 0x6c, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, - 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x22, - 0x29, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x30, 0x0a, 0x18, 0x52, 0x65, - 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x22, 0x7e, 0x0a, 0x11, - 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x70, 0x72, - 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x63, 0x6c, - 0x6f, 0x6e, 0x65, 0x49, 0x6e, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x0a, - 0x0e, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, - 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x64, 0x22, 0xc8, 0x01, 0x0a, - 0x19, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, - 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x07, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x69, - 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x43, - 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x5b, 0x0a, 0x0c, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x35, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x69, - 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x43, - 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x27, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, - 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x70, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, - 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x69, 0x6e, 0x63, - 0x65, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, - 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6c, 0x6f, - 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x68, 0x61, 0x72, 0x64, 0x22, 0xa8, 0x01, 0x0a, 0x12, - 0x52, 0x65, 0x70, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, - 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x43, 0x61, 0x73, 0x65, 0x22, 0x4c, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x42, 0x65, + 0x66, 0x6f, 0x72, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x22, 0x4b, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x41, 0x66, 0x74, 0x65, + 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, - 0x64, 0x12, 0x3d, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, - 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x13, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x53, - 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x73, 0x0a, 0x12, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x67, 0x69, 0x74, 0x5f, 0x64, 0x69, 0x72, 0x5f, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x67, 0x69, 0x74, 0x44, 0x69, 0x72, - 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, - 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, - 0x22, 0x6f, 0x0a, 0x0d, 0x50, 0x34, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x34, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x70, 0x34, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x34, 0x75, - 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x34, 0x75, 0x73, 0x65, - 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x34, 0x70, 0x61, 0x73, 0x73, 0x77, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x34, 0x70, 0x61, 0x73, 0x73, 0x77, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, - 0x73, 0x22, 0x24, 0x0a, 0x0e, 0x50, 0x34, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x47, - 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, - 0x0a, 0x0d, 0x67, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x48, - 0x6f, 0x73, 0x74, 0x22, 0x34, 0x0a, 0x0c, 0x47, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x52, - 0x65, 0x70, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x48, 0x0a, 0x14, 0x4c, 0x69, 0x73, - 0x74, 0x47, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x30, 0x0a, 0x05, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x52, 0x05, 0x72, 0x65, - 0x70, 0x6f, 0x73, 0x22, 0x47, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x44, 0x0a, 0x11, - 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x69, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x22, 0xd8, 0x01, 0x0a, 0x09, 0x47, 0x69, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x36, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, - 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, - 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x0a, 0x4f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x4f, 0x42, 0x4a, 0x45, 0x43, - 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, - 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x41, 0x47, 0x10, - 0x02, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x42, 0x4a, 0x45, 0x43, - 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4c, 0x4f, 0x42, 0x10, 0x04, 0x2a, 0x71, 0x0a, - 0x0c, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1d, 0x0a, - 0x19, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, - 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x4e, - 0x44, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x4f, 0x52, 0x5f, - 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x4f, 0x50, 0x45, - 0x52, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4e, 0x4f, 0x54, 0x10, 0x03, - 0x32, 0xc3, 0x09, 0x0a, 0x10, 0x47, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, - 0x67, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x84, 0x01, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x63, 0x68, 0x42, 0x69, 0x6e, 0x61, - 0x72, 0x79, 0x12, 0x30, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x72, - 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x63, 0x68, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x63, 0x68, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x04, 0x45, 0x78, 0x65, - 0x63, 0x12, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, - 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x09, - 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x60, 0x0a, 0x0f, - 0x49, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x12, - 0x24, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, - 0x73, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, + 0x49, 0x0a, 0x12, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x67, 0x6e, + 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, + 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x73, 0x65, 0x22, 0x46, 0x0a, 0x0f, 0x44, 0x69, + 0x66, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x78, 0x70, + 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, + 0x73, 0x65, 0x22, 0x4b, 0x0a, 0x14, 0x44, 0x69, 0x66, 0x66, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, + 0x65, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, + 0x70, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x12, 0x1f, + 0x0a, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x73, 0x65, 0x22, + 0x23, 0x0a, 0x0b, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x22, 0x73, 0x0a, 0x0c, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, + 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, + 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x33, 0x0a, 0x08, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x6e, 0x64, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x08, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x92, 0x05, 0x0a, 0x09, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x48, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, + 0x48, 0x00, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x73, 0x12, 0x51, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x6d, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, + 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, + 0x48, 0x00, 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x62, + 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x69, + 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x0c, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x42, 0x0a, 0x0c, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, + 0x48, 0x00, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, + 0x4b, 0x0a, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0c, + 0x64, 0x69, 0x66, 0x66, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x69, 0x66, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, 0x6f, 0x64, + 0x65, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x69, 0x66, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, + 0x12, 0x52, 0x0a, 0x12, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, + 0x73, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, + 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x66, 0x66, + 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x48, 0x00, 0x52, 0x10, 0x64, 0x69, 0x66, 0x66, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x73, + 0x46, 0x69, 0x6c, 0x65, 0x12, 0x35, 0x0a, 0x07, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x4e, 0x6f, 0x64, 0x65, + 0x48, 0x00, 0x52, 0x07, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x12, 0x38, 0x0a, 0x08, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x08, 0x6f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x6d, + 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x31, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x48, 0x00, 0x52, 0x05, 0x6d, 0x61, + 0x74, 0x63, 0x68, 0x12, 0x1d, 0x0a, 0x09, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x69, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x48, + 0x69, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xa9, 0x06, + 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x10, 0x0a, + 0x03, 0x6f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x69, 0x64, 0x12, + 0x3b, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x23, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x41, 0x0a, 0x09, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x23, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x12, + 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x66, + 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x66, 0x73, 0x12, 0x1f, 0x0a, + 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x73, 0x12, 0x41, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x64, 0x69, 0x66, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x04, 0x64, 0x69, 0x66, 0x66, 0x12, 0x25, + 0x0a, 0x0e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, + 0x46, 0x69, 0x6c, 0x65, 0x73, 0x1a, 0x65, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x2e, 0x0a, 0x04, + 0x64, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, 0x1a, 0x62, 0x0a, 0x0d, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, + 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x74, + 0x63, 0x68, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, + 0x1a, 0x77, 0x0a, 0x05, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x05, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x12, 0x34, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x4c, 0x6f, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x1a, 0x4e, 0x0a, 0x08, 0x4c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x6c, 0x69, 0x6e, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x74, 0x0a, 0x0e, 0x41, 0x72, 0x63, + 0x68, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, + 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, + 0x18, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x69, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x74, 0x72, 0x65, 0x65, 0x69, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x74, 0x68, 0x73, 0x70, 0x65, 0x63, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x74, 0x68, 0x73, 0x70, 0x65, 0x63, 0x73, 0x22, + 0x25, 0x0a, 0x0f, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x2c, 0x0a, 0x16, 0x49, 0x73, 0x52, 0x65, 0x70, 0x6f, + 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x72, 0x65, 0x70, 0x6f, 0x22, 0x67, 0x0a, 0x17, 0x49, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, + 0x6f, 0x6e, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x09, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, + 0x6c, 0x6f, 0x6e, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x26, 0x0a, + 0x10, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x72, 0x65, 0x70, 0x6f, 0x22, 0x29, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, + 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x22, 0x30, 0x0a, 0x18, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, + 0x72, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x72, 0x65, 0x70, + 0x6f, 0x73, 0x22, 0x7e, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x50, + 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6c, 0x6f, 0x6e, 0x65, + 0x5f, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0f, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x49, 0x6e, 0x50, 0x72, 0x6f, 0x67, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x5f, 0x70, 0x72, 0x6f, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x6f, + 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6c, + 0x6f, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, 0x6c, 0x6f, 0x6e, + 0x65, 0x64, 0x22, 0xc8, 0x01, 0x0a, 0x19, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, + 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4e, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, + 0x1a, 0x5b, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x27, 0x0a, + 0x11, 0x52, 0x65, 0x70, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x70, 0x6f, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x82, 0x01, 0x0a, + 0x11, 0x52, 0x65, 0x70, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x6c, 0x6f, 0x6e, 0x65, + 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x22, 0xa8, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x70, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, + 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x13, 0x0a, 0x11, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x73, 0x0a, 0x12, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x67, 0x69, 0x74, 0x5f, 0x64, + 0x69, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, + 0x67, 0x69, 0x74, 0x44, 0x69, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x6f, 0x0a, 0x0d, 0x50, 0x34, 0x45, 0x78, 0x65, 0x63, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x34, 0x70, 0x6f, 0x72, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x34, 0x70, 0x6f, 0x72, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x70, 0x34, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x70, 0x34, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x34, 0x70, 0x61, 0x73, + 0x73, 0x77, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x34, 0x70, 0x61, 0x73, + 0x73, 0x77, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x22, 0x24, 0x0a, 0x0e, 0x50, 0x34, 0x45, 0x78, 0x65, + 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x0a, + 0x13, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, + 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x69, 0x74, + 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x34, 0x0a, 0x0c, 0x47, 0x69, 0x74, + 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, + 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, + 0x48, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x52, 0x65, + 0x70, 0x6f, 0x52, 0x05, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x22, 0x47, 0x0a, 0x10, 0x47, 0x65, 0x74, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, + 0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, + 0x6d, 0x65, 0x22, 0x44, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0xd8, 0x01, 0x0a, 0x09, 0x47, 0x69, 0x74, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x82, + 0x01, 0x0a, 0x0a, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, + 0x17, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x4f, 0x42, + 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, + 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x54, 0x41, 0x47, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x42, 0x4a, 0x45, 0x43, + 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x03, 0x12, 0x14, 0x0a, + 0x10, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4c, 0x4f, + 0x42, 0x10, 0x04, 0x2a, 0x71, 0x0a, 0x0c, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x4b, + 0x69, 0x6e, 0x64, 0x12, 0x1d, 0x0a, 0x19, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x4f, 0x52, 0x5f, + 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x4b, + 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x4e, 0x44, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, + 0x52, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4f, 0x52, 0x10, 0x02, 0x12, + 0x15, 0x0a, 0x11, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x4b, 0x49, 0x4e, 0x44, + 0x5f, 0x4e, 0x4f, 0x54, 0x10, 0x03, 0x32, 0xc3, 0x09, 0x0a, 0x10, 0x47, 0x69, 0x74, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x42, + 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x84, 0x01, 0x0a, 0x1b, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, + 0x63, 0x68, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x12, 0x30, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x63, 0x68, 0x42, 0x69, 0x6e, + 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x69, 0x74, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x63, 0x68, 0x42, + 0x69, 0x6e, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x41, 0x0a, 0x04, 0x45, 0x78, 0x65, 0x63, 0x12, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, + 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x60, 0x0a, 0x0f, 0x49, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, + 0x65, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x24, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, - 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, - 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x12, 0x21, - 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x47, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, - 0x68, 0x12, 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, - 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, - 0x12, 0x4a, 0x0a, 0x07, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x69, - 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, - 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x47, 0x0a, 0x06, - 0x50, 0x34, 0x45, 0x78, 0x65, 0x63, 0x12, 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x34, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x34, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, - 0x6e, 0x65, 0x12, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x66, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, - 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x26, 0x2e, 0x67, 0x69, 0x74, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, - 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, - 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, - 0x0a, 0x52, 0x65, 0x70, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x69, - 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, - 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x51, 0x0a, 0x0a, 0x52, 0x65, 0x70, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1f, - 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x70, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x70, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0a, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x53, 0x74, 0x61, 0x74, - 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x69, + 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x52, 0x65, 0x70, + 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x6f, + 0x6c, 0x69, 0x74, 0x65, 0x12, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x6f, 0x6c, 0x69, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x6f, 0x6c, + 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, + 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x4a, 0x0a, 0x07, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, + 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x30, 0x01, 0x12, 0x47, 0x0a, 0x06, 0x50, 0x34, 0x45, 0x78, 0x65, 0x63, 0x12, 0x1b, 0x2e, 0x67, + 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x34, 0x45, 0x78, + 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x34, 0x45, 0x78, 0x65, 0x63, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x09, 0x52, + 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x12, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x66, 0x0a, 0x11, 0x52, + 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x26, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x43, 0x6c, 0x6f, 0x6e, + 0x65, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0a, 0x52, 0x65, 0x70, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x3a, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, - 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, - 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0a, 0x52, 0x65, 0x70, 0x6f, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0a, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x53, 0x74, 0x61, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x53, 0x74, 0x61, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x3a, 0x5a, 0x38, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x67, 0x72, 0x61, + 0x70, 0x68, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x69, 0x74, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/gitserver/v1/gitserver.proto b/internal/gitserver/v1/gitserver.proto index 41207b2c858..1c560222580 100644 --- a/internal/gitserver/v1/gitserver.proto +++ b/internal/gitserver/v1/gitserver.proto @@ -113,7 +113,7 @@ message CreateCommitFromPatchError { string repository_name = 1; // internal_error is the error that occurred on the server string internal_error = 2; - // command is th git command that was attempted + // command is the git command that was attempted string command = 3; // combined_output is the combined stderr and stdout from running the command string combined_output = 4; @@ -126,6 +126,8 @@ message CreateCommitFromPatchBinaryResponse { string rev = 1; // error is populated only on error CreateCommitFromPatchError error = 2; + // changelistid is the Perforce changelist id + string changelist_id = 3; } message ExecRequest { string repo = 1; diff --git a/internal/perforce/BUILD.bazel b/internal/perforce/BUILD.bazel index de83196d983..e03216524e9 100644 --- a/internal/perforce/BUILD.bazel +++ b/internal/perforce/BUILD.bazel @@ -8,6 +8,7 @@ go_library( visibility = ["//:__subpackages__"], deps = [ "//internal/api", + "//internal/gitserver/protocol", "//internal/lazyregexp", "//lib/errors", ], @@ -17,5 +18,9 @@ go_test( name = "perforce_test", srcs = ["changelist_test.go"], embed = [":perforce"], - deps = ["@com_github_stretchr_testify//require"], + deps = [ + "//internal/gitserver/protocol", + "@com_github_google_go_cmp//cmp", + "@com_github_stretchr_testify//require", + ], ) diff --git a/internal/perforce/changelist.go b/internal/perforce/changelist.go index a065ad973fc..f101d767e7c 100644 --- a/internal/perforce/changelist.go +++ b/internal/perforce/changelist.go @@ -3,7 +3,13 @@ package perforce import ( "fmt" + "encoding/json" + "strings" + "time" + "github.com/sourcegraph/sourcegraph/internal/api" + + "github.com/sourcegraph/sourcegraph/internal/gitserver/protocol" "github.com/sourcegraph/sourcegraph/internal/lazyregexp" "github.com/sourcegraph/sourcegraph/lib/errors" ) @@ -18,6 +24,7 @@ import ( // we can look for this pattern even when this is not in its own line by itself. var gitP4Pattern = lazyregexp.New(`\[(?:git-p4|p4-fusion): depot-paths? = "(.*?)"\: change = (\d+)\]`) +// Parses a changelist id from the message trailer that `git p4` and `p4-fusion` add to the commit message func GetP4ChangelistID(body string) (string, error) { matches := gitP4Pattern.FindStringSubmatch(body) if len(matches) != 3 { @@ -36,3 +43,89 @@ type ChangelistNotFoundError struct { func (e *ChangelistNotFoundError) Error() string { return fmt.Sprintf("revision not found: %s@%s", e.Repo, e.ID) } + +type BadChangelistError struct { + CID string + Repo api.RepoName +} + +func (e *BadChangelistError) Error() string { + return fmt.Sprintf("invalid changelist ID %q for repo %q", e.Repo, e.CID) +} + +// Example changelist info output in "long" format +// (from `p4 changes -l ...`) +// Change 1188 on 2023/06/09 by admin@yet-moar-lines *pending* +// +// Append still another line to all SECOND.md files +// +// "admin@yet-moar-lines" is the username @ the client spec name, which in this case is the branch name from the batch change +// the final field - "*pending*" in this example - is optional and not present when the changelist has been submitted ("merged", in Git parlance) +// Example changelist info in json format +// (from `p4 -ztags -Mj changes -l ...`) +// {"data":"Change 1178 on 2023/06/01 by admin@hello-third-world *pending*\n\n\tAppend Hello World to all THIRD.md files\n","level":0} +var changelistInfoPattern = lazyregexp.New(`^Change (\d+) on (\d{4}/\d{2}/\d{2}) by ([^ ]+)@([^ ]+)(?: [*](pending|submitted|shelved)[*])?(?: '(.+)')?$`) + +type changelistJson struct { + Data string `json:"data"` + Level int `json:"level"` +} + +// Parses the output of `p4 changes` +// Handles one changelist only +// Accepts any format: standard, long, json standard, json long +func ParseChangelistOutput(output string) (*protocol.PerforceChangelist, error) { + // output will be whitespace-trimmed and not empty + + // if the given text is json format, extract the Data portion + // so that it will have the same format as the standard output + cidj := new(changelistJson) + err := json.Unmarshal([]byte(output), cidj) + if err == nil { + output = strings.TrimSpace(cidj.Data) + } + + lines := strings.Split(output, "\n") + + // the first line contains the changelist information + matches := changelistInfoPattern.FindStringSubmatch(lines[0]) + + if matches == nil || len(matches) < 5 { + return nil, errors.New("invalid changelist output") + } + + pcl := new(protocol.PerforceChangelist) + pcl.ID = matches[1] + time, err := time.Parse("2006/01/02", matches[2]) + if err != nil { + return nil, errors.Wrap(err, "invalid date: "+matches[2]) + } + pcl.CreationDate = time + pcl.Author = matches[3] + pcl.Title = matches[4] + status := "submitted" + if len(matches) > 5 && matches[5] != "" { + status = matches[5] + } + cls, err := protocol.ParsePerforceChangelistState(status) + if err != nil { + return nil, err + } + pcl.State = cls + + if len(matches) > 6 && matches[6] != "" { + // the commit message is inline with the info + pcl.Message = strings.TrimSpace(matches[6]) + } else { + // the commit message is in subsequent lines of the output + var builder strings.Builder + for i := 2; i < len(lines); i++ { + if i > 2 { + builder.WriteString("\n") + } + builder.WriteString(strings.TrimSpace(lines[i])) + } + pcl.Message = builder.String() + } + return pcl, nil +} diff --git a/internal/perforce/changelist_test.go b/internal/perforce/changelist_test.go index 4a7a31b9463..ab1c51ad1f9 100644 --- a/internal/perforce/changelist_test.go +++ b/internal/perforce/changelist_test.go @@ -3,8 +3,12 @@ package perforce import ( "reflect" "testing" + "time" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" + + "github.com/sourcegraph/sourcegraph/internal/gitserver/protocol" ) func TestGetP4ChangelistID(t *testing.T) { @@ -51,3 +55,131 @@ func TestGetP4ChangelistID(t *testing.T) { } } } + +func TestParseChangelistOutput(t *testing.T) { + testCases := []struct { + output string + expectedChangelist *protocol.PerforceChangelist + shouldError bool + }{ + { + output: `Change 1188 on 2023/06/09 by admin@test-first-one *pending* + + Append still another line to all SECOND.md files + Here's a second line of message`, + expectedChangelist: &protocol.PerforceChangelist{ + ID: "1188", + CreationDate: time.Date(2023, 6, 9, 0, 0, 0, 0, time.UTC), + Author: "admin", + Title: "test-first-one", + State: protocol.PerforceChangelistStatePending, + Message: "Append still another line to all SECOND.md files\nHere's a second line of message", + }, + }, + { + output: `Change 1234567 on 2023/04/09 by someone@dsobsdfoibsdv + + Append still another line to all SECOND.md files + Here's a second line of message`, + expectedChangelist: &protocol.PerforceChangelist{ + ID: "1234567", + CreationDate: time.Date(2023, 4, 9, 0, 0, 0, 0, time.UTC), + Author: "someone", + Title: "dsobsdfoibsdv", + State: protocol.PerforceChangelistStateSubmitted, + Message: "Append still another line to all SECOND.md files\nHere's a second line of message", + }, + }, + { + output: `{"data":"Change 1188 on 2023/06/09 by admin@json-with-status *pending*\n\n\tAppend still another line to all SECOND.md files\n\tand another line here\n","level":0}`, + expectedChangelist: &protocol.PerforceChangelist{ + ID: "1188", + CreationDate: time.Date(2023, 6, 9, 0, 0, 0, 0, time.UTC), + Author: "admin", + Title: "json-with-status", + State: protocol.PerforceChangelistStatePending, + Message: "Append still another line to all SECOND.md files\nand another line here", + }, + }, + { + output: `{"data":"Change 1188 on 2023/06/09 by admin@json-no-status\n\n\tAppend still another line to all SECOND.md files\n\tand another line here\n","level":0}`, + expectedChangelist: &protocol.PerforceChangelist{ + ID: "1188", + CreationDate: time.Date(2023, 6, 9, 0, 0, 0, 0, time.UTC), + Author: "admin", + Title: "json-no-status", + State: protocol.PerforceChangelistStateSubmitted, + Message: "Append still another line to all SECOND.md files\nand another line here", + }, + }, + { + output: `{"data":"Change 27 on 2023/05/03 by admin@buttercup\n\n\t generated change at 2023-05-02 17:44:59.012487 -0700 PDT m=+7.371337167\n","level":0}`, + expectedChangelist: &protocol.PerforceChangelist{ + ID: "27", + CreationDate: time.Date(2023, 5, 3, 0, 0, 0, 0, time.UTC), + Author: "admin", + Title: "buttercup", + State: protocol.PerforceChangelistStateSubmitted, + Message: `generated change at 2023-05-02 17:44:59.012487 -0700 PDT m=+7.371337167`, + }, + }, + { + output: `Change 27 on 2023/05/03 by admin@buttercup`, + expectedChangelist: &protocol.PerforceChangelist{ + ID: "27", + CreationDate: time.Date(2023, 5, 3, 0, 0, 0, 0, time.UTC), + Author: "admin", + Title: "buttercup", + State: protocol.PerforceChangelistStateSubmitted, + Message: "", + }, + }, + { + output: `{"data":"Change 55 on 2023/05/03 by admin@test5 ' generated change at 2023-05-'","level":0}`, + expectedChangelist: &protocol.PerforceChangelist{ + ID: "55", + CreationDate: time.Date(2023, 5, 3, 0, 0, 0, 0, time.UTC), + Author: "admin", + Title: "test5", + State: protocol.PerforceChangelistStateSubmitted, + Message: `generated change at 2023-05-`, + }, + }, + { + output: `{"data":"Change 55 on 2023/56/42 by admin@buttercup ' generated change at 2023-05-'","level":0}`, + shouldError: true, + }, + { + output: `Change 55 by admin@buttercup 'generated change at 2023-05-'`, + shouldError: true, + }, + { + output: `{"data":"Change 1185 on 2023/06/09 by admin@yet-moar-lines *INVALID* 'Append still another line to al'","level":0}`, + shouldError: true, + }, + { + output: `Change INVALID on 2023/06/09 by admin@yet-moar-lines *pending* + + Append still another line to all SECOND.md files + + `, + shouldError: true, + }, + } + + for _, testCase := range testCases { + changelist, err := ParseChangelistOutput(testCase.output) + if testCase.shouldError { + if err == nil { + t.Errorf("expected error but got nil") + } + continue + } + if err != nil { + t.Errorf("unexpected error: %s", err) + } + if diff := cmp.Diff(testCase.expectedChangelist, changelist); diff != "" { + t.Errorf("parsed changelist did not match expected (-want +got):\n%s", diff) + } + } +} diff --git a/mockgen.test.yaml b/mockgen.test.yaml index 21762502580..87d7835b440 100644 --- a/mockgen.test.yaml +++ b/mockgen.test.yaml @@ -23,6 +23,10 @@ interfaces: - Client prefix: Gerrit + - path: github.com/sourcegraph/sourcegraph/internal/gitserver + interfaces: + - Client + prefix: Gitserver - filename: cmd/frontend/internal/httpapi/mocks_test.go path: github.com/sourcegraph/sourcegraph/internal/httpcli interfaces: diff --git a/schema/schema.go b/schema/schema.go index 32b5d57d42a..b9d9a51fdad 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -789,6 +789,8 @@ type ExpandedGitCommitDescription struct { // ExperimentalFeatures description: Experimental features and settings. type ExperimentalFeatures struct { + // BatchChangesEnablePerforce description: When enabled, batch changes will be executable on Perforce depots. + BatchChangesEnablePerforce bool `json:"batchChanges.enablePerforce,omitempty"` // CustomGitFetch description: JSON array of configuration that maps from Git clone URL domain/path to custom git fetch command. To enable this feature set environment variable `ENABLE_CUSTOM_GIT_FETCH` as `true` on gitserver. CustomGitFetch []*CustomGitFetchMapping `json:"customGitFetch,omitempty"` // DebugLog description: Turns on debug logging for specific debugging scenarios. @@ -881,6 +883,7 @@ func (v *ExperimentalFeatures) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &m); err != nil { return err } + delete(m, "batchChanges.enablePerforce") delete(m, "customGitFetch") delete(m, "debug.log") delete(m, "enableGRPC") diff --git a/schema/site.schema.json b/schema/site.schema.json index cfeb3286603..2c1dcc14e1c 100644 --- a/schema/site.schema.json +++ b/schema/site.schema.json @@ -522,6 +522,12 @@ "!go": { "pointer": true } + }, + "batchChanges.enablePerforce": { + "description": "When enabled, batch changes will be executable on Perforce depots.", + "type": "boolean", + "group": "BatchChanges", + "default": false } }, "examples": [