Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package gh for openSUSE:Factory checked in at 2022-11-29 10:54:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gh (Old) and /work/SRC/openSUSE:Factory/.gh.new.1597 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gh" Tue Nov 29 10:54:09 2022 rev:24 rq:1038789 version:2.20.2 Changes: -------- --- /work/SRC/openSUSE:Factory/gh/gh.changes 2022-11-12 17:41:40.790350405 +0100 +++ /work/SRC/openSUSE:Factory/.gh.new.1597/gh.changes 2022-11-29 10:54:54.153287260 +0100 @@ -1,0 +2,10 @@ +Tue Nov 29 05:02:04 UTC 2022 - Emily Roberts <nopeinomi...@posteo.net> + +- Update to 2.20.2 + https://github.com/cli/cli/releases + * Update security policy by @maclarel in #6587 + * Fix listing repositories for a named GitHub user by @mislav in #6608 + * Fix commands not properly refreshing the terminal screen by @samcoe in #6607 + + +------------------------------------------------------------------- Old: ---- cli-2.20.0.tar.gz New: ---- cli-2.20.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gh.spec ++++++ --- /var/tmp/diff_new_pack.1wFfit/_old 2022-11-29 10:54:55.973296821 +0100 +++ /var/tmp/diff_new_pack.1wFfit/_new 2022-11-29 10:54:55.977296842 +0100 @@ -19,7 +19,7 @@ %define goflags "-buildmode=pie -trimpath -mod=vendor -modcacherw" %define sname cli Name: gh -Version: 2.20.0 +Version: 2.20.2 Release: 0 Summary: The official CLI for GitHub License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.1wFfit/_old 2022-11-29 10:54:56.013297031 +0100 +++ /var/tmp/diff_new_pack.1wFfit/_new 2022-11-29 10:54:56.017297052 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/cli/cli</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v2.20.0</param> + <param name="revision">v2.20.2</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">disable</param> <param name="versionrewrite-pattern">v(.*)</param> @@ -16,7 +16,7 @@ <param name="compression">gz</param> </service> <service name="go_modules" mode="disabled"> - <param name="archive">cli-2.20.0.tar.gz</param> + <param name="archive">cli-2.20.2.tar.gz</param> </service> </services> ++++++ cli-2.20.0.tar.gz -> cli-2.20.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/.github/SECURITY.md new/cli-2.20.2/.github/SECURITY.md --- old/cli-2.20.0/.github/SECURITY.md 2022-11-08 21:54:07.000000000 +0100 +++ new/cli-2.20.2/.github/SECURITY.md 2022-11-15 10:40:30.000000000 +0100 @@ -1,3 +1,14 @@ -If you discover a security issue in this repository, please submit it through the [GitHub Security Bug Bounty](https://hackerone.com/github). +GitHub takes the security of our software products and services seriously, including the open source code repositories managed through our GitHub organizations, such as [cli](https://github.com/cli). + +If you believe you have found a security vulnerability in GitHub CLI, you can report it to us in one of two ways: + +* Report it to this repository directly using [private vulnerability reporting][]. Such reports are not eligible for a bounty reward. + +* Submit the report through [HackerOne][] to be eligible for a bounty reward. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** Thanks for helping make GitHub safe for everyone. + + [private vulnerability reporting]: https://github.com/cli/cli/security/advisories + [HackerOne]: https://hackerone.com/github diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/.github/workflows/releases.yml new/cli-2.20.2/.github/workflows/releases.yml --- old/cli-2.20.0/.github/workflows/releases.yml 2022-11-08 21:54:07.000000000 +0100 +++ new/cli-2.20.2/.github/workflows/releases.yml 2022-11-15 10:40:30.000000000 +0100 @@ -15,6 +15,8 @@ steps: - name: Checkout uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Set up Go 1.18 uses: actions/setup-go@v3 with: @@ -41,7 +43,7 @@ - name: Run GoReleaser uses: goreleaser/goreleaser-action@v3 with: - version: v0.174.1 + version: v1.12.3 args: release --release-notes=CHANGELOG.md env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/.goreleaser.yml new/cli-2.20.2/.goreleaser.yml --- old/cli-2.20.0/.goreleaser.yml 2022-11-08 21:54:07.000000000 +0100 +++ new/cli-2.20.2/.goreleaser.yml 2022-11-15 10:40:30.000000000 +0100 @@ -60,7 +60,7 @@ - license: MIT maintainer: GitHub homepage: https://github.com/cli/cli - bindir: /usr/bin + bindir: /usr dependencies: - git description: GitHubâs official command line tool. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/git/client.go new/cli-2.20.2/git/client.go --- old/cli-2.20.0/git/client.go 2022-11-08 21:54:07.000000000 +0100 +++ new/cli-2.20.2/git/client.go 2022-11-15 10:40:30.000000000 +0100 @@ -32,7 +32,7 @@ mu sync.Mutex } -func (c *Client) Command(ctx context.Context, args ...string) (*gitCommand, error) { +func (c *Client) Command(ctx context.Context, args ...string) (*Command, error) { if c.RepoDir != "" { args = append([]string{"-C", c.RepoDir}, args...) } @@ -53,12 +53,12 @@ cmd.Stderr = c.Stderr cmd.Stdin = c.Stdin cmd.Stdout = c.Stdout - return &gitCommand{cmd}, nil + return &Command{cmd}, nil } // AuthenticatedCommand is a wrapper around Command that included configuration to use gh // as the credential helper for git. -func (c *Client) AuthenticatedCommand(ctx context.Context, args ...string) (*gitCommand, error) { +func (c *Client) AuthenticatedCommand(ctx context.Context, args ...string) (*Command, error) { preArgs := []string{"-c", "credential.helper="} if c.GhPath == "" { // Assumes that gh is in PATH. @@ -414,7 +414,10 @@ } func (c *Client) Pull(ctx context.Context, remote, branch string, mods ...CommandModifier) error { - args := []string{"pull", "--ff-only", remote, branch} + args := []string{"pull", "--ff-only"} + if remote != "" && branch != "" { + args = append(args, remote, branch) + } // TODO: Use AuthenticatedCommand cmd, err := c.Command(ctx, args...) if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/git/command.go new/cli-2.20.2/git/command.go --- old/cli-2.20.0/git/command.go 2022-11-08 21:54:07.000000000 +0100 +++ new/cli-2.20.2/git/command.go 2022-11-15 10:40:30.000000000 +0100 @@ -12,11 +12,11 @@ type commandCtx = func(ctx context.Context, name string, args ...string) *exec.Cmd -type gitCommand struct { +type Command struct { *exec.Cmd } -func (gc *gitCommand) Run() error { +func (gc *Command) Run() error { stderr := &bytes.Buffer{} if gc.Cmd.Stderr == nil { gc.Cmd.Stderr = stderr @@ -35,7 +35,7 @@ return nil } -func (gc *gitCommand) Output() ([]byte, error) { +func (gc *Command) Output() ([]byte, error) { gc.Stdout = nil gc.Stderr = nil // This is a hack in order to not break the hundreds of @@ -53,7 +53,7 @@ return out, err } -func (gc *gitCommand) setRepoDir(repoDir string) { +func (gc *Command) setRepoDir(repoDir string) { for i, arg := range gc.Args { if arg == "-C" { gc.Args[i+1] = repoDir @@ -73,28 +73,28 @@ } // Allow individual commands to be modified from the default client options. -type CommandModifier func(*gitCommand) +type CommandModifier func(*Command) func WithStderr(stderr io.Writer) CommandModifier { - return func(gc *gitCommand) { + return func(gc *Command) { gc.Stderr = stderr } } func WithStdout(stdout io.Writer) CommandModifier { - return func(gc *gitCommand) { + return func(gc *Command) { gc.Stdout = stdout } } func WithStdin(stdin io.Reader) CommandModifier { - return func(gc *gitCommand) { + return func(gc *Command) { gc.Stdin = stdin } } func WithRepoDir(repoDir string) CommandModifier { - return func(gc *gitCommand) { + return func(gc *Command) { gc.setRepoDir(repoDir) } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/pkg/cmd/extension/git.go new/cli-2.20.2/pkg/cmd/extension/git.go --- old/cli-2.20.0/pkg/cmd/extension/git.go 1970-01-01 01:00:00.000000000 +0100 +++ new/cli-2.20.2/pkg/cmd/extension/git.go 2022-11-15 10:40:30.000000000 +0100 @@ -0,0 +1,67 @@ +package extension + +import ( + "context" + + "github.com/cli/cli/v2/git" +) + +type gitClient interface { + CheckoutBranch(branch string) error + Clone(cloneURL string, args []string) (string, error) + CommandOutput(args []string) ([]byte, error) + Config(name string) (string, error) + Fetch(remote string, refspec string) error + ForRepo(repoDir string) gitClient + Pull(remote, branch string) error + Remotes() (git.RemoteSet, error) +} + +type gitExecuter struct { + client *git.Client +} + +func (g *gitExecuter) CheckoutBranch(branch string) error { + return g.client.CheckoutBranch(context.Background(), branch) +} + +func (g *gitExecuter) Clone(cloneURL string, cloneArgs []string) (string, error) { + return g.client.Clone(context.Background(), cloneURL, cloneArgs) +} + +func (g *gitExecuter) CommandOutput(args []string) ([]byte, error) { + cmd, err := g.client.Command(context.Background(), args...) + if err != nil { + return nil, err + } + return cmd.Output() +} + +func (g *gitExecuter) Config(name string) (string, error) { + return g.client.Config(context.Background(), name) +} + +func (g *gitExecuter) Fetch(remote string, refspec string) error { + return g.client.Fetch(context.Background(), remote, refspec) +} + +func (g *gitExecuter) ForRepo(repoDir string) gitClient { + return &gitExecuter{ + client: &git.Client{ + GhPath: g.client.GhPath, + RepoDir: repoDir, + GitPath: g.client.GitPath, + Stderr: g.client.Stderr, + Stdin: g.client.Stdin, + Stdout: g.client.Stdout, + }, + } +} + +func (g *gitExecuter) Pull(remote, branch string) error { + return g.client.Pull(context.Background(), remote, branch) +} + +func (g *gitExecuter) Remotes() (git.RemoteSet, error) { + return g.client.Remotes(context.Background()) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/pkg/cmd/extension/manager.go new/cli-2.20.2/pkg/cmd/extension/manager.go --- old/cli-2.20.0/pkg/cmd/extension/manager.go 2022-11-08 21:54:07.000000000 +0100 +++ new/cli-2.20.2/pkg/cmd/extension/manager.go 2022-11-15 10:40:30.000000000 +0100 @@ -2,7 +2,6 @@ import ( "bytes" - "context" _ "embed" "errors" "fmt" @@ -35,12 +34,13 @@ newCommand func(string, ...string) *exec.Cmd platform func() (string, string) client *http.Client + gitClient gitClient config config.Config io *iostreams.IOStreams dryRunMode bool } -func NewManager(ios *iostreams.IOStreams) *Manager { +func NewManager(ios *iostreams.IOStreams, gc *git.Client) *Manager { return &Manager{ dataDir: config.DataDir, lookPath: safeexec.LookPath, @@ -53,7 +53,8 @@ } return fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH), ext }, - io: ios, + io: ios, + gitClient: &gitExecuter{client: gc}, } } @@ -231,15 +232,9 @@ // getCurrentVersion determines the current version for non-local git extensions. func (m *Manager) getCurrentVersion(extension string) string { - gitExe, err := m.lookPath("git") - if err != nil { - return "" - } - dir := m.installDir() - gitDir := "--git-dir=" + filepath.Join(dir, extension, ".git") - cmd := m.newCommand(gitExe, gitDir, "rev-parse", "HEAD") - - localSha, err := cmd.Output() + dir := filepath.Join(m.installDir(), extension) + scopedClient := m.gitClient.ForRepo(dir) + localSha, err := scopedClient.CommandOutput([]string{"rev-parse", "HEAD"}) if err != nil { return "" } @@ -248,14 +243,9 @@ // getRemoteUrl determines the remote URL for non-local git extensions. func (m *Manager) getRemoteUrl(extension string) string { - gitExe, err := m.lookPath("git") - if err != nil { - return "" - } - dir := m.installDir() - gitDir := "--git-dir=" + filepath.Join(dir, extension, ".git") - cmd := m.newCommand(gitExe, gitDir, "config", "remote.origin.url") - url, err := cmd.Output() + dir := filepath.Join(m.installDir(), extension) + scopedClient := m.gitClient.ForRepo(dir) + url, err := scopedClient.Config("remote.origin.url") if err != nil { return "" } @@ -301,14 +291,9 @@ } return r.Tag, nil } else { - gitExe, err := m.lookPath("git") - if err != nil { - return "", err - } extDir := filepath.Dir(ext.path) - gitDir := "--git-dir=" + filepath.Join(extDir, ".git") - cmd := m.newCommand(gitExe, gitDir, "ls-remote", "origin", "HEAD") - lsRemote, err := cmd.Output() + scopedClient := m.gitClient.ForRepo(extDir) + lsRemote, err := scopedClient.CommandOutput([]string{"ls-remote", "origin", "HEAD"}) if err != nil { return "", err } @@ -469,13 +454,9 @@ protocol, _ := m.config.GetOrDefault(repo.RepoHost(), "git_protocol") cloneURL := ghrepo.FormatRemoteURL(repo, protocol) - exe, err := m.lookPath("git") - if err != nil { - return err - } - var commitSHA string if target != "" { + var err error commitSHA, err = fetchCommitSHA(m.client, repo, target) if err != nil { return err @@ -485,20 +466,17 @@ name := strings.TrimSuffix(path.Base(cloneURL), ".git") targetDir := filepath.Join(m.installDir(), name) - externalCmd := m.newCommand(exe, "clone", cloneURL, targetDir) - externalCmd.Stdout = stdout - externalCmd.Stderr = stderr - if err := externalCmd.Run(); err != nil { + _, err := m.gitClient.Clone(cloneURL, []string{targetDir}) + if err != nil { return err } if commitSHA == "" { return nil } - checkoutCmd := m.newCommand(exe, "-C", targetDir, "checkout", commitSHA) - checkoutCmd.Stdout = stdout - checkoutCmd.Stderr = stderr - if err := checkoutCmd.Run(); err != nil { + scopedClient := m.gitClient.ForRepo(targetDir) + err = scopedClient.CheckoutBranch(commitSHA) + if err != nil { return err } @@ -587,7 +565,7 @@ } else { // Check if git extension has changed to a binary extension var isBin bool - repo, repoErr := repoFromPath(filepath.Join(ext.Path(), "..")) + repo, repoErr := repoFromPath(m.gitClient, filepath.Join(ext.Path(), "..")) if repoErr == nil { isBin, _ = isBinExtension(m.client, repo) } @@ -603,21 +581,22 @@ } func (m *Manager) upgradeGitExtension(ext Extension, force bool) error { - exe, err := m.lookPath("git") - if err != nil { - return err - } - dir := filepath.Dir(ext.path) if m.dryRunMode { return nil } + dir := filepath.Dir(ext.path) + scopedClient := m.gitClient.ForRepo(dir) if force { - if err := m.newCommand(exe, "-C", dir, "fetch", "origin", "HEAD").Run(); err != nil { + err := scopedClient.Fetch("origin", "HEAD") + if err != nil { return err } - return m.newCommand(exe, "-C", dir, "reset", "--hard", "origin/HEAD").Run() + + _, err = scopedClient.CommandOutput([]string{"reset", "--hard", "origin/HEAD"}) + return err } - return m.newCommand(exe, "-C", dir, "pull", "--ff-only").Run() + + return scopedClient.Pull("", "") } func (m *Manager) upgradeBinExtension(ext Extension) error { @@ -659,19 +638,14 @@ var buildScript []byte func (m *Manager) Create(name string, tmplType extensions.ExtTemplateType) error { - exe, err := m.lookPath("git") - if err != nil { - return err - } - - if err := m.newCommand(exe, "init", "--quiet", name).Run(); err != nil { + if _, err := m.gitClient.CommandOutput([]string{"init", "--quiet", name}); err != nil { return err } if tmplType == extensions.GoBinTemplateType { - return m.goBinScaffolding(exe, name) + return m.goBinScaffolding(name) } else if tmplType == extensions.OtherBinTemplateType { - return m.otherBinScaffolding(exe, name) + return m.otherBinScaffolding(name) } script := fmt.Sprintf(scriptTmpl, name) @@ -679,10 +653,12 @@ return err } - return m.newCommand(exe, "-C", name, "add", name, "--chmod=+x").Run() + scopedClient := m.gitClient.ForRepo(name) + _, err := scopedClient.CommandOutput([]string{"add", name, "--chmod=+x"}) + return err } -func (m *Manager) otherBinScaffolding(gitExe, name string) error { +func (m *Manager) otherBinScaffolding(name string) error { if err := writeFile(filepath.Join(name, ".github", "workflows", "release.yml"), otherBinWorkflow, 0644); err != nil { return err } @@ -690,13 +666,17 @@ if err := writeFile(filepath.Join(name, buildScriptPath), buildScript, 0755); err != nil { return err } - if err := m.newCommand(gitExe, "-C", name, "add", buildScriptPath, "--chmod=+x").Run(); err != nil { + + scopedClient := m.gitClient.ForRepo(name) + if _, err := scopedClient.CommandOutput([]string{"add", buildScriptPath, "--chmod=+x"}); err != nil { return err } - return m.newCommand(gitExe, "-C", name, "add", ".").Run() + + _, err := scopedClient.CommandOutput([]string{"add", "."}) + return err } -func (m *Manager) goBinScaffolding(gitExe, name string) error { +func (m *Manager) goBinScaffolding(name string) error { goExe, err := m.lookPath("go") if err != nil { return fmt.Errorf("go is required for creating Go extensions: %w", err) @@ -737,7 +717,9 @@ } } - return m.newCommand(gitExe, "-C", name, "add", ".").Run() + scopedClient := m.gitClient.ForRepo(name) + _, err = scopedClient.CommandOutput([]string{"add", "."}) + return err } func isSymlink(m os.FileMode) bool { @@ -789,9 +771,9 @@ return } -func repoFromPath(path string) (ghrepo.Interface, error) { - gitClient := &git.Client{RepoDir: path} - remotes, err := gitClient.Remotes(context.Background()) +func repoFromPath(gitClient gitClient, path string) (ghrepo.Interface, error) { + scopedClient := gitClient.ForRepo(path) + remotes, err := scopedClient.Remotes() if err != nil { return nil, err } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/pkg/cmd/extension/manager_test.go new/cli-2.20.2/pkg/cmd/extension/manager_test.go --- old/cli-2.20.0/pkg/cmd/extension/manager_test.go 2022-11-08 21:54:07.000000000 +0100 +++ new/cli-2.20.2/pkg/cmd/extension/manager_test.go 2022-11-15 10:40:30.000000000 +0100 @@ -9,10 +9,10 @@ "path/filepath" "runtime" "sort" - "strings" "testing" "github.com/MakeNowJust/heredoc" + "github.com/cli/cli/v2/git" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/internal/run" @@ -29,15 +29,6 @@ return } if err := func(args []string) error { - // git init should create the directory named by argument - if len(args) > 2 && strings.HasPrefix(strings.Join(args, " "), "git init") { - dir := args[len(args)-1] - if !strings.HasPrefix(dir, "-") { - if err := os.MkdirAll(dir, 0755); err != nil { - return err - } - } - } fmt.Fprintf(os.Stdout, "%v\n", args) return nil }(os.Args[3:]); err != nil { @@ -47,7 +38,7 @@ os.Exit(0) } -func newTestManager(dir string, client *http.Client, ios *iostreams.IOStreams) *Manager { +func newTestManager(dir string, client *http.Client, gitClient gitClient, ios *iostreams.IOStreams) *Manager { return &Manager{ dataDir: func() string { return dir }, lookPath: func(exe string) (string, error) { return exe, nil }, @@ -62,9 +53,10 @@ cmd.Env = []string{"GH_WANT_HELPER_PROCESS=1"} return cmd }, - config: config.NewBlankConfig(), - io: ios, - client: client, + config: config.NewBlankConfig(), + io: ios, + client: client, + gitClient: gitClient, platform: func() (string, string) { return "windows-amd64", ".exe" }, @@ -85,12 +77,26 @@ Tag: "v1.0.1", })) - m := newTestManager(tempDir, nil, nil) + dirOne := filepath.Join(tempDir, "extensions", "gh-hello") + dirTwo := filepath.Join(tempDir, "extensions", "gh-two") + gc, gcOne, gcTwo := &mockGitClient{}, &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", dirOne).Return(gcOne).Twice() + gc.On("ForRepo", dirTwo).Return(gcTwo).Twice() + gcOne.On("Config", "remote.origin.url").Return("", nil).Once() + gcTwo.On("Config", "remote.origin.url").Return("", nil).Once() + gcOne.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + gcTwo.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + + m := newTestManager(tempDir, nil, gc, nil) exts := m.List() + assert.Equal(t, 3, len(exts)) assert.Equal(t, "bin-ext", exts[0].Name()) assert.Equal(t, "hello", exts[1].Name()) assert.Equal(t, "two", exts[2].Name()) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) + gcTwo.AssertExpectations(t) } func TestManager_list_includeMetadata(t *testing.T) { @@ -122,7 +128,7 @@ }, })) - m := newTestManager(tempDir, &client, nil) + m := newTestManager(tempDir, &client, nil, nil) exts, err := m.list(true) assert.NoError(t, err) @@ -134,10 +140,16 @@ func TestManager_Dispatch(t *testing.T) { tempDir := t.TempDir() + extDir := filepath.Join(tempDir, "extensions", "gh-hello") extPath := filepath.Join(tempDir, "extensions", "gh-hello", "gh-hello") assert.NoError(t, stubExtension(extPath)) - m := newTestManager(tempDir, nil, nil) + gc, gcOne := &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", extDir).Return(gcOne).Twice() + gcOne.On("Config", "remote.origin.url").Return("", nil).Once() + gcOne.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + + m := newTestManager(tempDir, nil, gc, nil) stdout := &bytes.Buffer{} stderr := &bytes.Buffer{} @@ -151,6 +163,9 @@ assert.Equal(t, fmt.Sprintf("[%s one two]\n", extPath), stdout.String()) } assert.Equal(t, "", stderr.String()) + + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) } func TestManager_Dispatch_binary(t *testing.T) { @@ -165,7 +180,7 @@ } assert.NoError(t, stubBinaryExtension(extPath, bm)) - m := newTestManager(tempDir, nil, nil) + m := newTestManager(tempDir, nil, nil, nil) stdout := &bytes.Buffer{} stderr := &bytes.Buffer{} @@ -182,7 +197,7 @@ assert.NoError(t, stubExtension(filepath.Join(tempDir, "extensions", "gh-hello", "gh-hello"))) assert.NoError(t, stubExtension(filepath.Join(tempDir, "extensions", "gh-two", "gh-two"))) - m := newTestManager(tempDir, nil, nil) + m := newTestManager(tempDir, nil, nil, nil) err := m.Remove("hello") assert.NoError(t, err) @@ -195,7 +210,7 @@ func TestManager_Upgrade_NoExtensions(t *testing.T) { tempDir := t.TempDir() ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, nil, ios) + m := newTestManager(tempDir, nil, nil, ios) err := m.Upgrade("", false) assert.EqualError(t, err, "no extensions installed") assert.Equal(t, "", stdout.String()) @@ -204,22 +219,42 @@ func TestManager_Upgrade_NoMatchingExtension(t *testing.T) { tempDir := t.TempDir() + extDir := filepath.Join(tempDir, "extensions", "gh-hello") assert.NoError(t, stubExtension(filepath.Join(tempDir, "extensions", "gh-hello", "gh-hello"))) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, nil, ios) + gc, gcOne := &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", extDir).Return(gcOne).Twice() + gcOne.On("Config", "remote.origin.url").Return("", nil).Once() + gcOne.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + m := newTestManager(tempDir, nil, gc, ios) err := m.Upgrade("invalid", false) assert.EqualError(t, err, `no extension matched "invalid"`) assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) } func TestManager_UpgradeExtensions(t *testing.T) { tempDir := t.TempDir() + dirOne := filepath.Join(tempDir, "extensions", "gh-hello") + dirTwo := filepath.Join(tempDir, "extensions", "gh-two") assert.NoError(t, stubExtension(filepath.Join(tempDir, "extensions", "gh-hello", "gh-hello"))) assert.NoError(t, stubExtension(filepath.Join(tempDir, "extensions", "gh-two", "gh-two"))) assert.NoError(t, stubLocalExtension(tempDir, filepath.Join(tempDir, "extensions", "gh-local", "gh-local"))) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, nil, ios) + gc, gcOne, gcTwo := &mockGitClient{}, &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", dirOne).Return(gcOne).Times(4) + gc.On("ForRepo", dirTwo).Return(gcTwo).Times(4) + gcOne.On("Config", "remote.origin.url").Return("", nil).Once() + gcTwo.On("Config", "remote.origin.url").Return("", nil).Once() + gcOne.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + gcTwo.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + gcOne.On("Remotes").Return(nil, nil).Once() + gcTwo.On("Remotes").Return(nil, nil).Once() + gcOne.On("Pull", "", "").Return(nil).Once() + gcTwo.On("Pull", "", "").Return(nil).Once() + m := newTestManager(tempDir, nil, gc, ios) exts, err := m.list(false) assert.NoError(t, err) assert.Equal(t, 3, len(exts)) @@ -229,27 +264,37 @@ } err = m.upgradeExtensions(exts, false) assert.NoError(t, err) - assert.Equal(t, heredoc.Docf( + assert.Equal(t, heredoc.Doc( ` - [hello]: [git -C %s pull --ff-only] - upgraded from old vers to new vers + [hello]: upgraded from old vers to new vers [local]: local extensions can not be upgraded - [two]: [git -C %s pull --ff-only] - upgraded from old vers to new vers + [two]: upgraded from old vers to new vers `, - filepath.Join(tempDir, "extensions", "gh-hello"), - filepath.Join(tempDir, "extensions", "gh-two"), ), stdout.String()) assert.Equal(t, "", stderr.String()) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) + gcTwo.AssertExpectations(t) } func TestManager_UpgradeExtensions_DryRun(t *testing.T) { tempDir := t.TempDir() + dirOne := filepath.Join(tempDir, "extensions", "gh-hello") + dirTwo := filepath.Join(tempDir, "extensions", "gh-two") assert.NoError(t, stubExtension(filepath.Join(tempDir, "extensions", "gh-hello", "gh-hello"))) assert.NoError(t, stubExtension(filepath.Join(tempDir, "extensions", "gh-two", "gh-two"))) assert.NoError(t, stubLocalExtension(tempDir, filepath.Join(tempDir, "extensions", "gh-local", "gh-local"))) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, nil, ios) + gc, gcOne, gcTwo := &mockGitClient{}, &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", dirOne).Return(gcOne).Times(3) + gc.On("ForRepo", dirTwo).Return(gcTwo).Times(3) + gcOne.On("Config", "remote.origin.url").Return("", nil).Once() + gcTwo.On("Config", "remote.origin.url").Return("", nil).Once() + gcOne.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + gcTwo.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + gcOne.On("Remotes").Return(nil, nil).Once() + gcTwo.On("Remotes").Return(nil, nil).Once() + m := newTestManager(tempDir, nil, gc, ios) m.EnableDryRunMode() exts, err := m.list(false) assert.NoError(t, err) @@ -268,6 +313,9 @@ `, ), stdout.String()) assert.Equal(t, "", stderr.String()) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) + gcTwo.AssertExpectations(t) } func TestManager_UpgradeExtension_LocalExtension(t *testing.T) { @@ -275,7 +323,7 @@ assert.NoError(t, stubLocalExtension(tempDir, filepath.Join(tempDir, "extensions", "gh-local", "gh-local"))) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, nil, ios) + m := newTestManager(tempDir, nil, nil, ios) exts, err := m.list(false) assert.NoError(t, err) assert.Equal(t, 1, len(exts)) @@ -290,7 +338,7 @@ assert.NoError(t, stubLocalExtension(tempDir, filepath.Join(tempDir, "extensions", "gh-local", "gh-local"))) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, nil, ios) + m := newTestManager(tempDir, nil, nil, ios) m.EnableDryRunMode() exts, err := m.list(false) assert.NoError(t, err) @@ -303,9 +351,16 @@ func TestManager_UpgradeExtension_GitExtension(t *testing.T) { tempDir := t.TempDir() + extensionDir := filepath.Join(tempDir, "extensions", "gh-remote") assert.NoError(t, stubExtension(filepath.Join(tempDir, "extensions", "gh-remote", "gh-remote"))) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, nil, ios) + gc, gcOne := &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", extensionDir).Return(gcOne).Times(4) + gcOne.On("Config", "remote.origin.url").Return("", nil).Once() + gcOne.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + gcOne.On("Remotes").Return(nil, nil).Once() + gcOne.On("Pull", "", "").Return(nil).Once() + m := newTestManager(tempDir, nil, gc, ios) exts, err := m.list(false) assert.NoError(t, err) assert.Equal(t, 1, len(exts)) @@ -314,20 +369,23 @@ ext.latestVersion = "new version" err = m.upgradeExtension(ext, false) assert.NoError(t, err) - assert.Equal(t, heredoc.Docf( - ` - [git -C %s pull --ff-only] - `, - filepath.Join(tempDir, "extensions", "gh-remote"), - ), stdout.String()) + assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) } func TestManager_UpgradeExtension_GitExtension_DryRun(t *testing.T) { tempDir := t.TempDir() + extDir := filepath.Join(tempDir, "extensions", "gh-remote") assert.NoError(t, stubExtension(filepath.Join(tempDir, "extensions", "gh-remote", "gh-remote"))) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, nil, ios) + gc, gcOne := &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", extDir).Return(gcOne).Times(3) + gcOne.On("Config", "remote.origin.url").Return("", nil).Once() + gcOne.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + gcOne.On("Remotes").Return(nil, nil).Once() + m := newTestManager(tempDir, nil, gc, ios) m.EnableDryRunMode() exts, err := m.list(false) assert.NoError(t, err) @@ -339,6 +397,8 @@ assert.NoError(t, err) assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) } func TestManager_UpgradeExtension_GitExtension_Force(t *testing.T) { @@ -346,7 +406,14 @@ extensionDir := filepath.Join(tempDir, "extensions", "gh-remote") assert.NoError(t, stubExtension(filepath.Join(tempDir, "extensions", "gh-remote", "gh-remote"))) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, nil, ios) + gc, gcOne := &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", extensionDir).Return(gcOne).Times(4) + gcOne.On("Config", "remote.origin.url").Return("", nil).Once() + gcOne.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + gcOne.On("Remotes").Return(nil, nil).Once() + gcOne.On("Fetch", "origin", "HEAD").Return(nil).Once() + gcOne.On("CommandOutput", []string{"reset", "--hard", "origin/HEAD"}).Return("", nil).Once() + m := newTestManager(tempDir, nil, gc, ios) exts, err := m.list(false) assert.NoError(t, err) assert.Equal(t, 1, len(exts)) @@ -355,14 +422,10 @@ ext.latestVersion = "new version" err = m.upgradeExtension(ext, true) assert.NoError(t, err) - assert.Equal(t, heredoc.Docf( - ` - [git -C %[1]s fetch origin HEAD] - [git -C %[1]s reset --hard origin/HEAD] - `, - extensionDir, - ), stdout.String()) + assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) } func TestManager_MigrateToBinaryExtension(t *testing.T) { @@ -373,7 +436,8 @@ reg := httpmock.Registry{} defer reg.Verify(t) client := http.Client{Transport: ®} - m := newTestManager(tempDir, &client, ios) + gc := &gitExecuter{client: &git.Client{}} + m := newTestManager(tempDir, &client, gc, ios) exts, err := m.list(false) assert.NoError(t, err) assert.Equal(t, 1, len(exts)) @@ -458,7 +522,7 @@ })) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, &http.Client{Transport: ®}, ios) + m := newTestManager(tempDir, &http.Client{Transport: ®}, nil, ios) reg.Register( httpmock.REST("GET", "api/v3/repos/owner/gh-bin-ext/releases/latest"), httpmock.JSONResponse( @@ -523,7 +587,7 @@ })) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, &http.Client{Transport: ®}, ios) + m := newTestManager(tempDir, &http.Client{Transport: ®}, nil, ios) reg.Register( httpmock.REST("GET", "api/v3/repos/owner/gh-bin-ext/releases/latest"), httpmock.JSONResponse( @@ -585,7 +649,7 @@ })) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, &http.Client{Transport: ®}, ios) + m := newTestManager(tempDir, &http.Client{Transport: ®}, nil, ios) m.EnableDryRunMode() reg.Register( httpmock.REST("GET", "api/v3/repos/owner/gh-bin-ext/releases/latest"), @@ -638,7 +702,7 @@ })) ios, _, _, _ := iostreams.Test() - m := newTestManager(tempDir, nil, ios) + m := newTestManager(tempDir, nil, nil, ios) exts, err := m.list(false) assert.Nil(t, err) assert.Equal(t, 1, len(exts)) @@ -655,8 +719,16 @@ assert.NoError(t, stubPinnedExtension(filepath.Join(extDir, "gh-remote"), "abcd1234")) ios, _, _, _ := iostreams.Test() - m := newTestManager(tempDir, nil, ios) + + gc, gcOne := &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", extDir).Return(gcOne).Twice() + gcOne.On("Config", "remote.origin.url").Return("", nil).Once() + gcOne.On("CommandOutput", []string{"rev-parse", "HEAD"}).Return("", nil).Once() + + m := newTestManager(tempDir, nil, gc, ios) + exts, err := m.list(false) + assert.NoError(t, err) assert.Equal(t, 1, len(exts)) ext := exts[0] @@ -666,6 +738,8 @@ err = m.upgradeExtension(ext, false) assert.NotNil(t, err) assert.Equal(t, err, pinnedExtensionUpgradeError) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) } func TestManager_Install_git(t *testing.T) { @@ -676,7 +750,12 @@ client := http.Client{Transport: ®} ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(tempDir, &client, ios) + + extensionDir := filepath.Join(tempDir, "extensions", "gh-some-ext") + gc := &mockGitClient{} + gc.On("Clone", "https://github.com/owner/gh-some-ext.git", []string{extensionDir}).Return("", nil).Once() + + m := newTestManager(tempDir, &client, gc, ios) reg.Register( httpmock.REST("GET", "repos/owner/gh-some-ext/releases/latest"), @@ -697,8 +776,9 @@ err := m.Install(repo, "") assert.NoError(t, err) - assert.Equal(t, fmt.Sprintf("[git clone https://github.com/owner/gh-some-ext.git %s]\n", filepath.Join(tempDir, "extensions", "gh-some-ext")), stdout.String()) + assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) + gc.AssertExpectations(t) } func TestManager_Install_git_pinned(t *testing.T) { @@ -708,8 +788,15 @@ defer reg.Verify(t) client := http.Client{Transport: ®} - ios, _, _, stderr := iostreams.Test() - m := newTestManager(tempDir, &client, ios) + ios, _, stdout, stderr := iostreams.Test() + + extensionDir := filepath.Join(tempDir, "extensions", "gh-cool-ext") + gc, gcOne := &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", extensionDir).Return(gcOne).Once() + gc.On("Clone", "https://github.com/owner/gh-cool-ext.git", []string{extensionDir}).Return("", nil).Once() + gcOne.On("CheckoutBranch", "abcd1234").Return(nil).Once() + + m := newTestManager(tempDir, &client, gc, ios) reg.Register( httpmock.REST("GET", "repos/owner/gh-cool-ext/releases/latest"), @@ -734,6 +821,9 @@ err := m.Install(repo, "some-ref") assert.NoError(t, err) assert.Equal(t, "", stderr.String()) + assert.Equal(t, "", stdout.String()) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) } func TestManager_Install_binary_pinned(t *testing.T) { @@ -772,7 +862,7 @@ ios, _, stdout, stderr := iostreams.Test() tempDir := t.TempDir() - m := newTestManager(tempDir, &http.Client{Transport: ®}, ios) + m := newTestManager(tempDir, &http.Client{Transport: ®}, nil, ios) err := m.Install(repo, "v1.6.3-pre") assert.NoError(t, err) @@ -836,7 +926,7 @@ ios, _, stdout, stderr := iostreams.Test() tempDir := t.TempDir() - m := newTestManager(tempDir, &client, ios) + m := newTestManager(tempDir, &client, nil, ios) err := m.Install(repo, "") assert.EqualError(t, err, "gh-bin-ext unsupported for windows-amd64. Open an issue: `gh issue create -R owner/gh-bin-ext -t'Support windows-amd64'`") @@ -881,7 +971,7 @@ ios, _, stdout, stderr := iostreams.Test() tempDir := t.TempDir() - m := newTestManager(tempDir, &http.Client{Transport: ®}, ios) + m := newTestManager(tempDir, &http.Client{Transport: ®}, nil, ios) err := m.Install(repo, "") assert.NoError(t, err) @@ -925,7 +1015,7 @@ ios, _, stdout, stderr := iostreams.Test() tempDir := t.TempDir() - m := newTestManager(tempDir, &http.Client{Transport: ®}, ios) + m := newTestManager(tempDir, &http.Client{Transport: ®}, nil, ios) if err := m.Install(repo, ""); err != repositoryNotFoundErr { t.Errorf("expected repositoryNotFoundErr, got: %v", err) @@ -937,24 +1027,35 @@ func TestManager_Create(t *testing.T) { chdirTemp(t) + err := os.MkdirAll("gh-test", 0755) + assert.NoError(t, err) + ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(".", nil, ios) - err := m.Create("gh-test", extensions.GitTemplateType) + gc, gcOne := &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", "gh-test").Return(gcOne).Once() + gc.On("CommandOutput", []string{"init", "--quiet", "gh-test"}).Return("", nil).Once() + gcOne.On("CommandOutput", []string{"add", "gh-test", "--chmod=+x"}).Return("", nil).Once() + + m := newTestManager(".", nil, gc, ios) + + err = m.Create("gh-test", extensions.GitTemplateType) assert.NoError(t, err) files, err := os.ReadDir("gh-test") assert.NoError(t, err) assert.Equal(t, []string{"gh-test"}, fileNames(files)) - assert.Equal(t, heredoc.Doc(` - [git init --quiet gh-test] - [git -C gh-test add gh-test --chmod=+x] - `), stdout.String()) + assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) } func TestManager_Create_go_binary(t *testing.T) { chdirTemp(t) + err := os.MkdirAll("gh-test", 0755) + assert.NoError(t, err) + reg := httpmock.Registry{} defer reg.Verify(t) reg.Register( @@ -962,9 +1063,15 @@ httpmock.StringResponse(`{"data":{"viewer":{"login":"jillv"}}}`)) ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(".", &http.Client{Transport: ®}, ios) - err := m.Create("gh-test", extensions.GoBinTemplateType) + gc, gcOne := &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", "gh-test").Return(gcOne).Once() + gc.On("CommandOutput", []string{"init", "--quiet", "gh-test"}).Return("", nil).Once() + gcOne.On("CommandOutput", []string{"add", "."}).Return("", nil).Once() + + m := newTestManager(".", &http.Client{Transport: ®}, gc, ios) + + err = m.Create("gh-test", extensions.GoBinTemplateType) require.NoError(t, err) files, err := os.ReadDir("gh-test") @@ -983,21 +1090,31 @@ assert.Equal(t, []string{"release.yml"}, fileNames(files)) assert.Equal(t, heredoc.Doc(` - [git init --quiet gh-test] [go mod init github.com/jillv/gh-test] [go mod tidy] [go build] - [git -C gh-test add .] `), stdout.String()) assert.Equal(t, "", stderr.String()) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) } func TestManager_Create_other_binary(t *testing.T) { chdirTemp(t) + err := os.MkdirAll("gh-test", 0755) + assert.NoError(t, err) + ios, _, stdout, stderr := iostreams.Test() - m := newTestManager(".", nil, ios) - err := m.Create("gh-test", extensions.OtherBinTemplateType) + gc, gcOne := &mockGitClient{}, &mockGitClient{} + gc.On("ForRepo", "gh-test").Return(gcOne).Once() + gc.On("CommandOutput", []string{"init", "--quiet", "gh-test"}).Return("", nil).Once() + gcOne.On("CommandOutput", []string{"add", filepath.Join("script", "build.sh"), "--chmod=+x"}).Return("", nil).Once() + gcOne.On("CommandOutput", []string{"add", "."}).Return("", nil).Once() + + m := newTestManager(".", nil, gc, ios) + + err = m.Create("gh-test", extensions.OtherBinTemplateType) assert.NoError(t, err) files, err := os.ReadDir("gh-test") @@ -1012,12 +1129,10 @@ assert.NoError(t, err) assert.Equal(t, []string{"build.sh"}, fileNames(files)) - assert.Equal(t, heredoc.Docf(` - [git init --quiet gh-test] - [git -C gh-test add %s --chmod=+x] - [git -C gh-test add .] - `, filepath.FromSlash("script/build.sh")), stdout.String()) + assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) + gc.AssertExpectations(t) + gcOne.AssertExpectations(t) } // chdirTemp changes the current working directory to a temporary directory for the duration of the test. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/pkg/cmd/extension/mocks.go new/cli-2.20.2/pkg/cmd/extension/mocks.go --- old/cli-2.20.0/pkg/cmd/extension/mocks.go 1970-01-01 01:00:00.000000000 +0100 +++ new/cli-2.20.2/pkg/cmd/extension/mocks.go 2022-11-15 10:40:30.000000000 +0100 @@ -0,0 +1,53 @@ +package extension + +import ( + "github.com/cli/cli/v2/git" + "github.com/stretchr/testify/mock" +) + +type mockGitClient struct { + mock.Mock +} + +func (g *mockGitClient) CheckoutBranch(branch string) error { + args := g.Called(branch) + return args.Error(0) +} + +func (g *mockGitClient) Clone(cloneURL string, cloneArgs []string) (string, error) { + args := g.Called(cloneURL, cloneArgs) + return args.String(0), args.Error(1) +} + +func (g *mockGitClient) CommandOutput(commandArgs []string) ([]byte, error) { + args := g.Called(commandArgs) + return []byte(args.String(0)), args.Error(1) +} + +func (g *mockGitClient) Config(name string) (string, error) { + args := g.Called(name) + return args.String(0), args.Error(1) +} + +func (g *mockGitClient) Fetch(remote string, refspec string) error { + args := g.Called(remote, refspec) + return args.Error(0) +} + +func (g *mockGitClient) ForRepo(repoDir string) gitClient { + args := g.Called(repoDir) + if v, ok := args.Get(0).(*mockGitClient); ok { + return v + } + return nil +} + +func (g *mockGitClient) Pull(remote, branch string) error { + args := g.Called(remote, branch) + return args.Error(0) +} + +func (g *mockGitClient) Remotes() (git.RemoteSet, error) { + args := g.Called() + return nil, args.Error(1) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/pkg/cmd/factory/default.go new/cli-2.20.2/pkg/cmd/factory/default.go --- old/cli-2.20.0/pkg/cmd/factory/default.go 2022-11-08 21:54:07.000000000 +0100 +++ new/cli-2.20.2/pkg/cmd/factory/default.go 2022-11-15 10:40:30.000000000 +0100 @@ -156,7 +156,7 @@ } func extensionManager(f *cmdutil.Factory) *extension.Manager { - em := extension.NewManager(f.IOStreams) + em := extension.NewManager(f.IOStreams, f.GitClient) cfg, err := f.Config() if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/pkg/cmd/repo/list/http.go new/cli-2.20.2/pkg/cmd/repo/list/http.go --- old/cli-2.20.0/pkg/cmd/repo/list/http.go 2022-11-08 21:54:07.000000000 +0100 +++ new/cli-2.20.2/pkg/cmd/repo/list/http.go 2022-11-15 10:40:30.000000000 +0100 @@ -80,7 +80,7 @@ query := fmt.Sprintf(`query RepositoryList(%s) { %s { login - repositories(first: $perPage, after: $endCursor, privacy: $privacy, isFork: $fork, affiliations: OWNER, orderBy: { field: PUSHED_AT, direction: DESC }) { + repositories(first: $perPage, after: $endCursor, privacy: $privacy, isFork: $fork, ownerAffiliations: OWNER, orderBy: { field: PUSHED_AT, direction: DESC }) { nodes{%s} totalCount pageInfo{hasNextPage,endCursor} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cli-2.20.0/pkg/iostreams/iostreams.go new/cli-2.20.2/pkg/iostreams/iostreams.go --- old/cli-2.20.0/pkg/iostreams/iostreams.go 2022-11-08 21:54:07.000000000 +0100 +++ new/cli-2.20.2/pkg/iostreams/iostreams.go 2022-11-15 10:40:30.000000000 +0100 @@ -341,7 +341,7 @@ } func (s *IOStreams) RefreshScreen() { - if s.stdoutIsTTY { + if s.IsStdoutTTY() { // Move cursor to 0,0 fmt.Fprint(s.Out, "\x1b[0;0H") // Clear from cursor to bottom of screen @@ -407,8 +407,9 @@ } stdoutIsTTY := io.IsStdoutTTY() + stderrIsTTY := io.IsStderrTTY() - if stdoutIsTTY && io.IsStderrTTY() { + if stdoutIsTTY && stderrIsTTY { io.progressIndicatorEnabled = true } ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/gh/vendor.tar.gz /work/SRC/openSUSE:Factory/.gh.new.1597/vendor.tar.gz differ: char 5, line 1