Use git client in extension manager (#6547)
This commit is contained in:
parent
30ad3f0fd1
commit
6bbfc5056d
7 changed files with 381 additions and 161 deletions
|
|
@ -32,7 +32,7 @@ type Client struct {
|
|||
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 @@ func (c *Client) Command(ctx context.Context, args ...string) (*gitCommand, erro
|
|||
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) Fetch(ctx context.Context, remote string, refspec string, mods
|
|||
}
|
||||
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ import (
|
|||
|
||||
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 @@ func (gc *gitCommand) Run() error {
|
|||
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 @@ func (gc *gitCommand) Output() ([]byte, error) {
|
|||
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 @@ func (gc *gitCommand) setRepoDir(repoDir string) {
|
|||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
67
pkg/cmd/extension/git.go
Normal file
67
pkg/cmd/extension/git.go
Normal file
|
|
@ -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())
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@ package extension
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
_ "embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -35,12 +34,13 @@ type Manager struct {
|
|||
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 @@ func NewManager(ios *iostreams.IOStreams) *Manager {
|
|||
}
|
||||
return fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH), ext
|
||||
},
|
||||
io: ios,
|
||||
io: ios,
|
||||
gitClient: &gitExecuter{client: gc},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -231,15 +232,9 @@ func (m *Manager) parseGitExtensionDir(fi fs.DirEntry) (Extension, error) {
|
|||
|
||||
// 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 @@ func (m *Manager) getCurrentVersion(extension string) string {
|
|||
|
||||
// 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 @@ func (m *Manager) getLatestVersion(ext Extension) (string, error) {
|
|||
}
|
||||
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 @@ func (m *Manager) installGit(repo ghrepo.Interface, target string, stdout, stder
|
|||
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 @@ func (m *Manager) installGit(repo ghrepo.Interface, target string, stdout, stder
|
|||
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 @@ func (m *Manager) upgradeExtension(ext Extension, force bool) error {
|
|||
} 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) upgradeExtension(ext Extension, force bool) error {
|
|||
}
|
||||
|
||||
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 scriptTmpl string
|
|||
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 @@ func (m *Manager) Create(name string, tmplType extensions.ExtTemplateType) error
|
|||
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 @@ func (m *Manager) otherBinScaffolding(gitExe, name string) error {
|
|||
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 @@ func (m *Manager) goBinScaffolding(gitExe, name string) error {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ func isBinExtension(client *http.Client, repo ghrepo.Interface) (isBin bool, err
|
|||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ import (
|
|||
"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 @@ func TestHelperProcess(t *testing.T) {
|
|||
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 @@ func TestHelperProcess(t *testing.T) {
|
|||
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 @@ func newTestManager(dir string, client *http.Client, ios *iostreams.IOStreams) *
|
|||
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 @@ func TestManager_List(t *testing.T) {
|
|||
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 @@ func TestManager_list_includeMetadata(t *testing.T) {
|
|||
},
|
||||
}))
|
||||
|
||||
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_list_includeMetadata(t *testing.T) {
|
|||
|
||||
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 @@ func TestManager_Dispatch(t *testing.T) {
|
|||
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 @@ func TestManager_Dispatch_binary(t *testing.T) {
|
|||
}
|
||||
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 @@ func TestManager_Remove(t *testing.T) {
|
|||
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_Remove(t *testing.T) {
|
|||
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_NoExtensions(t *testing.T) {
|
|||
|
||||
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 @@ func TestManager_UpgradeExtensions(t *testing.T) {
|
|||
}
|
||||
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 @@ func TestManager_UpgradeExtensions_DryRun(t *testing.T) {
|
|||
`,
|
||||
), 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 @@ func TestManager_UpgradeExtension_LocalExtension(t *testing.T) {
|
|||
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 @@ func TestManager_UpgradeExtension_LocalExtension_DryRun(t *testing.T) {
|
|||
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_LocalExtension_DryRun(t *testing.T) {
|
|||
|
||||
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 @@ func TestManager_UpgradeExtension_GitExtension(t *testing.T) {
|
|||
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 @@ func TestManager_UpgradeExtension_GitExtension_DryRun(t *testing.T) {
|
|||
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 @@ func TestManager_UpgradeExtension_GitExtension_Force(t *testing.T) {
|
|||
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 @@ func TestManager_UpgradeExtension_GitExtension_Force(t *testing.T) {
|
|||
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 @@ func TestManager_MigrateToBinaryExtension(t *testing.T) {
|
|||
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 @@ func TestManager_UpgradeExtension_BinaryExtension(t *testing.T) {
|
|||
}))
|
||||
|
||||
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 @@ func TestManager_UpgradeExtension_BinaryExtension_Pinned_Force(t *testing.T) {
|
|||
}))
|
||||
|
||||
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 @@ func TestManager_UpgradeExtension_BinaryExtension_DryRun(t *testing.T) {
|
|||
}))
|
||||
|
||||
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 @@ func TestManager_UpgradeExtension_BinaryExtension_Pinned(t *testing.T) {
|
|||
}))
|
||||
|
||||
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 @@ func TestManager_UpgradeExtenion_GitExtension_Pinned(t *testing.T) {
|
|||
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 @@ func TestManager_UpgradeExtenion_GitExtension_Pinned(t *testing.T) {
|
|||
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 @@ func TestManager_Install_git(t *testing.T) {
|
|||
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 @@ func TestManager_Install_git(t *testing.T) {
|
|||
|
||||
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 @@ func TestManager_Install_git_pinned(t *testing.T) {
|
|||
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 @@ func TestManager_Install_git_pinned(t *testing.T) {
|
|||
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 @@ func TestManager_Install_binary_pinned(t *testing.T) {
|
|||
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 @@ func TestManager_Install_binary_unsupported(t *testing.T) {
|
|||
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 @@ func TestManager_Install_binary(t *testing.T) {
|
|||
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 @@ func TestManager_repo_not_found(t *testing.T) {
|
|||
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_repo_not_found(t *testing.T) {
|
|||
|
||||
func TestManager_Create(t *testing.T) {
|
||||
chdirTemp(t)
|
||||
ios, _, stdout, stderr := iostreams.Test()
|
||||
m := newTestManager(".", nil, ios)
|
||||
err := os.MkdirAll("gh-test", 0755)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err := m.Create("gh-test", extensions.GitTemplateType)
|
||||
ios, _, stdout, stderr := iostreams.Test()
|
||||
|
||||
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 @@ func TestManager_Create_go_binary(t *testing.T) {
|
|||
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 @@ func TestManager_Create_go_binary(t *testing.T) {
|
|||
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)
|
||||
ios, _, stdout, stderr := iostreams.Test()
|
||||
m := newTestManager(".", nil, ios)
|
||||
err := os.MkdirAll("gh-test", 0755)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err := m.Create("gh-test", extensions.OtherBinTemplateType)
|
||||
ios, _, stdout, stderr := iostreams.Test()
|
||||
|
||||
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 @@ func TestManager_Create_other_binary(t *testing.T) {
|
|||
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.
|
||||
|
|
|
|||
53
pkg/cmd/extension/mocks.go
Normal file
53
pkg/cmd/extension/mocks.go
Normal file
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ func branchFunc(f *cmdutil.Factory) func() (string, error) {
|
|||
}
|
||||
|
||||
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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue