diff --git a/acceptance/testdata/repo/repo-rename-transfer-ownership.txtar b/acceptance/testdata/repo/repo-rename-transfer-ownership.txtar new file mode 100644 index 000000000..6b1a3e3fb --- /dev/null +++ b/acceptance/testdata/repo/repo-rename-transfer-ownership.txtar @@ -0,0 +1,9 @@ +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Attempt to rename the repo with a slash in the name +! exec gh repo rename $ORG/new-name --repo=$ORG/$SCRIPT_NAME-$RANDOM_STRING --yes +stderr 'New repository name cannot contain '/' character - to transfer a repository to a new owner, you must follow additional steps on GitHub.com. For more information on transferring repository ownership, see .' + +# Defer repo deletion +defer gh repo delete $ORG/$SCRIPT_NAME-$RANDOM_STRING --yes \ No newline at end of file diff --git a/pkg/cmd/extension/command.go b/pkg/cmd/extension/command.go index dad4021b6..93c385374 100644 --- a/pkg/cmd/extension/command.go +++ b/pkg/cmd/extension/command.go @@ -298,9 +298,18 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { Long: heredoc.Docf(` Install a GitHub CLI extension from a GitHub or local repository. - For GitHub repositories, the repository argument can be specified in %[1]sOWNER/REPO%[1]s format or as a full repository URL. + For GitHub repositories, the repository argument can be specified in + %[1]sOWNER/REPO%[1]s format or as a full repository URL. The URL format is useful when the repository is not hosted on github.com. + For remote repositories, the GitHub CLI first looks for the release artifacts assuming + that it's a binary extension i.e. prebuilt binaries provided as part of the release. + In the absence of a release, the repository itself is cloned assuming that it's a + script extension i.e. prebuilt executable or script exists on its root. + + The %[1]s--pin%[1]s flag may be used to specify a tag or commit for binary and script + extensions respectively, the latest version is used otherwise. + For local repositories, often used while developing extensions, use %[1]s.%[1]s as the value of the repository argument. Note the following: diff --git a/pkg/cmd/extension/manager.go b/pkg/cmd/extension/manager.go index c6947f479..b7f1f1c0c 100644 --- a/pkg/cmd/extension/manager.go +++ b/pkg/cmd/extension/manager.go @@ -268,7 +268,7 @@ func (m *Manager) Install(repo ghrepo.Interface, target string) error { return err } if !hs { - return errors.New("extension is not installable: missing executable") + return fmt.Errorf("extension is not installable: no usable release artifact or script found in %s", repo) } return m.installGit(repo, target) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 74523e2e7..e50095d76 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "strings" "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/api" @@ -124,6 +125,10 @@ func renameRun(opts *RenameOptions) error { } } + if strings.Contains(newRepoName, "/") { + return fmt.Errorf("New repository name cannot contain '/' character - to transfer a repository to a new owner, you must follow additional steps on GitHub.com. For more information on transferring repository ownership, see .") + } + if opts.DoConfirm { var confirmed bool if confirmed, err = opts.Prompter.Confirm(fmt.Sprintf( diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index da40e51b0..e33e14438 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -113,6 +113,8 @@ func TestRenameRun(t *testing.T) { promptStubs func(*prompter.MockPrompter) wantOut string tty bool + wantErr bool + errMsg string }{ { name: "none argument", @@ -217,6 +219,16 @@ func TestRenameRun(t *testing.T) { }, wantOut: "", }, + + { + name: "error on name with slash", + tty: true, + opts: RenameOptions{ + newRepoSelector: "org/new-name", + }, + wantErr: true, + errMsg: "New repository name cannot contain '/' character - to transfer a repository to a new owner, you must follow additional steps on GitHub.com. For more information on transferring repository ownership, see .", + }, } for _, tt := range testCases { @@ -268,6 +280,10 @@ func TestRenameRun(t *testing.T) { t.Run(tt.name, func(t *testing.T) { defer reg.Verify(t) err := renameRun(&tt.opts) + if tt.wantErr { + assert.EqualError(t, err, tt.errMsg) + return + } assert.NoError(t, err) assert.Equal(t, tt.wantOut, stdout.String()) })