From 5fad092b9e7f4b847a77dffe883d71e6310df416 Mon Sep 17 00:00:00 2001 From: Heath Stewart Date: Sun, 5 Sep 2021 01:01:58 -0700 Subject: [PATCH 001/253] Refactor Windows Installer setup Resolves #703 along with several other issues: * Build an x64 MSI for an x64 executable. This means the binary is installed to C:\Program Files, by default, rather than C:\Program Files (x86) without the ability to redirect it to 64-bit locations. * Environment change to PATH is not system-wide, which for a per-machine install it should be so all users who can access the executable have it in their PATH. * Environment change to PATH is not cleaned up when uninstalled. * RTF conversion of LICENSE was difficult to read. A simple conversion script is checked in to facilitate regenerating RTF from root LICENSE. --- .github/workflows/releases.yml | 14 +++----- build/windows/ConvertTo-Rtf.ps1 | 24 ++++++++++++++ build/windows/LICENSE.rtf | 23 +++++++++++++ build/windows/gh.wixproj | 35 ++++++++++++++++++++ build/windows/gh.wxs | 58 +++++++++++++++++++++++++++++++++ wix.json | 32 ------------------ 6 files changed, 144 insertions(+), 42 deletions(-) create mode 100644 build/windows/ConvertTo-Rtf.ps1 create mode 100644 build/windows/LICENSE.rtf create mode 100644 build/windows/gh.wixproj create mode 100644 build/windows/gh.wxs delete mode 100644 wix.json diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index 79e150113..cbba42cb9 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -123,23 +123,17 @@ jobs: unzip -o *.zip && rm -v *.zip env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} - - name: Install go-msi - run: choco install -y "go-msi" - name: Prepare PATH - shell: bash - run: | - echo "$WIX\\bin" >> $GITHUB_PATH - echo "C:\\Program Files\\go-msi" >> $GITHUB_PATH + uses: microsoft/setup-msbuild@v1.0.3 - name: Build MSI id: buildmsi shell: bash env: ZIP_FILE: ${{ steps.download_exe.outputs.zip }} run: | - mkdir -p build - msi="$(basename "$ZIP_FILE" ".zip").msi" - printf "::set-output name=msi::%s\n" "$msi" - go-msi make --msi "$PWD/$msi" --out "$PWD/build" --version "${GITHUB_REF#refs/tags/}" + name="$(basename "$ZIP_FILE" ".zip")" + printf "::set-output name=msi::%s\n" "$name.msi" + msbuild .\build\windows\gh.wixproj /p:SourceDir="$PWD" /p:OutputName="$name" /p:ProductVersion="${GITHUB_REF#refs/tags/}" - name: Obtain signing cert id: obtain_cert env: diff --git a/build/windows/ConvertTo-Rtf.ps1 b/build/windows/ConvertTo-Rtf.ps1 new file mode 100644 index 000000000..401951cc8 --- /dev/null +++ b/build/windows/ConvertTo-Rtf.ps1 @@ -0,0 +1,24 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory=$true, Position=0)] + [string] $Path, + + [Parameter(Mandatory=$true, Position=1)] + [string] $OutFile, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string] $FontFamily = 'Arial' +) + +$rtf = "{\rtf1\ansi\deff0{\fonttbl{\f0\fcharset0 $FontFamily;}}\pard\sa200\sl200\slmult1\fs20`n" +foreach ($line in (Get-Content $Path)) { + if (!$line) { + $rtf += "\par`n" + } else { + $rtf += "$line`n" + } +} +$rtf += '}' + +$rtf | Set-Content $OutFile \ No newline at end of file diff --git a/build/windows/LICENSE.rtf b/build/windows/LICENSE.rtf new file mode 100644 index 000000000..185063f24 --- /dev/null +++ b/build/windows/LICENSE.rtf @@ -0,0 +1,23 @@ +{\rtf1\ansi\deff0{\fonttbl{\f0\fcharset0 Arial;}}\pard\sa200\sl200\slmult1\fs20 +MIT License +\par +Copyright (c) 2019 GitHub Inc. +\par +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +\par +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +\par +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +} diff --git a/build/windows/gh.wixproj b/build/windows/gh.wixproj new file mode 100644 index 000000000..56a87fb66 --- /dev/null +++ b/build/windows/gh.wixproj @@ -0,0 +1,35 @@ + + + + Debug + x64 + 0.1.0 + $(MSBuildProjectName) + package + $(MSBuildProjectDirectory)\..\.. + $(RepoPath)\bin\$(Platform)\$(Configuration)\ + $(RepoPath)\bin\obj\$(Platform)\$(Configuration)\ + + $(DefineConstants); + ProductVersion=$(ProductVersion); + + false + $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets + + + + + + + + + + + + + + + + + + diff --git a/build/windows/gh.wxs b/build/windows/gh.wxs new file mode 100644 index 000000000..7d2f967d5 --- /dev/null +++ b/build/windows/gh.wxs @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wix.json b/wix.json deleted file mode 100644 index 6b2356ae3..000000000 --- a/wix.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "product": "GitHub CLI", - "company": "GitHub, Inc.", - "license": "LICENSE", - "upgrade-code": "7c0a5736-5b8e-4176-b350-613fa2d8a1b3", - "files": { - "guid": "6e6dcb19-3cf6-46d1-ac56-c6fb39485c9d", - "items": [ - "bin/gh.exe" - ] - }, - "env": { - "guid": "94faac3d-4478-431c-8497-fba55dcfb249", - "vars": [ - { - "name": "PATH", - "value": "[INSTALLDIR]", - "permanent": "yes", - "system": "no", - "action": "set", - "part": "last" - } - ] - }, - "shortcuts": {}, - "choco": { - "description": "Use GitHub from the CLI", - "project-url": "https://github.com/cli/cli", - "tags": "github cli git", - "license-url": "https://github.com/cli/cli/blob/trunk/LICENSE" - } -} From cb599af1a33789e2d6be93b4be6a93c428e4b4b0 Mon Sep 17 00:00:00 2001 From: Heath Stewart Date: Sun, 5 Sep 2021 09:15:36 -0700 Subject: [PATCH 002/253] Make sure correct step output is set Also simplifies directories for an always-release binary. --- .github/workflows/releases.yml | 2 +- build/windows/gh.wixproj | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index cbba42cb9..3acd23acd 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -133,7 +133,7 @@ jobs: run: | name="$(basename "$ZIP_FILE" ".zip")" printf "::set-output name=msi::%s\n" "$name.msi" - msbuild .\build\windows\gh.wixproj /p:SourceDir="$PWD" /p:OutputName="$name" /p:ProductVersion="${GITHUB_REF#refs/tags/}" + msbuild .\build\windows\gh.wixproj /p:SourceDir="$PWD" /p:OutputPath="$PWD" /p:OutputName="$name" /p:ProductVersion="${GITHUB_REF#refs/tags/}" - name: Obtain signing cert id: obtain_cert env: diff --git a/build/windows/gh.wixproj b/build/windows/gh.wixproj index 56a87fb66..db5f1b0c7 100644 --- a/build/windows/gh.wixproj +++ b/build/windows/gh.wixproj @@ -1,14 +1,14 @@ - Debug + Release x64 0.1.0 $(MSBuildProjectName) package - $(MSBuildProjectDirectory)\..\.. - $(RepoPath)\bin\$(Platform)\$(Configuration)\ - $(RepoPath)\bin\obj\$(Platform)\$(Configuration)\ + $([MSBuild]::NormalizeDirectory($(MSBuildProjectDirectory)\..\..)) + $(RepoPath)bin\$(Platform)\ + $(RepoPath)bin\obj\$(Platform)\ $(DefineConstants); ProductVersion=$(ProductVersion); @@ -31,5 +31,9 @@ + + + + From 2fa3de9ba49ca28223a5a01026ce81d8c87c42d6 Mon Sep 17 00:00:00 2001 From: Heath Stewart Date: Tue, 7 Sep 2021 23:02:59 -0700 Subject: [PATCH 003/253] Resolve PR feedback --- .github/workflows/releases.yml | 3 +-- build/windows/gh.wixproj | 1 + build/windows/gh.wxs | 30 +++++++++++++++++++++++++----- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index 3acd23acd..63a3891e6 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -132,8 +132,7 @@ jobs: ZIP_FILE: ${{ steps.download_exe.outputs.zip }} run: | name="$(basename "$ZIP_FILE" ".zip")" - printf "::set-output name=msi::%s\n" "$name.msi" - msbuild .\build\windows\gh.wixproj /p:SourceDir="$PWD" /p:OutputPath="$PWD" /p:OutputName="$name" /p:ProductVersion="${GITHUB_REF#refs/tags/}" + msbuild .\build\windows\gh.wixproj /p:SourceDir="$PWD" /p:OutputPath="$PWD" /p:OutputName="$name" /p:ProductVersion="${GITHUB_REF#refs/tags/v}" - name: Obtain signing cert id: obtain_cert env: diff --git a/build/windows/gh.wixproj b/build/windows/gh.wixproj index db5f1b0c7..5c355955d 100644 --- a/build/windows/gh.wixproj +++ b/build/windows/gh.wixproj @@ -13,6 +13,7 @@ $(DefineConstants); ProductVersion=$(ProductVersion); + ICE39 false $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets diff --git a/build/windows/gh.wxs b/build/windows/gh.wxs index 7d2f967d5..32eb9564b 100644 --- a/build/windows/gh.wxs +++ b/build/windows/gh.wxs @@ -5,11 +5,27 @@ - + + + + + + + + + + + + + + + + + - + @@ -21,7 +37,7 @@ - + @@ -35,6 +51,7 @@ + @@ -42,8 +59,11 @@ - - + + + + + From a6c7bd832694fd5ef7baa67ddba6cf1c5c657167 Mon Sep 17 00:00:00 2001 From: Heath Stewart Date: Sat, 18 Sep 2021 09:23:43 -0700 Subject: [PATCH 004/253] Resolve PR feedback * Removed license dialog * Removed RTF copy of license --- build/windows/ConvertTo-Rtf.ps1 | 24 --------------- build/windows/LICENSE.rtf | 23 -------------- build/windows/gh.wixproj | 4 +-- build/windows/gh.wxs | 5 ++- build/windows/ui.wxs | 54 +++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 53 deletions(-) delete mode 100644 build/windows/ConvertTo-Rtf.ps1 delete mode 100644 build/windows/LICENSE.rtf create mode 100644 build/windows/ui.wxs diff --git a/build/windows/ConvertTo-Rtf.ps1 b/build/windows/ConvertTo-Rtf.ps1 deleted file mode 100644 index 401951cc8..000000000 --- a/build/windows/ConvertTo-Rtf.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -[CmdletBinding()] -param ( - [Parameter(Mandatory=$true, Position=0)] - [string] $Path, - - [Parameter(Mandatory=$true, Position=1)] - [string] $OutFile, - - [Parameter()] - [ValidateNotNullOrEmpty()] - [string] $FontFamily = 'Arial' -) - -$rtf = "{\rtf1\ansi\deff0{\fonttbl{\f0\fcharset0 $FontFamily;}}\pard\sa200\sl200\slmult1\fs20`n" -foreach ($line in (Get-Content $Path)) { - if (!$line) { - $rtf += "\par`n" - } else { - $rtf += "$line`n" - } -} -$rtf += '}' - -$rtf | Set-Content $OutFile \ No newline at end of file diff --git a/build/windows/LICENSE.rtf b/build/windows/LICENSE.rtf deleted file mode 100644 index 185063f24..000000000 --- a/build/windows/LICENSE.rtf +++ /dev/null @@ -1,23 +0,0 @@ -{\rtf1\ansi\deff0{\fonttbl{\f0\fcharset0 Arial;}}\pard\sa200\sl200\slmult1\fs20 -MIT License -\par -Copyright (c) 2019 GitHub Inc. -\par -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -\par -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -\par -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -} diff --git a/build/windows/gh.wixproj b/build/windows/gh.wixproj index 5c355955d..aa72d4da3 100644 --- a/build/windows/gh.wixproj +++ b/build/windows/gh.wixproj @@ -19,11 +19,9 @@ + - - - diff --git a/build/windows/gh.wxs b/build/windows/gh.wxs index 32eb9564b..1e91734f1 100644 --- a/build/windows/gh.wxs +++ b/build/windows/gh.wxs @@ -70,9 +70,8 @@ - + - - + diff --git a/build/windows/ui.wxs b/build/windows/ui.wxs new file mode 100644 index 000000000..8c534adc8 --- /dev/null +++ b/build/windows/ui.wxs @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + 1 + "1"]]> + + 1 + + NOT Installed + Installed AND PATCH + + 1 + 1 + NOT WIXUI_DONTVALIDATEPATH + "1"]]> + WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1" + 1 + 1 + + NOT Installed + Installed AND NOT PATCH + Installed AND PATCH + + 1 + + 1 + 1 + 1 + + + + + + + \ No newline at end of file From 2d6c1e21d747a7925e8e4db17c4436d08c3ce278 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 6 Oct 2021 14:09:45 -0400 Subject: [PATCH 005/253] added a bunch of stuff --- pkg/cmd/repo/rename/rename.go | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 pkg/cmd/repo/rename/rename.go diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go new file mode 100644 index 000000000..11597b618 --- /dev/null +++ b/pkg/cmd/repo/rename/rename.go @@ -0,0 +1,73 @@ +package rename + +import ( + "fmt" + "net/http" + "strings" + + "github.com/cli/cli/v2/api" + "github.com/cli/cli/v2/internal/ghinstance" + "github.com/cli/cli/v2/internal/ghrepo" + "github.com/cli/cli/v2/pkg/cmdutil" + "github.com/cli/cli/v2/pkg/iostreams" + "github.com/spf13/cobra" +) + +type RenameOptions struct{ + HttpClient func() (*http.Client, error) + IO *iostreams.IOStreams + RepoName string +} + +func MewCmcRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Command { + opts:= &RenameOptions { + IO: f.IOStreams, + HttpClient: f.HttpClient, + } + + cmd := &cobra.Command{ + Use: "rename Date: Thu, 7 Oct 2021 10:59:08 -0400 Subject: [PATCH 006/253] added more stuff --- api/queries_repo.go | 19 ++++++++++++++++ go.mod | 2 ++ pkg/cmd/repo/rename/http.go | 2 ++ pkg/cmd/repo/rename/rename.go | 43 +++++++++++++++++++++-------------- pkg/cmd/repo/repo.go | 2 ++ 5 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 pkg/cmd/repo/rename/http.go diff --git a/api/queries_repo.go b/api/queries_repo.go index b1e41370d..c9d8b46f9 100644 --- a/api/queries_repo.go +++ b/api/queries_repo.go @@ -230,6 +230,25 @@ func (r Repository) ViewerCanTriage() bool { } } +func FetchRepository(client *Client, repo ghrepo.Interface, fields []string) (*Repository, error) { + query := fmt.Sprintf(`query RepositoryInfo($owner: String!, $name: String!) { + repository(owner: $owner, name: $name) {%s} + }`, RepositoryGraphQL(fields)) + + variables := map[string]interface{}{ + "owner": repo.RepoOwner(), + "name": repo.RepoName(), + } + + var result struct { + Repository Repository + } + if err := client.GraphQL(repo.RepoHost(), query, variables, &result); err != nil { + return nil, err + } + return InitRepoHostname(&result.Repository, repo.RepoHost()), nil +} + func GitHubRepo(client *Client, repo ghrepo.Interface) (*Repository, error) { query := ` fragment repo on Repository { diff --git a/go.mod b/go.mod index 89885a50a..e04f06576 100644 --- a/go.mod +++ b/go.mod @@ -47,3 +47,5 @@ require ( replace github.com/shurcooL/graphql => github.com/cli/shurcooL-graphql v0.0.0-20200707151639-0f7232a2bf7e replace golang.org/x/crypto => github.com/cli/crypto v0.0.0-20210929142629-6be313f59b03 + +replace github.com/cli/cli/v2/pkg/cmd/repo/rename => /cli/cli/v2/pkg/cmd/repo/rename \ No newline at end of file diff --git a/pkg/cmd/repo/rename/http.go b/pkg/cmd/repo/rename/http.go new file mode 100644 index 000000000..f20f487c8 --- /dev/null +++ b/pkg/cmd/repo/rename/http.go @@ -0,0 +1,2 @@ +package rename + diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 11597b618..b02c5d332 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -3,10 +3,15 @@ package rename import ( "fmt" "net/http" - "strings" + + // "strings" "github.com/cli/cli/v2/api" + "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/internal/ghinstance" + + // "github.com/cli/cli/v2/internal/ghinstance" + "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" @@ -16,20 +21,23 @@ import ( type RenameOptions struct{ HttpClient func() (*http.Client, error) IO *iostreams.IOStreams + Config func() (config.Config, error) RepoName string } -func MewCmcRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Command { +func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Command { opts:= &RenameOptions { IO: f.IOStreams, HttpClient: f.HttpClient, } cmd := &cobra.Command{ - Use: "rename ", Short: "Rename a repository", Long: "Rename a GitHub repository", - Args: cmdutil.ExactArgs(2, "cannot rename: repository argument required"), + Args: cmdutil.ExactArgs(1, "cannot rename: repository argument required"), RunE: func (cmd *cobra.Command, args []string) error { opts.RepoName = args[0] if runf != nil { @@ -43,31 +51,32 @@ func MewCmcRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co func renameRun(opts *RenameOptions) error { - cs := opts.IO.ColorScheme() + // cs := opts.IO.ColorScheme() httpClient, err := opts.HttpClient() if err != nil { return err } apiClient := api.NewClientFromHTTP(httpClient); - var toRename ghrepo.Interface - - repoURL := opts.RepoName - - if !strings.Contains(repoURL, "/") { - currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) - if err != nil { - return err - } - repoURL = currentUser + "/" + repoURL + username, err := api.CurrentLoginName(apiClient, ghinstance.Default()) + if err != nil { + return err } - toRename, err = ghrepo.FromFullName(repoURL) + toRename, err := ghrepo.FromFullName(opts.RepoName) if err != nil { return fmt.Errorf("argument error: %w", err) } fields := []string{"name", "owner", "id"} + repo, err := api.FetchRepository(apiClient, toRename, fields) + if err != nil { + return err + } - repo, err := + if username != repo.Owner.Login { + return fmt.Errorf("you do not own this repository"); + } + + return nil } \ No newline at end of file diff --git a/pkg/cmd/repo/repo.go b/pkg/cmd/repo/repo.go index 252c322e9..608d0a2ff 100644 --- a/pkg/cmd/repo/repo.go +++ b/pkg/cmd/repo/repo.go @@ -10,6 +10,7 @@ import ( repoListCmd "github.com/cli/cli/v2/pkg/cmd/repo/list" repoSyncCmd "github.com/cli/cli/v2/pkg/cmd/repo/sync" repoViewCmd "github.com/cli/cli/v2/pkg/cmd/repo/view" + repoRenameCmd "github.com/cli/cli/v2/pkg/cmd/repo/rename" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/spf13/cobra" ) @@ -42,6 +43,7 @@ func NewCmdRepo(f *cmdutil.Factory) *cobra.Command { cmd.AddCommand(repoSyncCmd.NewCmdSync(f, nil)) cmd.AddCommand(creditsCmd.NewCmdRepoCredits(f, nil)) cmd.AddCommand(gardenCmd.NewCmdGarden(f, nil)) + cmd.AddCommand(repoRenameCmd.NewCmdRename(f, nil)) return cmd } From 8f3911bb30c8cb00c6f1c4559bbe554e6c07500f Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Thu, 7 Oct 2021 11:36:58 -0400 Subject: [PATCH 007/253] added unfinished api call --- pkg/cmd/repo/rename/rename.go | 49 ++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index b02c5d332..5b19065a7 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -18,28 +18,28 @@ import ( "github.com/spf13/cobra" ) -type RenameOptions struct{ +type RenameOptions struct { HttpClient func() (*http.Client, error) - IO *iostreams.IOStreams + IO *iostreams.IOStreams Config func() (config.Config, error) - RepoName string + RepoName []string } func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Command { - opts:= &RenameOptions { - IO: f.IOStreams, + opts := &RenameOptions{ + IO: f.IOStreams, HttpClient: f.HttpClient, } cmd := &cobra.Command{ DisableFlagsInUseLine: true, - - Use: "rename ", + + Use: "rename ", Short: "Rename a repository", - Long: "Rename a GitHub repository", - Args: cmdutil.ExactArgs(1, "cannot rename: repository argument required"), - RunE: func (cmd *cobra.Command, args []string) error { - opts.RepoName = args[0] + Long: "Rename a GitHub repository", + Args: cmdutil.ExactArgs(2, "cannot rename: repository argument required"), + RunE: func(cmd *cobra.Command, args []string) error { + opts.RepoName = append(opts.RepoName, args[0], args[1]) if runf != nil { return runf(opts) } @@ -49,34 +49,47 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co return cmd } - func renameRun(opts *RenameOptions) error { + oldRepoName := opts.RepoName[0] + // cs := opts.IO.ColorScheme() httpClient, err := opts.HttpClient() if err != nil { return err } - apiClient := api.NewClientFromHTTP(httpClient); + apiClient := api.NewClientFromHTTP(httpClient) username, err := api.CurrentLoginName(apiClient, ghinstance.Default()) if err != nil { return err } - toRename, err := ghrepo.FromFullName(opts.RepoName) + repo, err := ghrepo.FromFullName(oldRepoName) if err != nil { return fmt.Errorf("argument error: %w", err) } fields := []string{"name", "owner", "id"} - repo, err := api.FetchRepository(apiClient, toRename, fields) + repoDetails, err := api.FetchRepository(apiClient, repo, fields) if err != nil { return err } - if username != repo.Owner.Login { - return fmt.Errorf("you do not own this repository"); + if username != repoDetails.Owner.Login { + return fmt.Errorf("you do not own this repository") + } + + err = renameRepo(apiClient, repo.RepoHost(), repoDetails) + if err != nil { + return err } return nil -} \ No newline at end of file +} + +func renameRepo(apiClient *api.Client, hostname string, repoDetails *api.Repository) error { + path := fmt.Sprintf("/repos/%s/%s", repoDetails.Owner.Login, repoDetails.Name) + fmt.Println(path); + + return nil +} From f24951836125c6ca4aec82ff2acc075168757287 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Thu, 7 Oct 2021 11:39:26 -0400 Subject: [PATCH 008/253] error handling --- pkg/cmd/repo/rename/rename.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 5b19065a7..34c54fc11 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -88,8 +88,10 @@ func renameRun(opts *RenameOptions) error { } func renameRepo(apiClient *api.Client, hostname string, repoDetails *api.Repository) error { - path := fmt.Sprintf("/repos/%s/%s", repoDetails.Owner.Login, repoDetails.Name) - fmt.Println(path); - + path := fmt.Sprintf("repos/%s/%s", repoDetails.Owner.Login, repoDetails.Name) + err := apiClient.REST(hostname, "PATCH", path, nil, nil) + if err != nil { + return err + } return nil } From 1b4abd67a92fbfdcd104ceb71a1f2bd0503a2fce Mon Sep 17 00:00:00 2001 From: Parth Date: Fri, 8 Oct 2021 15:06:43 -0400 Subject: [PATCH 009/253] added api --- pkg/cmd/repo/rename/rename.go | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 34c54fc11..7f9ba78ab 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -1,17 +1,14 @@ package rename import ( + "bytes" + "encoding/json" "fmt" "net/http" - // "strings" - "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/internal/ghinstance" - - // "github.com/cli/cli/v2/internal/ghinstance" - "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" @@ -25,6 +22,12 @@ type RenameOptions struct { RepoName []string } +type renameRepo struct{ + Owner string + Repository string + Name string `json:"name,omitempty"` +} + func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Command { opts := &RenameOptions{ IO: f.IOStreams, @@ -51,6 +54,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co func renameRun(opts *RenameOptions) error { oldRepoName := opts.RepoName[0] + newRepoName := opts.RepoName[1] // cs := opts.IO.ColorScheme() httpClient, err := opts.HttpClient() @@ -79,7 +83,13 @@ func renameRun(opts *RenameOptions) error { return fmt.Errorf("you do not own this repository") } - err = renameRepo(apiClient, repo.RepoHost(), repoDetails) + input := renameRepo{ + Owner: repo.RepoOwner(), + Repository: repo.RepoName(), + Name: newRepoName, + } + + err = runRename(apiClient, repo.RepoHost(), repoDetails, input) if err != nil { return err } @@ -87,9 +97,14 @@ func renameRun(opts *RenameOptions) error { return nil } -func renameRepo(apiClient *api.Client, hostname string, repoDetails *api.Repository) error { +func runRename(apiClient *api.Client, hostname string, repoDetails *api.Repository, input renameRepo) error { + body := &bytes.Buffer{} + enc := json.NewEncoder(body) + if err := enc.Encode(input); err != nil { + return err + } path := fmt.Sprintf("repos/%s/%s", repoDetails.Owner.Login, repoDetails.Name) - err := apiClient.REST(hostname, "PATCH", path, nil, nil) + err := apiClient.REST(hostname, "PATCH", path, nil, body) if err != nil { return err } From 7725116428e36597364094a77482bdc4f18536b6 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 8 Oct 2021 15:37:01 -0400 Subject: [PATCH 010/253] works --- pkg/cmd/repo/rename/http.go | 2 -- pkg/cmd/repo/rename/rename.go | 8 ++++++-- 2 files changed, 6 insertions(+), 4 deletions(-) delete mode 100644 pkg/cmd/repo/rename/http.go diff --git a/pkg/cmd/repo/rename/http.go b/pkg/cmd/repo/rename/http.go deleted file mode 100644 index f20f487c8..000000000 --- a/pkg/cmd/repo/rename/http.go +++ /dev/null @@ -1,2 +0,0 @@ -package rename - diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 7f9ba78ab..628f53402 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -94,17 +94,21 @@ func renameRun(opts *RenameOptions) error { return err } + + return nil } func runRename(apiClient *api.Client, hostname string, repoDetails *api.Repository, input renameRepo) error { + path := fmt.Sprintf("repos/%s/%s", repoDetails.Owner.Login, repoDetails.Name) + body := &bytes.Buffer{} enc := json.NewEncoder(body) if err := enc.Encode(input); err != nil { return err } - path := fmt.Sprintf("repos/%s/%s", repoDetails.Owner.Login, repoDetails.Name) - err := apiClient.REST(hostname, "PATCH", path, nil, body) + + err := apiClient.REST(hostname, "PATCH", path, body, nil) if err != nil { return err } From e6e8d72428dd4a15d6b1a7d44650fb7719ceca07 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 8 Oct 2021 17:03:37 -0400 Subject: [PATCH 011/253] added full functionality --- pkg/cmd/repo/rename/rename.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 628f53402..adf81c49d 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "net/http" + "strings" "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/internal/config" @@ -37,7 +38,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co cmd := &cobra.Command{ DisableFlagsInUseLine: true, - Use: "rename ", + Use: "rename ", Short: "Rename a repository", Long: "Rename a GitHub repository", Args: cmdutil.ExactArgs(2, "cannot rename: repository argument required"), @@ -53,21 +54,24 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co } func renameRun(opts *RenameOptions) error { - oldRepoName := opts.RepoName[0] - newRepoName := opts.RepoName[1] - - // cs := opts.IO.ColorScheme() + cs := opts.IO.ColorScheme() httpClient, err := opts.HttpClient() if err != nil { return err } apiClient := api.NewClientFromHTTP(httpClient) - username, err := api.CurrentLoginName(apiClient, ghinstance.Default()) + currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) if err != nil { return err } + oldRepoName := opts.RepoName[0] + if !strings.Contains(oldRepoName, "/") { + oldRepoName = currentUser + "/" + oldRepoName + } + newRepoName := opts.RepoName[1] + repo, err := ghrepo.FromFullName(oldRepoName) if err != nil { return fmt.Errorf("argument error: %w", err) @@ -79,7 +83,7 @@ func renameRun(opts *RenameOptions) error { return err } - if username != repoDetails.Owner.Login { + if currentUser != repoDetails.Owner.Login { return fmt.Errorf("you do not own this repository") } @@ -94,7 +98,9 @@ func renameRun(opts *RenameOptions) error { return err } - + if opts.IO.IsStdoutTTY() { + fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), currentUser + "/" + newRepoName) + } return nil } From 2ff8732836c290ea2fc5bd9f415055d98b19bd64 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 8 Oct 2021 17:05:36 -0400 Subject: [PATCH 012/253] minor fix --- pkg/cmd/repo/rename/rename.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index adf81c49d..e69e3f982 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -38,7 +38,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co cmd := &cobra.Command{ DisableFlagsInUseLine: true, - Use: "rename ", + Use: "rename ", Short: "Rename a repository", Long: "Rename a GitHub repository", Args: cmdutil.ExactArgs(2, "cannot rename: repository argument required"), @@ -84,7 +84,7 @@ func renameRun(opts *RenameOptions) error { } if currentUser != repoDetails.Owner.Login { - return fmt.Errorf("you do not own this repository") + return fmt.Errorf("%s you do not own this repository", cs.FailureIcon()) } input := renameRepo{ From b9c60e8dc8da2e68cab9da6b278975c32045266b Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 8 Oct 2021 17:18:15 -0400 Subject: [PATCH 013/253] remove go.mod change --- go.mod | 2 -- pkg/cmd/repo/rename/rename.go | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e04f06576..89885a50a 100644 --- a/go.mod +++ b/go.mod @@ -47,5 +47,3 @@ require ( replace github.com/shurcooL/graphql => github.com/cli/shurcooL-graphql v0.0.0-20200707151639-0f7232a2bf7e replace golang.org/x/crypto => github.com/cli/crypto v0.0.0-20210929142629-6be313f59b03 - -replace github.com/cli/cli/v2/pkg/cmd/repo/rename => /cli/cli/v2/pkg/cmd/repo/rename \ No newline at end of file diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index e69e3f982..92d9277de 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -113,7 +113,7 @@ func runRename(apiClient *api.Client, hostname string, repoDetails *api.Reposito if err := enc.Encode(input); err != nil { return err } - + err := apiClient.REST(hostname, "PATCH", path, body, nil) if err != nil { return err From 28bfd8e773b83ba65a84f576fd76c55e3d33d070 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 8 Oct 2021 17:21:03 -0400 Subject: [PATCH 014/253] lint fix --- pkg/cmd/repo/rename/rename.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 92d9277de..176149f48 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -23,10 +23,10 @@ type RenameOptions struct { RepoName []string } -type renameRepo struct{ - Owner string - Repository string - Name string `json:"name,omitempty"` +type renameRepo struct { + Owner string + Repository string + Name string `json:"name,omitempty"` } func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Command { @@ -88,9 +88,9 @@ func renameRun(opts *RenameOptions) error { } input := renameRepo{ - Owner: repo.RepoOwner(), - Repository: repo.RepoName(), - Name: newRepoName, + Owner: repo.RepoOwner(), + Repository: repo.RepoName(), + Name: newRepoName, } err = runRename(apiClient, repo.RepoHost(), repoDetails, input) @@ -99,7 +99,7 @@ func renameRun(opts *RenameOptions) error { } if opts.IO.IsStdoutTTY() { - fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), currentUser + "/" + newRepoName) + fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), currentUser+"/"+newRepoName) } return nil @@ -107,13 +107,13 @@ func renameRun(opts *RenameOptions) error { func runRename(apiClient *api.Client, hostname string, repoDetails *api.Repository, input renameRepo) error { path := fmt.Sprintf("repos/%s/%s", repoDetails.Owner.Login, repoDetails.Name) - + body := &bytes.Buffer{} enc := json.NewEncoder(body) if err := enc.Encode(input); err != nil { return err } - + err := apiClient.REST(hostname, "PATCH", path, body, nil) if err != nil { return err From 3001afda777200285e05de82eb3edf6b32d8c6a2 Mon Sep 17 00:00:00 2001 From: Parth Date: Fri, 8 Oct 2021 17:38:56 -0400 Subject: [PATCH 015/253] full lint fix --- pkg/cmd/repo/rename/rename_test.go | 40 ++++++++++++++++++++++++++++++ pkg/cmd/repo/repo.go | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 pkg/cmd/repo/rename/rename_test.go diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go new file mode 100644 index 000000000..c91a7a427 --- /dev/null +++ b/pkg/cmd/repo/rename/rename_test.go @@ -0,0 +1,40 @@ +package rename + +import ( + "testing" +) + +func TestNewCmdRename(t * testing.T) { + tests := []struct { + name string + tty bool + input string + output RenameOptions + wantErr bool + errMsg string + }{ + { + name: "no argument", + tty: true, + input: "", + output: RenameOptions{}, + }, + { + name: "argument", + tty: true, + input: "cli/cli", + output: RenameOptions{ + DestArg: "cli comand-line-interface", + }, + }, + { + name: "incorrect argument", + tty: true, + input: "", + output: RenameOptions{ + DestArg: "cli ", + }, + }, + } +} + diff --git a/pkg/cmd/repo/repo.go b/pkg/cmd/repo/repo.go index 608d0a2ff..973bc33df 100644 --- a/pkg/cmd/repo/repo.go +++ b/pkg/cmd/repo/repo.go @@ -8,9 +8,9 @@ import ( repoForkCmd "github.com/cli/cli/v2/pkg/cmd/repo/fork" gardenCmd "github.com/cli/cli/v2/pkg/cmd/repo/garden" repoListCmd "github.com/cli/cli/v2/pkg/cmd/repo/list" + repoRenameCmd "github.com/cli/cli/v2/pkg/cmd/repo/rename" repoSyncCmd "github.com/cli/cli/v2/pkg/cmd/repo/sync" repoViewCmd "github.com/cli/cli/v2/pkg/cmd/repo/view" - repoRenameCmd "github.com/cli/cli/v2/pkg/cmd/repo/rename" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/spf13/cobra" ) From c894587761c4c4e972d1b07abe4e50e1d3c26256 Mon Sep 17 00:00:00 2001 From: Parth Date: Fri, 8 Oct 2021 21:02:40 -0400 Subject: [PATCH 016/253] added function tests --- pkg/cmd/repo/rename/rename.go | 16 +++--- pkg/cmd/repo/rename/rename_test.go | 80 ++++++++++++++++++++---------- 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 176149f48..118adaa44 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -17,10 +17,11 @@ import ( ) type RenameOptions struct { - HttpClient func() (*http.Client, error) - IO *iostreams.IOStreams - Config func() (config.Config, error) - RepoName []string + HttpClient func() (*http.Client, error) + IO *iostreams.IOStreams + Config func() (config.Config, error) + oldRepoName string + newRepoName string } type renameRepo struct { @@ -43,7 +44,8 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co Long: "Rename a GitHub repository", Args: cmdutil.ExactArgs(2, "cannot rename: repository argument required"), RunE: func(cmd *cobra.Command, args []string) error { - opts.RepoName = append(opts.RepoName, args[0], args[1]) + opts.oldRepoName = args[0] + opts.newRepoName = args[1] if runf != nil { return runf(opts) } @@ -66,11 +68,11 @@ func renameRun(opts *RenameOptions) error { return err } - oldRepoName := opts.RepoName[0] + oldRepoName := opts.oldRepoName if !strings.Contains(oldRepoName, "/") { oldRepoName = currentUser + "/" + oldRepoName } - newRepoName := opts.RepoName[1] + newRepoName := opts.newRepoName repo, err := ghrepo.FromFullName(oldRepoName) if err != nil { diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index c91a7a427..c07b3aa8b 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -2,39 +2,67 @@ package rename import ( "testing" + + "github.com/cli/cli/v2/pkg/cmdutil" + "github.com/cli/cli/v2/pkg/iostreams" + "github.com/google/shlex" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -func TestNewCmdRename(t * testing.T) { - tests := []struct { - name string - tty bool - input string - output RenameOptions - wantErr bool - errMsg string +func TestNewCmdRename(t *testing.T) { + testCases := []struct { + name string + args string + wantOpts RenameOptions + wantErr string }{ { - name: "no argument", - tty: true, - input: "", - output: RenameOptions{}, - }, - { - name: "argument", - tty: true, - input: "cli/cli", - output: RenameOptions{ - DestArg: "cli comand-line-interface", - }, + name: "no arguments", + args: "", + wantErr: "cannot rename: repository argument required", }, { - name: "incorrect argument", - tty: true, - input: "", - output: RenameOptions{ - DestArg: "cli ", + name: "correct argument", + args: "OWNER/REPO REPOS", + wantOpts: RenameOptions{ + oldRepoName: "OWNER/REPO", + newRepoName: "REPOS", }, }, } -} + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + io, stdin, stdout, stderr := iostreams.Test() + fac := &cmdutil.Factory{IOStreams: io} + var opts *RenameOptions + cmd := NewCmdRename(fac, func(co *RenameOptions) error { + opts = co + return nil + }) + + argv, err := shlex.Split(tt.args) + require.NoError(t, err) + cmd.SetArgs(argv) + + cmd.SetIn(stdin) + cmd.SetOut(stdout) + cmd.SetErr(stderr) + + _, err = cmd.ExecuteC() + if tt.wantErr != "" { + assert.EqualError(t, err, tt.wantErr) + return + } else { + assert.NoError(t, err) + } + + assert.Equal(t, "", stdout.String()) + assert.Equal(t, "", stderr.String()) + + assert.Equal(t, tt.wantOpts.oldRepoName, opts.oldRepoName) + assert.Equal(t, tt.wantOpts.newRepoName, opts.newRepoName) + }) + } +} \ No newline at end of file From c714ed6fdf11ae2bbc998e43f046f53452788a2d Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 8 Oct 2021 22:02:59 -0400 Subject: [PATCH 017/253] added api tests --- pkg/cmd/repo/rename/rename_test.go | 88 ++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index c07b3aa8b..1a35579b8 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -1,9 +1,11 @@ package rename import ( + "net/http" "testing" "github.com/cli/cli/v2/pkg/cmdutil" + "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" "github.com/google/shlex" "github.com/stretchr/testify/assert" @@ -65,4 +67,90 @@ func TestNewCmdRename(t *testing.T) { assert.Equal(t, tt.wantOpts.newRepoName, opts.newRepoName) }) } +} + +func TestRenameRun(t *testing.T) { + testCases := []struct { + name string + opts RenameOptions + httpStubs func(*httpmock.Registry) + stdoutTTY bool + wantOut string + }{ + { + name: "owner repo change name tty", + opts: RenameOptions{ + oldRepoName: "OWNER/REPO", + newRepoName: "NEW_REPO", + }, + wantOut: "✓ Renamed repository pxrth9/team2-hack", + httpStubs: func(reg *httpmock.Registry) { + reg.Register(httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(200, "{}")) + }, + stdoutTTY: true, + }, + { + name: "owner repo change name notty", + opts: RenameOptions{ + oldRepoName: "OWNER/REPO", + newRepoName: "NEW_REPO", + }, + wantOut: "✓ Renamed repository pxrth9/team2-hack", + httpStubs: func(reg *httpmock.Registry) { + reg.Register(httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(200, "{}")) + }, + stdoutTTY: false, + }, + { + name: "nonowner repo change name tty", + opts: RenameOptions{ + oldRepoName: "NON_OWNER/REPO", + newRepoName: "NEW_REPO", + }, + wantOut: "X you do not own this repository", + httpStubs: func(reg *httpmock.Registry) { + reg.Register(httpmock.REST("PATCH", "repos/NON_OWNER/REPO"), + httpmock.StatusStringResponse(200, "{}")) + }, + stdoutTTY: true, + }, + { + name: "non owner repo change name notty", + opts: RenameOptions{ + oldRepoName: "NON_OWNER/REPO", + newRepoName: "NEW_REPO", + }, + wantOut: "X you do not own this repository", + httpStubs: func(reg *httpmock.Registry) { + reg.Register(httpmock.REST("PATCH", "repos/NON_OWNER/REPO"), + httpmock.StatusStringResponse(200, "{}")) + }, + stdoutTTY: false, + }, + } + + for _, tt := range testCases { + reg := &httpmock.Registry{} + if tt.httpStubs != nil { + tt.httpStubs(reg) + } + tt.opts.HttpClient = func() (*http.Client, error) { + return &http.Client{Transport: reg}, nil + } + + io, _, stdout, _ := iostreams.Test() + tt.opts.IO = io + + t.Run(tt.name, func(t *testing.T) { + defer reg.Verify(t) + io.SetStderrTTY(tt.stdoutTTY) + + err := renameRun(&tt.opts) + assert.NoError(t, err) + assert.Equal(t, tt.wantOut, stdout.String()) + }) + } + } \ No newline at end of file From f7ec49e809fda3861c6cd846a37f6f05305341cc Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 8 Oct 2021 22:05:36 -0400 Subject: [PATCH 018/253] lint fix --- pkg/cmd/repo/rename/rename_test.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 1a35579b8..1e5637324 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -69,13 +69,13 @@ func TestNewCmdRename(t *testing.T) { } } -func TestRenameRun(t *testing.T) { +func TestRenameRun(t *testing.T) { testCases := []struct { - name string - opts RenameOptions + name string + opts RenameOptions httpStubs func(*httpmock.Registry) stdoutTTY bool - wantOut string + wantOut string }{ { name: "owner repo change name tty", @@ -138,7 +138,7 @@ func TestRenameRun(t *testing.T) { } tt.opts.HttpClient = func() (*http.Client, error) { return &http.Client{Transport: reg}, nil - } + } io, _, stdout, _ := iostreams.Test() tt.opts.IO = io @@ -152,5 +152,4 @@ func TestRenameRun(t *testing.T) { assert.Equal(t, tt.wantOut, stdout.String()) }) } - -} \ No newline at end of file +} From 7e6cf79355756aab7c07b7db21f1917c786f9e4a Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Mon, 11 Oct 2021 17:38:20 -0400 Subject: [PATCH 019/253] minor changes --- pkg/cmd/repo/rename/rename.go | 10 +- pkg/cmd/repo/rename/rename_test.go | 187 ++++++++++++++++------------- 2 files changed, 110 insertions(+), 87 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 118adaa44..086ef8121 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -63,13 +63,13 @@ func renameRun(opts *RenameOptions) error { } apiClient := api.NewClientFromHTTP(httpClient) - currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) - if err != nil { - return err - } - oldRepoName := opts.oldRepoName + var currentUser string if !strings.Contains(oldRepoName, "/") { + currentUser, err = api.CurrentLoginName(apiClient, ghinstance.Default()) + if err != nil { + return err + } oldRepoName = currentUser + "/" + oldRepoName } newRepoName := opts.newRepoName diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 1e5637324..735e5b3c4 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -1,11 +1,9 @@ package rename import ( - "net/http" "testing" "github.com/cli/cli/v2/pkg/cmdutil" - "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" "github.com/google/shlex" "github.com/stretchr/testify/assert" @@ -69,87 +67,112 @@ func TestNewCmdRename(t *testing.T) { } } -func TestRenameRun(t *testing.T) { - testCases := []struct { - name string - opts RenameOptions - httpStubs func(*httpmock.Registry) - stdoutTTY bool - wantOut string - }{ - { - name: "owner repo change name tty", - opts: RenameOptions{ - oldRepoName: "OWNER/REPO", - newRepoName: "NEW_REPO", - }, - wantOut: "✓ Renamed repository pxrth9/team2-hack", - httpStubs: func(reg *httpmock.Registry) { - reg.Register(httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(200, "{}")) - }, - stdoutTTY: true, - }, - { - name: "owner repo change name notty", - opts: RenameOptions{ - oldRepoName: "OWNER/REPO", - newRepoName: "NEW_REPO", - }, - wantOut: "✓ Renamed repository pxrth9/team2-hack", - httpStubs: func(reg *httpmock.Registry) { - reg.Register(httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(200, "{}")) - }, - stdoutTTY: false, - }, - { - name: "nonowner repo change name tty", - opts: RenameOptions{ - oldRepoName: "NON_OWNER/REPO", - newRepoName: "NEW_REPO", - }, - wantOut: "X you do not own this repository", - httpStubs: func(reg *httpmock.Registry) { - reg.Register(httpmock.REST("PATCH", "repos/NON_OWNER/REPO"), - httpmock.StatusStringResponse(200, "{}")) - }, - stdoutTTY: true, - }, - { - name: "non owner repo change name notty", - opts: RenameOptions{ - oldRepoName: "NON_OWNER/REPO", - newRepoName: "NEW_REPO", - }, - wantOut: "X you do not own this repository", - httpStubs: func(reg *httpmock.Registry) { - reg.Register(httpmock.REST("PATCH", "repos/NON_OWNER/REPO"), - httpmock.StatusStringResponse(200, "{}")) - }, - stdoutTTY: false, - }, - } +// func TestRenameRun(t *testing.T) { +// testCases := []struct { +// name string +// opts RenameOptions +// httpStubs func(*httpmock.Registry) +// stdoutTTY bool +// wantOut string +// }{ +// { +// name: "owner repo change name tty", +// opts: RenameOptions{ +// oldRepoName: "OWNER/REPO", +// newRepoName: "NEW_REPO", +// }, +// wantOut: "✓ Renamed repository OWNER/NEW_REPO", +// httpStubs: func(reg *httpmock.Registry) { +// reg.Register( +// httpmock.GraphQL(`query RepositoryInfo\b`), +// httpmock.StringResponse(`{ "data": +// { "repository": { +// "id": "THE-ID"} } }`)) +// reg.Register( +// httpmock.REST("PATCH", "repos/OWNER/REPO"), +// httpmock.StatusStringResponse(204, "{}")) +// }, +// stdoutTTY: true, +// }, +// { +// name: "owner repo change name notty", +// opts: RenameOptions{ +// oldRepoName: "OWNER/REPO", +// newRepoName: "NEW_REPO", +// }, +// wantOut: "✓ Renamed repository pxrth9/team2-hack", +// httpStubs: func(reg *httpmock.Registry) { +// reg.Register( +// httpmock.GraphQL(`query RepositoryInfo\b`), +// httpmock.StringResponse(`{ "data": +// { "repository": { +// "id": "THE-ID"} } }`)) +// reg.Register( +// httpmock.REST("PATCH", "repos/OWNER/REPO"), +// httpmock.StatusStringResponse(200, "{}")) +// }, +// stdoutTTY: false, +// }, +// { +// name: "nonowner repo change name tty", +// opts: RenameOptions{ +// oldRepoName: "NON_OWNER/REPO", +// newRepoName: "NEW_REPO", +// }, +// wantOut: "X you do not own this repository", +// httpStubs: func(reg *httpmock.Registry) { +// reg.Register( +// httpmock.GraphQL(`query RepositoryInfo\b`), +// httpmock.StringResponse(`{ "data": +// { "repository": { +// "id": "THE-ID"} } }`)) +// reg.Register( +// httpmock.REST("PATCH", "repos/NON_OWNER/REPO"), +// httpmock.StatusStringResponse(200, "{}")) +// }, +// stdoutTTY: true, +// }, +// { +// name: "non owner repo change name notty", +// opts: RenameOptions{ +// oldRepoName: "NON_OWNER/REPO", +// newRepoName: "NEW_REPO", +// }, +// wantOut: "X you do not own this repository", +// httpStubs: func(reg *httpmock.Registry) { +// reg.Register( +// httpmock.GraphQL(`query RepositoryInfo\b`), +// httpmock.StringResponse(`{ "data": +// { "repository": { +// "id": "THE-ID"} } }`)) +// reg.Register( +// httpmock.REST("PATCH", "repos/NON_OWNER/REPO"), +// httpmock.StatusStringResponse(200, "{}")) +// }, +// stdoutTTY: false, +// }, +// } - for _, tt := range testCases { - reg := &httpmock.Registry{} - if tt.httpStubs != nil { - tt.httpStubs(reg) - } - tt.opts.HttpClient = func() (*http.Client, error) { - return &http.Client{Transport: reg}, nil - } +// for _, tt := range testCases { +// t.Run(tt.name, func(t * testing.T) { +// reg := &httpmock.Registry{} +// defer reg.Verify(t) +// if tt.httpStubs != nil { +// tt.httpStubs(reg) +// } - io, _, stdout, _ := iostreams.Test() - tt.opts.IO = io +// io, _, stdout, _ := iostreams.Test() - t.Run(tt.name, func(t *testing.T) { - defer reg.Verify(t) - io.SetStderrTTY(tt.stdoutTTY) +// tt.opts.HttpClient = func() (*http.Client, error) { +// return &http.Client{Transport: reg}, nil +// } - err := renameRun(&tt.opts) - assert.NoError(t, err) - assert.Equal(t, tt.wantOut, stdout.String()) - }) - } -} +// tt.opts.IO = io +// io.SetStderrTTY(tt.stdoutTTY) +// io.SetStdoutTTY(tt.stdoutTTY) +// err := renameRun(&tt.opts) +// assert.NoError(t, err) +// assert.Equal(t, tt.wantOut, stdout.String()) +// }) +// } +// } From c639161394fbae16079cbeabe8020eb83f96aaf2 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Tue, 12 Oct 2021 18:46:15 -0400 Subject: [PATCH 020/253] final touches --- pkg/cmd/repo/rename/rename.go | 11 +- pkg/cmd/repo/rename/rename_test.go | 191 +++++++++++++---------------- 2 files changed, 89 insertions(+), 113 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 086ef8121..225a4a39f 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -64,9 +64,8 @@ func renameRun(opts *RenameOptions) error { apiClient := api.NewClientFromHTTP(httpClient) oldRepoName := opts.oldRepoName - var currentUser string if !strings.Contains(oldRepoName, "/") { - currentUser, err = api.CurrentLoginName(apiClient, ghinstance.Default()) + currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) if err != nil { return err } @@ -85,10 +84,6 @@ func renameRun(opts *RenameOptions) error { return err } - if currentUser != repoDetails.Owner.Login { - return fmt.Errorf("%s you do not own this repository", cs.FailureIcon()) - } - input := renameRepo{ Owner: repo.RepoOwner(), Repository: repo.RepoName(), @@ -97,11 +92,11 @@ func renameRun(opts *RenameOptions) error { err = runRename(apiClient, repo.RepoHost(), repoDetails, input) if err != nil { - return err + return fmt.Errorf("API called failed: %s, please check your parameters", err.Error()) } if opts.IO.IsStdoutTTY() { - fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), currentUser+"/"+newRepoName) + fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), repo.RepoOwner()+"/"+newRepoName) } return nil diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 735e5b3c4..42c9a1479 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -1,9 +1,11 @@ package rename import ( + "net/http" "testing" "github.com/cli/cli/v2/pkg/cmdutil" + "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" "github.com/google/shlex" "github.com/stretchr/testify/assert" @@ -67,112 +69,91 @@ func TestNewCmdRename(t *testing.T) { } } -// func TestRenameRun(t *testing.T) { -// testCases := []struct { -// name string -// opts RenameOptions -// httpStubs func(*httpmock.Registry) -// stdoutTTY bool -// wantOut string -// }{ -// { -// name: "owner repo change name tty", -// opts: RenameOptions{ -// oldRepoName: "OWNER/REPO", -// newRepoName: "NEW_REPO", -// }, -// wantOut: "✓ Renamed repository OWNER/NEW_REPO", -// httpStubs: func(reg *httpmock.Registry) { -// reg.Register( -// httpmock.GraphQL(`query RepositoryInfo\b`), -// httpmock.StringResponse(`{ "data": -// { "repository": { -// "id": "THE-ID"} } }`)) -// reg.Register( -// httpmock.REST("PATCH", "repos/OWNER/REPO"), -// httpmock.StatusStringResponse(204, "{}")) -// }, -// stdoutTTY: true, -// }, -// { -// name: "owner repo change name notty", -// opts: RenameOptions{ -// oldRepoName: "OWNER/REPO", -// newRepoName: "NEW_REPO", -// }, -// wantOut: "✓ Renamed repository pxrth9/team2-hack", -// httpStubs: func(reg *httpmock.Registry) { -// reg.Register( -// httpmock.GraphQL(`query RepositoryInfo\b`), -// httpmock.StringResponse(`{ "data": -// { "repository": { -// "id": "THE-ID"} } }`)) -// reg.Register( -// httpmock.REST("PATCH", "repos/OWNER/REPO"), -// httpmock.StatusStringResponse(200, "{}")) -// }, -// stdoutTTY: false, -// }, -// { -// name: "nonowner repo change name tty", -// opts: RenameOptions{ -// oldRepoName: "NON_OWNER/REPO", -// newRepoName: "NEW_REPO", -// }, -// wantOut: "X you do not own this repository", -// httpStubs: func(reg *httpmock.Registry) { -// reg.Register( -// httpmock.GraphQL(`query RepositoryInfo\b`), -// httpmock.StringResponse(`{ "data": -// { "repository": { -// "id": "THE-ID"} } }`)) -// reg.Register( -// httpmock.REST("PATCH", "repos/NON_OWNER/REPO"), -// httpmock.StatusStringResponse(200, "{}")) -// }, -// stdoutTTY: true, -// }, -// { -// name: "non owner repo change name notty", -// opts: RenameOptions{ -// oldRepoName: "NON_OWNER/REPO", -// newRepoName: "NEW_REPO", -// }, -// wantOut: "X you do not own this repository", -// httpStubs: func(reg *httpmock.Registry) { -// reg.Register( -// httpmock.GraphQL(`query RepositoryInfo\b`), -// httpmock.StringResponse(`{ "data": -// { "repository": { -// "id": "THE-ID"} } }`)) -// reg.Register( -// httpmock.REST("PATCH", "repos/NON_OWNER/REPO"), -// httpmock.StatusStringResponse(200, "{}")) -// }, -// stdoutTTY: false, -// }, -// } +func TestRenameRun(t *testing.T) { + testCases := []struct { + name string + opts RenameOptions + httpStubs func(*httpmock.Registry) + stdoutTTY bool + wantOut string + }{ + { + name: "owner repo change name tty", + opts: RenameOptions{ + oldRepoName: "OWNER/REPO", + newRepoName: "NEW_REPO", + }, + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.GraphQL(`query RepositoryInfo\b`), + httpmock.StringResponse(` + { + "data": { + "repository": { + "id": "THE-ID", + "name": "REPO", + "owner": { + "login": "OWNER" + } + } + } + }`)) + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + stdoutTTY: true, + }, + { + name: "owner repo change name notty", + opts: RenameOptions{ + oldRepoName: "OWNER/REPO", + newRepoName: "NEW_REPO", + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.GraphQL(`query RepositoryInfo\b`), + httpmock.StringResponse(` + { + "data": { + "repository": { + "id": "THE-ID", + "name": "REPO", + "owner": { + "login": "OWNER" + } + } + } + }`)) + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(200, "{}")) + }, + stdoutTTY: false, + }, + } -// for _, tt := range testCases { -// t.Run(tt.name, func(t * testing.T) { -// reg := &httpmock.Registry{} -// defer reg.Verify(t) -// if tt.httpStubs != nil { -// tt.httpStubs(reg) -// } + for _, tt := range testCases { + reg := &httpmock.Registry{} + if tt.httpStubs != nil { + tt.httpStubs(reg) + } + tt.opts.HttpClient = func() (*http.Client, error) { + return &http.Client{Transport: reg}, nil + } -// io, _, stdout, _ := iostreams.Test() + io, _, stdout, _ := iostreams.Test() + tt.opts.IO = io -// tt.opts.HttpClient = func() (*http.Client, error) { -// return &http.Client{Transport: reg}, nil -// } + t.Run(tt.name, func(t *testing.T) { + defer reg.Verify(t) + io.SetStderrTTY(tt.stdoutTTY) + io.SetStdoutTTY(tt.stdoutTTY) -// tt.opts.IO = io -// io.SetStderrTTY(tt.stdoutTTY) -// io.SetStdoutTTY(tt.stdoutTTY) -// err := renameRun(&tt.opts) -// assert.NoError(t, err) -// assert.Equal(t, tt.wantOut, stdout.String()) -// }) -// } -// } + err := renameRun(&tt.opts) + assert.NoError(t, err) + assert.Equal(t, tt.wantOut, stdout.String()) + }) + } +} From 4afd1e06bf53900c3a6a74ec9c8edec93827574b Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Tue, 12 Oct 2021 18:56:32 -0400 Subject: [PATCH 021/253] optimize command --- pkg/cmd/repo/rename/rename.go | 17 ++++++++-------- pkg/cmd/repo/rename/rename_test.go | 32 ++---------------------------- 2 files changed, 10 insertions(+), 39 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 225a4a39f..6d073941b 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -77,12 +77,11 @@ func renameRun(opts *RenameOptions) error { if err != nil { return fmt.Errorf("argument error: %w", err) } - - fields := []string{"name", "owner", "id"} - repoDetails, err := api.FetchRepository(apiClient, repo, fields) - if err != nil { - return err - } + // fields := []string{"name", "owner", "id"} + // repoDetails, err := api.FetchRepository(apiClient, repo, fields) + // if err != nil { + // return err + // } input := renameRepo{ Owner: repo.RepoOwner(), @@ -90,7 +89,7 @@ func renameRun(opts *RenameOptions) error { Name: newRepoName, } - err = runRename(apiClient, repo.RepoHost(), repoDetails, input) + err = runRename(apiClient, repo.RepoHost(), input) if err != nil { return fmt.Errorf("API called failed: %s, please check your parameters", err.Error()) } @@ -102,8 +101,8 @@ func renameRun(opts *RenameOptions) error { return nil } -func runRename(apiClient *api.Client, hostname string, repoDetails *api.Repository, input renameRepo) error { - path := fmt.Sprintf("repos/%s/%s", repoDetails.Owner.Login, repoDetails.Name) +func runRename(apiClient *api.Client, hostname string, input renameRepo) error { + path := fmt.Sprintf("repos/%s/%s", input.Owner, input.Repository) body := &bytes.Buffer{} enc := json.NewEncoder(body) diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 42c9a1479..750ac1e3d 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -85,20 +85,6 @@ func TestRenameRun(t *testing.T) { }, wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.GraphQL(`query RepositoryInfo\b`), - httpmock.StringResponse(` - { - "data": { - "repository": { - "id": "THE-ID", - "name": "REPO", - "owner": { - "login": "OWNER" - } - } - } - }`)) reg.Register( httpmock.REST("PATCH", "repos/OWNER/REPO"), httpmock.StatusStringResponse(204, "{}")) @@ -108,26 +94,12 @@ func TestRenameRun(t *testing.T) { { name: "owner repo change name notty", opts: RenameOptions{ - oldRepoName: "OWNER/REPO", + oldRepoName: "NON_OWNER/REPO", newRepoName: "NEW_REPO", }, httpStubs: func(reg *httpmock.Registry) { reg.Register( - httpmock.GraphQL(`query RepositoryInfo\b`), - httpmock.StringResponse(` - { - "data": { - "repository": { - "id": "THE-ID", - "name": "REPO", - "owner": { - "login": "OWNER" - } - } - } - }`)) - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.REST("PATCH", "repos/NON_OWNER/REPO"), httpmock.StatusStringResponse(200, "{}")) }, stdoutTTY: false, From b106e606e1b82ba38c85f75330198e24595e158a Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Tue, 12 Oct 2021 18:56:56 -0400 Subject: [PATCH 022/253] final touches --- pkg/cmd/repo/rename/rename.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 6d073941b..daf0d1164 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -77,11 +77,6 @@ func renameRun(opts *RenameOptions) error { if err != nil { return fmt.Errorf("argument error: %w", err) } - // fields := []string{"name", "owner", "id"} - // repoDetails, err := api.FetchRepository(apiClient, repo, fields) - // if err != nil { - // return err - // } input := renameRepo{ Owner: repo.RepoOwner(), From c1c2946179ad63a3387ed1e37910ebadb0afa3f2 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 13 Oct 2021 15:04:43 -0400 Subject: [PATCH 023/253] minor fix --- pkg/cmd/repo/rename/rename.go | 2 +- pkg/cmd/repo/rename/rename_test.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index daf0d1164..46fe4a400 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -86,7 +86,7 @@ func renameRun(opts *RenameOptions) error { err = runRename(apiClient, repo.RepoHost(), input) if err != nil { - return fmt.Errorf("API called failed: %s, please check your parameters", err.Error()) + return fmt.Errorf("API called failed: %s, please check your parameters", err) } if opts.IO.IsStdoutTTY() { diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 750ac1e3d..692c0d08a 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -94,13 +94,13 @@ func TestRenameRun(t *testing.T) { { name: "owner repo change name notty", opts: RenameOptions{ - oldRepoName: "NON_OWNER/REPO", + oldRepoName: "OWNER/REPO", newRepoName: "NEW_REPO", }, httpStubs: func(reg *httpmock.Registry) { reg.Register( - httpmock.REST("PATCH", "repos/NON_OWNER/REPO"), - httpmock.StatusStringResponse(200, "{}")) + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) }, stdoutTTY: false, }, From 69db6fca25cdec05712098b956424c647b2c09d3 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 13 Oct 2021 16:31:54 -0400 Subject: [PATCH 024/253] res comments --- pkg/cmd/repo/rename/rename.go | 26 +++++++++++--------------- pkg/cmd/repo/rename/rename_test.go | 16 ++++++++-------- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 46fe4a400..0d09ac580 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -20,8 +20,8 @@ type RenameOptions struct { HttpClient func() (*http.Client, error) IO *iostreams.IOStreams Config func() (config.Config, error) - oldRepoName string - newRepoName string + oldRepoSelector string + newRepoSelector string } type renameRepo struct { @@ -39,13 +39,13 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co cmd := &cobra.Command{ DisableFlagsInUseLine: true, - Use: "rename ", + Use: "rename ", Short: "Rename a repository", Long: "Rename a GitHub repository", Args: cmdutil.ExactArgs(2, "cannot rename: repository argument required"), RunE: func(cmd *cobra.Command, args []string) error { - opts.oldRepoName = args[0] - opts.newRepoName = args[1] + opts.oldRepoSelector = args[0] + opts.newRepoSelector = args[1] if runf != nil { return runf(opts) } @@ -63,17 +63,17 @@ func renameRun(opts *RenameOptions) error { } apiClient := api.NewClientFromHTTP(httpClient) - oldRepoName := opts.oldRepoName - if !strings.Contains(oldRepoName, "/") { + oldRepoURL := opts.oldRepoSelector + if !strings.Contains(oldRepoURL, "/") { currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) if err != nil { return err } - oldRepoName = currentUser + "/" + oldRepoName + oldRepoURL = currentUser + "/" + oldRepoURL } - newRepoName := opts.newRepoName + newRepoName := opts.newRepoSelector - repo, err := ghrepo.FromFullName(oldRepoName) + repo, err := ghrepo.FromFullName(oldRepoURL) if err != nil { return fmt.Errorf("argument error: %w", err) } @@ -105,9 +105,5 @@ func runRename(apiClient *api.Client, hostname string, input renameRepo) error { return err } - err := apiClient.REST(hostname, "PATCH", path, body, nil) - if err != nil { - return err - } - return nil + return apiClient.REST(hostname, "PATCH", path, body, nil) } diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 692c0d08a..d6813d321 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -28,8 +28,8 @@ func TestNewCmdRename(t *testing.T) { name: "correct argument", args: "OWNER/REPO REPOS", wantOpts: RenameOptions{ - oldRepoName: "OWNER/REPO", - newRepoName: "REPOS", + oldRepoSelector: "OWNER/REPO", + newRepoSelector: "REPOS", }, }, } @@ -63,8 +63,8 @@ func TestNewCmdRename(t *testing.T) { assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) - assert.Equal(t, tt.wantOpts.oldRepoName, opts.oldRepoName) - assert.Equal(t, tt.wantOpts.newRepoName, opts.newRepoName) + assert.Equal(t, tt.wantOpts.oldRepoSelector, opts.oldRepoSelector) + assert.Equal(t, tt.wantOpts.newRepoSelector, opts.newRepoSelector) }) } } @@ -80,8 +80,8 @@ func TestRenameRun(t *testing.T) { { name: "owner repo change name tty", opts: RenameOptions{ - oldRepoName: "OWNER/REPO", - newRepoName: "NEW_REPO", + oldRepoSelector: "OWNER/REPO", + newRepoSelector: "NEW_REPO", }, wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", httpStubs: func(reg *httpmock.Registry) { @@ -94,8 +94,8 @@ func TestRenameRun(t *testing.T) { { name: "owner repo change name notty", opts: RenameOptions{ - oldRepoName: "OWNER/REPO", - newRepoName: "NEW_REPO", + oldRepoSelector: "OWNER/REPO", + newRepoSelector: "NEW_REPO", }, httpStubs: func(reg *httpmock.Registry) { reg.Register( From 3a21dfa1c50ed278b96b99b618400397906fc1fb Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 13 Oct 2021 16:41:46 -0400 Subject: [PATCH 025/253] lint fix --- pkg/cmd/repo/rename/rename.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 0d09ac580..8c1410d83 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -17,9 +17,9 @@ import ( ) type RenameOptions struct { - HttpClient func() (*http.Client, error) - IO *iostreams.IOStreams - Config func() (config.Config, error) + HttpClient func() (*http.Client, error) + IO *iostreams.IOStreams + Config func() (config.Config, error) oldRepoSelector string newRepoSelector string } From 5ed77c996835102973d79d098e30093f5e787520 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 15 Oct 2021 19:10:05 -0400 Subject: [PATCH 026/253] made some progress, not done yet --- pkg/cmd/repo/rename/rename.go | 85 +++++++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 14 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 8c1410d83..4492bef06 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -3,16 +3,19 @@ package rename import ( "bytes" "encoding/json" + "errors" "fmt" "net/http" "strings" + "github.com/AlecAivazis/survey/v2" "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/internal/ghinstance" "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" + "github.com/cli/cli/v2/pkg/prompt" "github.com/spf13/cobra" ) @@ -20,8 +23,10 @@ type RenameOptions struct { HttpClient func() (*http.Client, error) IO *iostreams.IOStreams Config func() (config.Config, error) + BaseRepo func() (ghrepo.Interface, error) oldRepoSelector string newRepoSelector string + flagRepo bool } type renameRepo struct { @@ -34,24 +39,42 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co opts := &RenameOptions{ IO: f.IOStreams, HttpClient: f.HttpClient, + BaseRepo: f.BaseRepo, } cmd := &cobra.Command{ - DisableFlagsInUseLine: true, - - Use: "rename ", + Use: "rename [-R] [] []", Short: "Rename a repository", - Long: "Rename a GitHub repository", - Args: cmdutil.ExactArgs(2, "cannot rename: repository argument required"), + Long: `Rename a GitHub repository + With no argument, the repository for the current directory is renamed using a prompt + With one argument, the repository of the current directory is renamed using the argument + With '-R', and two arguments the given repository is replaced with the new name `, + Args: cobra.MaximumNArgs(2), RunE: func(cmd *cobra.Command, args []string) error { - opts.oldRepoSelector = args[0] - opts.newRepoSelector = args[1] + if len(args) > 0 { + if len(args) == 2 && opts.flagRepo { + opts.oldRepoSelector = args[0] + opts.newRepoSelector = args[1] + } else if len(args) == 1 && !opts.flagRepo { + opts.newRepoSelector = args[0] + } else { + return fmt.Errorf("check your parameters") + } + } else { + if !opts.IO.CanPrompt() { + return &cmdutil.FlagError{ + Err: errors.New("could not prompt: proceed with prompt or argument(s) required")} + } + } if runf != nil { return runf(opts) } return renameRun(opts) }, } + + cmd.Flags().BoolVarP(&opts.flagRepo, "repo", "R", false, "pass in two arguments to rename a repository") + return cmd } @@ -63,15 +86,49 @@ func renameRun(opts *RenameOptions) error { } apiClient := api.NewClientFromHTTP(httpClient) - oldRepoURL := opts.oldRepoSelector - if !strings.Contains(oldRepoURL, "/") { - currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) - if err != nil { - return err + var toRename ghrepo.Interface + oldRepoURL := "" + newRepoName := "" + + if !opts.flagRepo { + if opts.newRepoSelector != "" && opts.oldRepoSelector == "" { + newRepoName = opts.newRepoSelector + } else { + err = prompt.SurveyAskOne( + &survey.Input{ + Message: "Rename current repo to: ", + }, + &newRepoName, + ) + if err != nil { + return err + } + + toRename, err = opts.BaseRepo() + if err != nil { + return err + } + } + } else { + if opts.newRepoSelector != "" && opts.oldRepoSelector != "" { + oldRepoURL = opts.oldRepoSelector + newRepoName = opts.newRepoSelector + if !strings.Contains(oldRepoURL, "/") { + currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) + if err != nil { + return err + } + oldRepoURL = currentUser + "/" + oldRepoURL + } + } else { + return fmt.Errorf("check your params") } - oldRepoURL = currentUser + "/" + oldRepoURL } - newRepoName := opts.newRepoSelector + + fmt.Println(toRename) + fmt.Printf("Old: %s\n", oldRepoURL) + fmt.Printf("New: %s\n", newRepoName) + fmt.Println(opts.flagRepo) repo, err := ghrepo.FromFullName(oldRepoURL) if err != nil { From fd376d552cbbae265b05f2b88adcd93771f01fec Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Mon, 18 Oct 2021 13:53:31 -0400 Subject: [PATCH 027/253] final changes, update local remote left --- pkg/cmd/repo/rename/rename.go | 83 ++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 4492bef06..3d3425e5b 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -58,12 +58,13 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co } else if len(args) == 1 && !opts.flagRepo { opts.newRepoSelector = args[0] } else { - return fmt.Errorf("check your parameters") + return &cmdutil.FlagError{ + Err: errors.New("check your parameters")} } } else { if !opts.IO.CanPrompt() { return &cmdutil.FlagError{ - Err: errors.New("could not prompt: proceed with prompt or argument(s) required")} + Err: errors.New("could not prompt: proceed with prompt")} } } if runf != nil { @@ -86,11 +87,17 @@ func renameRun(opts *RenameOptions) error { } apiClient := api.NewClientFromHTTP(httpClient) - var toRename ghrepo.Interface - oldRepoURL := "" - newRepoName := "" + var hostName string + var input renameRepo + var newRepoName string if !opts.flagRepo { + currRepo, err := opts.BaseRepo() + if err != nil { + return err + } + + hostName = currRepo.RepoHost() if opts.newRepoSelector != "" && opts.oldRepoSelector == "" { newRepoName = opts.newRepoSelector } else { @@ -103,51 +110,47 @@ func renameRun(opts *RenameOptions) error { if err != nil { return err } - - toRename, err = opts.BaseRepo() - if err != nil { - return err - } } + + input = renameRepo{ + Owner: currRepo.RepoOwner(), + Repository: currRepo.RepoName(), + Name: newRepoName, + } + } else { - if opts.newRepoSelector != "" && opts.oldRepoSelector != "" { - oldRepoURL = opts.oldRepoSelector - newRepoName = opts.newRepoSelector - if !strings.Contains(oldRepoURL, "/") { - currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) - if err != nil { - return err - } - oldRepoURL = currentUser + "/" + oldRepoURL - } - } else { - return fmt.Errorf("check your params") + oldRepoURL := opts.oldRepoSelector + newRepoName = opts.newRepoSelector + + currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) + if err != nil { + return err + } + + if !strings.Contains(oldRepoURL, "/") { + oldRepoURL = currentUser + "/" + oldRepoURL + } + + currRepo, err := ghrepo.FromFullName(oldRepoURL) + if err != nil { + return fmt.Errorf("argument error: %w", err) + } + hostName = currRepo.RepoHost() + + input = renameRepo{ + Owner: currRepo.RepoOwner(), + Repository: currRepo.RepoName(), + Name: newRepoName, } } - fmt.Println(toRename) - fmt.Printf("Old: %s\n", oldRepoURL) - fmt.Printf("New: %s\n", newRepoName) - fmt.Println(opts.flagRepo) - - repo, err := ghrepo.FromFullName(oldRepoURL) - if err != nil { - return fmt.Errorf("argument error: %w", err) - } - - input := renameRepo{ - Owner: repo.RepoOwner(), - Repository: repo.RepoName(), - Name: newRepoName, - } - - err = runRename(apiClient, repo.RepoHost(), input) + err = runRename(apiClient, hostName, input) if err != nil { return fmt.Errorf("API called failed: %s, please check your parameters", err) } if opts.IO.IsStdoutTTY() { - fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), repo.RepoOwner()+"/"+newRepoName) + fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), input.Owner+"/"+newRepoName) } return nil From cc63e7de8d683578dd894e740db6bbb5c0efa2f5 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Mon, 18 Oct 2021 13:54:30 -0400 Subject: [PATCH 028/253] minor fix --- pkg/cmd/repo/rename/rename.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 3d3425e5b..4ba8e73a0 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -58,8 +58,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co } else if len(args) == 1 && !opts.flagRepo { opts.newRepoSelector = args[0] } else { - return &cmdutil.FlagError{ - Err: errors.New("check your parameters")} + return fmt.Errorf("check your parameters") } } else { if !opts.IO.CanPrompt() { From 93221a19d441ac06f970a385205b8da75e368e48 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Mon, 18 Oct 2021 13:56:48 -0400 Subject: [PATCH 029/253] fix --- pkg/cmd/repo/rename/rename.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 4ba8e73a0..7a79032e8 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -88,9 +88,9 @@ func renameRun(opts *RenameOptions) error { var hostName string var input renameRepo - var newRepoName string if !opts.flagRepo { + var newRepoName string currRepo, err := opts.BaseRepo() if err != nil { return err @@ -119,7 +119,7 @@ func renameRun(opts *RenameOptions) error { } else { oldRepoURL := opts.oldRepoSelector - newRepoName = opts.newRepoSelector + newRepoName := opts.newRepoSelector currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) if err != nil { @@ -134,6 +134,7 @@ func renameRun(opts *RenameOptions) error { if err != nil { return fmt.Errorf("argument error: %w", err) } + hostName = currRepo.RepoHost() input = renameRepo{ @@ -149,7 +150,7 @@ func renameRun(opts *RenameOptions) error { } if opts.IO.IsStdoutTTY() { - fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), input.Owner+"/"+newRepoName) + fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), input.Owner+"/"+input.Name) } return nil From ddd0b7cb0438a1afa75e351b535d6225e8e01900 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Mon, 18 Oct 2021 16:43:40 -0400 Subject: [PATCH 030/253] added remote update --- git/remote.go | 8 ++ pkg/cmd/repo/rename/rename.go | 63 ++++++++++++---- pkg/cmd/repo/rename/rename_test.go | 114 +++++++++++++++-------------- 3 files changed, 116 insertions(+), 69 deletions(-) diff --git a/git/remote.go b/git/remote.go index f9dfbc4bd..c74b529d4 100644 --- a/git/remote.go +++ b/git/remote.go @@ -140,6 +140,14 @@ func AddRemote(name, u string) (*Remote, error) { }, nil } +func UpdateRemote(name, u string) error { + addCmd, err := GitCommand("remote", "set-url", name, u) + if err != nil { + return err + } + return run.PrepareCmd(addCmd).Run() +} + func SetRemoteResolution(name, resolution string) error { addCmd, err := GitCommand("config", "--add", fmt.Sprintf("remote.%s.gh-resolved", name), resolution) if err != nil { diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 7a79032e8..121038df6 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -10,6 +10,7 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/cli/cli/v2/api" + "github.com/cli/cli/v2/git" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/internal/ghinstance" "github.com/cli/cli/v2/internal/ghrepo" @@ -30,9 +31,10 @@ type RenameOptions struct { } type renameRepo struct { - Owner string - Repository string - Name string `json:"name,omitempty"` + RepoHost string + RepoOwner string + RepoName string + Name string `json:"name,omitempty"` } func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Command { @@ -40,6 +42,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co IO: f.IOStreams, HttpClient: f.HttpClient, BaseRepo: f.BaseRepo, + Config: f.Config, } cmd := &cobra.Command{ @@ -86,7 +89,6 @@ func renameRun(opts *RenameOptions) error { } apiClient := api.NewClientFromHTTP(httpClient) - var hostName string var input renameRepo if !opts.flagRepo { @@ -96,7 +98,6 @@ func renameRun(opts *RenameOptions) error { return err } - hostName = currRepo.RepoHost() if opts.newRepoSelector != "" && opts.oldRepoSelector == "" { newRepoName = opts.newRepoSelector } else { @@ -112,9 +113,10 @@ func renameRun(opts *RenameOptions) error { } input = renameRepo{ - Owner: currRepo.RepoOwner(), - Repository: currRepo.RepoName(), - Name: newRepoName, + RepoHost: currRepo.RepoHost(), + RepoOwner: currRepo.RepoOwner(), + RepoName: currRepo.RepoName(), + Name: newRepoName, } } else { @@ -135,29 +137,58 @@ func renameRun(opts *RenameOptions) error { return fmt.Errorf("argument error: %w", err) } - hostName = currRepo.RepoHost() - input = renameRepo{ - Owner: currRepo.RepoOwner(), - Repository: currRepo.RepoName(), - Name: newRepoName, + RepoHost: currRepo.RepoHost(), + RepoOwner: currRepo.RepoOwner(), + RepoName: currRepo.RepoName(), + Name: newRepoName, } } - err = runRename(apiClient, hostName, input) + err = runRename(apiClient, input.RepoHost, input) if err != nil { return fmt.Errorf("API called failed: %s, please check your parameters", err) } + if !opts.flagRepo { + cfg, err := opts.Config() + if err != nil { + return err + } + + protocol, err := cfg.Get(input.RepoHost, "git_protocol") + if err != nil { + return err + } + remoteURL := formatRemoteURL(input, protocol) + + err = git.UpdateRemote("origin", remoteURL) + if err != nil { + return err + } + + if opts.IO.IsStdoutTTY() { + fmt.Fprintf(opts.IO.Out, "%s Added remote %s\n", cs.SuccessIcon(), remoteURL) + } + } + if opts.IO.IsStdoutTTY() { - fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), input.Owner+"/"+input.Name) + fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), input.RepoOwner+"/"+input.Name) } return nil } +func formatRemoteURL(repo renameRepo, protocol string) string { + if protocol == "ssh" { + return fmt.Sprintf("git@%s:%s/%s.git", repo.RepoHost, repo.RepoOwner, repo.Name) + } + + return fmt.Sprintf("https://%s/%s/%s.git", repo.RepoHost, repo.RepoOwner, repo.Name) +} + func runRename(apiClient *api.Client, hostname string, input renameRepo) error { - path := fmt.Sprintf("repos/%s/%s", input.Owner, input.Repository) + path := fmt.Sprintf("repos/%s/%s", input.RepoOwner, input.RepoName) body := &bytes.Buffer{} enc := json.NewEncoder(body) diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index d6813d321..6b2c2134a 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -4,70 +4,70 @@ import ( "net/http" "testing" - "github.com/cli/cli/v2/pkg/cmdutil" + // "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/google/shlex" + // "github.com/google/shlex" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + // "github.com/stretchr/testify/require" ) -func TestNewCmdRename(t *testing.T) { - testCases := []struct { - name string - args string - wantOpts RenameOptions - wantErr string - }{ - { - name: "no arguments", - args: "", - wantErr: "cannot rename: repository argument required", - }, - { - name: "correct argument", - args: "OWNER/REPO REPOS", - wantOpts: RenameOptions{ - oldRepoSelector: "OWNER/REPO", - newRepoSelector: "REPOS", - }, - }, - } - for _, tt := range testCases { - t.Run(tt.name, func(t *testing.T) { - io, stdin, stdout, stderr := iostreams.Test() - fac := &cmdutil.Factory{IOStreams: io} +// func TestNewCmdRename(t *testing.T) { +// testCases := []struct { +// name string +// args string +// wantOpts RenameOptions +// wantErr string +// }{ +// { +// name: "no arguments", +// args: "", +// wantErr: "cannot rename: repository argument required", +// }, +// { +// name: "correct argument", +// args: "OWNER/REPO REPOS", +// wantOpts: RenameOptions{ +// oldRepoSelector: "OWNER/REPO", +// newRepoSelector: "REPOS", +// }, +// }, +// } +// for _, tt := range testCases { +// t.Run(tt.name, func(t *testing.T) { +// io, stdin, stdout, stderr := iostreams.Test() +// fac := &cmdutil.Factory{IOStreams: io} - var opts *RenameOptions - cmd := NewCmdRename(fac, func(co *RenameOptions) error { - opts = co - return nil - }) +// var opts *RenameOptions +// cmd := NewCmdRename(fac, func(co *RenameOptions) error { +// opts = co +// return nil +// }) - argv, err := shlex.Split(tt.args) - require.NoError(t, err) - cmd.SetArgs(argv) +// argv, err := shlex.Split(tt.args) +// require.NoError(t, err) +// cmd.SetArgs(argv) - cmd.SetIn(stdin) - cmd.SetOut(stdout) - cmd.SetErr(stderr) +// cmd.SetIn(stdin) +// cmd.SetOut(stdout) +// cmd.SetErr(stderr) - _, err = cmd.ExecuteC() - if tt.wantErr != "" { - assert.EqualError(t, err, tt.wantErr) - return - } else { - assert.NoError(t, err) - } +// _, err = cmd.ExecuteC() +// if tt.wantErr != "" { +// assert.EqualError(t, err, tt.wantErr) +// return +// } else { +// assert.NoError(t, err) +// } - assert.Equal(t, "", stdout.String()) - assert.Equal(t, "", stderr.String()) +// assert.Equal(t, "", stdout.String()) +// assert.Equal(t, "", stderr.String()) - assert.Equal(t, tt.wantOpts.oldRepoSelector, opts.oldRepoSelector) - assert.Equal(t, tt.wantOpts.newRepoSelector, opts.newRepoSelector) - }) - } -} +// assert.Equal(t, tt.wantOpts.oldRepoSelector, opts.oldRepoSelector) +// assert.Equal(t, tt.wantOpts.newRepoSelector, opts.newRepoSelector) +// }) +// } +// } func TestRenameRun(t *testing.T) { testCases := []struct { @@ -82,9 +82,13 @@ func TestRenameRun(t *testing.T) { opts: RenameOptions{ oldRepoSelector: "OWNER/REPO", newRepoSelector: "NEW_REPO", + flagRepo: true, }, wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.GraphQL(`query UserCurrent\b`), + httpmock.StringResponse(`{"data":{"viewer":{"login":"OWNER"}}}`)) reg.Register( httpmock.REST("PATCH", "repos/OWNER/REPO"), httpmock.StatusStringResponse(204, "{}")) @@ -96,8 +100,12 @@ func TestRenameRun(t *testing.T) { opts: RenameOptions{ oldRepoSelector: "OWNER/REPO", newRepoSelector: "NEW_REPO", + flagRepo: true, }, httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.GraphQL(`query UserCurrent\b`), + httpmock.StringResponse(`{"data":{"viewer":{"login":"OWNER"}}}`)) reg.Register( httpmock.REST("PATCH", "repos/OWNER/REPO"), httpmock.StatusStringResponse(204, "{}")) From 8400ed4a19794c30e1beeb91c6c086f00734ad57 Mon Sep 17 00:00:00 2001 From: Parth Date: Tue, 19 Oct 2021 11:28:55 -0400 Subject: [PATCH 031/253] optimize api calls --- pkg/cmd/repo/rename/rename.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 121038df6..e36607059 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -123,12 +123,11 @@ func renameRun(opts *RenameOptions) error { oldRepoURL := opts.oldRepoSelector newRepoName := opts.newRepoSelector - currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) - if err != nil { - return err - } - if !strings.Contains(oldRepoURL, "/") { + currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) + if err != nil { + return err + } oldRepoURL = currentUser + "/" + oldRepoURL } From dd87e80b4cad6f67b19de46dc7e00ec12fc95814 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 20 Oct 2021 16:12:32 -0400 Subject: [PATCH 032/253] added final touches --- git/remote.go | 2 +- pkg/cmd/repo/rename/rename.go | 83 ++++++------- pkg/cmd/repo/rename/rename_test.go | 193 ++++++++++++++++++----------- 3 files changed, 158 insertions(+), 120 deletions(-) diff --git a/git/remote.go b/git/remote.go index c74b529d4..91bbb6770 100644 --- a/git/remote.go +++ b/git/remote.go @@ -140,7 +140,7 @@ func AddRemote(name, u string) (*Remote, error) { }, nil } -func UpdateRemote(name, u string) error { +func UpdateRemoteURL(name, u string) error { addCmd, err := GitCommand("remote", "set-url", name, u) if err != nil { return err diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index e36607059..4380cc5d8 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -4,15 +4,16 @@ import ( "bytes" "encoding/json" "errors" + + // "errors" "fmt" "net/http" - "strings" "github.com/AlecAivazis/survey/v2" "github.com/cli/cli/v2/api" + "github.com/cli/cli/v2/context" "github.com/cli/cli/v2/git" "github.com/cli/cli/v2/internal/config" - "github.com/cli/cli/v2/internal/ghinstance" "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" @@ -25,9 +26,9 @@ type RenameOptions struct { IO *iostreams.IOStreams Config func() (config.Config, error) BaseRepo func() (ghrepo.Interface, error) + Remotes func() (context.Remotes, error) oldRepoSelector string newRepoSelector string - flagRepo bool } type renameRepo struct { @@ -42,6 +43,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co IO: f.IOStreams, HttpClient: f.HttpClient, BaseRepo: f.BaseRepo, + Remotes: f.Remotes, Config: f.Config, } @@ -52,31 +54,21 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co With no argument, the repository for the current directory is renamed using a prompt With one argument, the repository of the current directory is renamed using the argument With '-R', and two arguments the given repository is replaced with the new name `, - Args: cobra.MaximumNArgs(2), + Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - if len(args) > 0 { - if len(args) == 2 && opts.flagRepo { - opts.oldRepoSelector = args[0] - opts.newRepoSelector = args[1] - } else if len(args) == 1 && !opts.flagRepo { - opts.newRepoSelector = args[0] - } else { - return fmt.Errorf("check your parameters") - } + if len(args) > 0 { + opts.newRepoSelector = args[0] } else { if !opts.IO.CanPrompt() { return &cmdutil.FlagError{ Err: errors.New("could not prompt: proceed with prompt")} } } - if runf != nil { - return runf(opts) - } return renameRun(opts) }, } - cmd.Flags().BoolVarP(&opts.flagRepo, "repo", "R", false, "pass in two arguments to rename a repository") + cmd.Flags().StringVarP(&opts.oldRepoSelector, "repo", "R", "", "pass in two arguments to rename a repository") return cmd } @@ -90,8 +82,10 @@ func renameRun(opts *RenameOptions) error { apiClient := api.NewClientFromHTTP(httpClient) var input renameRepo + var oldRepo ghrepo.Interface + var newRepo ghrepo.Interface - if !opts.flagRepo { + if opts.oldRepoSelector == "" { var newRepoName string currRepo, err := opts.BaseRepo() if err != nil { @@ -112,6 +106,9 @@ func renameRun(opts *RenameOptions) error { } } + oldRepo = ghrepo.NewWithHost(currRepo.RepoOwner(), currRepo.RepoName(), currRepo.RepoHost()) + newRepo = ghrepo.NewWithHost(currRepo.RepoOwner(), newRepoName, currRepo.RepoHost()) + input = renameRepo{ RepoHost: currRepo.RepoHost(), RepoOwner: currRepo.RepoOwner(), @@ -123,19 +120,13 @@ func renameRun(opts *RenameOptions) error { oldRepoURL := opts.oldRepoSelector newRepoName := opts.newRepoSelector - if !strings.Contains(oldRepoURL, "/") { - currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) - if err != nil { - return err - } - oldRepoURL = currentUser + "/" + oldRepoURL - } - currRepo, err := ghrepo.FromFullName(oldRepoURL) if err != nil { return fmt.Errorf("argument error: %w", err) } + oldRepo = ghrepo.NewWithHost(currRepo.RepoOwner(), currRepo.RepoName(), currRepo.RepoHost()) + input = renameRepo{ RepoHost: currRepo.RepoHost(), RepoOwner: currRepo.RepoOwner(), @@ -144,51 +135,51 @@ func renameRun(opts *RenameOptions) error { } } - err = runRename(apiClient, input.RepoHost, input) + err = runRename(apiClient, oldRepo.RepoHost(), input) if err != nil { return fmt.Errorf("API called failed: %s, please check your parameters", err) } - if !opts.flagRepo { + if opts.oldRepoSelector == "" { cfg, err := opts.Config() if err != nil { return err } - protocol, err := cfg.Get(input.RepoHost, "git_protocol") - if err != nil { - return err - } - remoteURL := formatRemoteURL(input, protocol) - - err = git.UpdateRemote("origin", remoteURL) + protocol, err := cfg.Get(oldRepo.RepoHost(), "git_protocol") if err != nil { return err } - if opts.IO.IsStdoutTTY() { - fmt.Fprintf(opts.IO.Out, "%s Added remote %s\n", cs.SuccessIcon(), remoteURL) + remotes, err := opts.Remotes() + if err != nil { + return err + } + + baseRemote, err := remotes.FindByRepo(oldRepo.RepoOwner(), oldRepo.RepoName()) + if err != nil { + return err + } + + remoteURL := ghrepo.FormatRemoteURL(newRepo, protocol) + err = git.UpdateRemoteURL(baseRemote.Name, remoteURL) + if err != nil { + return err } } if opts.IO.IsStdoutTTY() { fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), input.RepoOwner+"/"+input.Name) + if opts.oldRepoSelector == "" { + fmt.Fprintf(opts.IO.Out, `%s Updated the "origin" remote`, cs.SuccessIcon()) + } } return nil } -func formatRemoteURL(repo renameRepo, protocol string) string { - if protocol == "ssh" { - return fmt.Sprintf("git@%s:%s/%s.git", repo.RepoHost, repo.RepoOwner, repo.Name) - } - - return fmt.Sprintf("https://%s/%s/%s.git", repo.RepoHost, repo.RepoOwner, repo.Name) -} - func runRename(apiClient *api.Client, hostname string, input renameRepo) error { path := fmt.Sprintf("repos/%s/%s", input.RepoOwner, input.RepoName) - body := &bytes.Buffer{} enc := json.NewEncoder(body) if err := enc.Encode(input); err != nil { diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 6b2c2134a..fb582b2e4 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -1,16 +1,20 @@ package rename -import ( - "net/http" - "testing" +// import ( +// "fmt" +// "net/http" +// "testing" - // "github.com/cli/cli/v2/pkg/cmdutil" - "github.com/cli/cli/v2/pkg/httpmock" - "github.com/cli/cli/v2/pkg/iostreams" - // "github.com/google/shlex" - "github.com/stretchr/testify/assert" - // "github.com/stretchr/testify/require" -) +// "github.com/cli/cli/v2/pkg/cmdutil" +// "github.com/cli/cli/v2/internal/ghrepo" +// "github.com/cli/cli/v2/pkg/httpmock" +// "github.com/cli/cli/v2/pkg/iostreams" +// "github.com/cli/cli/v2/pkg/prompt" + +// "github.com/google/shlex" +// "github.com/stretchr/testify/assert" +// "github.com/stretchr/testify/require" +// ) // func TestNewCmdRename(t *testing.T) { // testCases := []struct { @@ -69,71 +73,114 @@ import ( // } // } -func TestRenameRun(t *testing.T) { - testCases := []struct { - name string - opts RenameOptions - httpStubs func(*httpmock.Registry) - stdoutTTY bool - wantOut string - }{ - { - name: "owner repo change name tty", - opts: RenameOptions{ - oldRepoSelector: "OWNER/REPO", - newRepoSelector: "NEW_REPO", - flagRepo: true, - }, - wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.GraphQL(`query UserCurrent\b`), - httpmock.StringResponse(`{"data":{"viewer":{"login":"OWNER"}}}`)) - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - stdoutTTY: true, - }, - { - name: "owner repo change name notty", - opts: RenameOptions{ - oldRepoSelector: "OWNER/REPO", - newRepoSelector: "NEW_REPO", - flagRepo: true, - }, - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.GraphQL(`query UserCurrent\b`), - httpmock.StringResponse(`{"data":{"viewer":{"login":"OWNER"}}}`)) - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - stdoutTTY: false, - }, +// func TestRenameRun(t *testing.T) { +// testCases := []struct { +// name string +// opts RenameOptions +// httpStubs func(*httpmock.Registry) +// askStubs func(*prompt.AskStubber) +// wantOut string +// tty bool +// prompt bool +// }{ + // { + // name: "owner repo change name using flag", + // opts: RenameOptions{ + // oldRepoSelector: "OWNER/REPO", + // newRepoSelector: "NEW_REPO", + // flagRepo: true, + // }, + // wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", + // httpStubs: func(reg *httpmock.Registry) { + // reg.Register( + // httpmock.GraphQL(`query UserCurrent\b`), + // httpmock.StringResponse(`{"data":{"viewer":{"login":"OWNER"}}}`)) + // reg.Register( + // httpmock.REST("PATCH", "repos/OWNER/REPO"), + // httpmock.StatusStringResponse(204, "{}")) + // }, + // tty: true, + // }, + // { + // name: "owner repo change name prompt", + // opts: RenameOptions{ + // BaseRepo: func() (ghrepo.Interface, error) { + // return ghrepo.New("OWNER", "REPO"), nil + // }, + // oldRepoSelector: "NEW_REPO", + // }, + // wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", + // askStubs: func(q *prompt.AskStubber) { + // q.StubOne("NEW_REPO") + // }, + // httpStubs: func(reg *httpmock.Registry) { + // reg.Register( + // httpmock.REST("PATCH", "repos/OWNER/REPO"), + // httpmock.StatusStringResponse(204, "{}")) + // }, + // prompt: true, + // }, + // { + // name: "owner repo change name argument ", + // opts: RenameOptions{ + // newRepoSelector: "REPO", + // flagRepo: false, + // }, + // askStubs: func(q *prompt.AskStubber) { + // q.StubOne("OWNER/REPO") + // }, + // httpStubs: func(reg *httpmock.Registry) { + // reg.Register( + // httpmock.GraphQL(`query RepositoryInfo\b`), + // httpmock.StringResponse(` + // { + // "data": { + // "repository": { + // "id": "THE-ID", + // "name": "REPO", + // "owner": { + // "login": "OWNER" + // } + // } + // } + // }`)) + // reg.Register( + // httpmock.REST("PATCH", "repos/OWNER/REPO"), + // httpmock.StatusStringResponse(204, "{}")) + // }, + // }, } - for _, tt := range testCases { - reg := &httpmock.Registry{} - if tt.httpStubs != nil { - tt.httpStubs(reg) - } - tt.opts.HttpClient = func() (*http.Client, error) { - return &http.Client{Transport: reg}, nil - } +// for _, tt := range testCases { +// q, teardown := prompt.InitAskStubber() +// defer teardown() +// if tt.askStubs != nil { +// tt.askStubs(q) +// } - io, _, stdout, _ := iostreams.Test() - tt.opts.IO = io +// tt.opts.BaseRepo = func() (ghrepo.Interface, error) { +// repo, _ := ghrepo.FromFullName(tt.opts.oldRepoSelector) +// return repo, nil +// } - t.Run(tt.name, func(t *testing.T) { - defer reg.Verify(t) - io.SetStderrTTY(tt.stdoutTTY) - io.SetStdoutTTY(tt.stdoutTTY) +// reg := &httpmock.Registry{} +// if tt.httpStubs != nil { +// tt.httpStubs(reg) +// } +// tt.opts.HttpClient = func() (*http.Client, error) { +// return &http.Client{Transport: reg}, nil +// } - err := renameRun(&tt.opts) - assert.NoError(t, err) - assert.Equal(t, tt.wantOut, stdout.String()) - }) - } -} +// io, _, stdout, _ := iostreams.Test() +// io.SetStdinTTY(tt.tty) +// io.SetStdoutTTY(tt.tty) +// tt.opts.IO = io + +// t.Run(tt.name, func(t *testing.T) { +// defer reg.Verify(t) +// err := renameRun(&tt.opts) +// assert.NoError(t, err) +// assert.Equal(t, tt.wantOut, stdout.String()) +// }) +// } +// } From f5e963fd568bb5c7c0d8d1d16b73168302216fbf Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 20 Oct 2021 16:13:11 -0400 Subject: [PATCH 033/253] minor fix --- pkg/cmd/repo/rename/rename.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 4380cc5d8..05868155d 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -4,8 +4,6 @@ import ( "bytes" "encoding/json" "errors" - - // "errors" "fmt" "net/http" From 9003034c1c9488690eb3d9e91c931d897d289c2b Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 20 Oct 2021 16:17:29 -0400 Subject: [PATCH 034/253] lint fix --- pkg/cmd/repo/rename/rename.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 05868155d..43bd3c455 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -54,7 +54,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co With '-R', and two arguments the given repository is replaced with the new name `, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - if len(args) > 0 { + if len(args) > 0 { opts.newRepoSelector = args[0] } else { if !opts.IO.CanPrompt() { From 5ac744a68dac745c2ddd6cfc863de0252e86c5e9 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 20 Oct 2021 16:19:20 -0400 Subject: [PATCH 035/253] lint fix --- pkg/cmd/repo/rename/rename_test.go | 134 ++++++++++++++--------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index fb582b2e4..8b61b4ef3 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -83,73 +83,73 @@ package rename // tty bool // prompt bool // }{ - // { - // name: "owner repo change name using flag", - // opts: RenameOptions{ - // oldRepoSelector: "OWNER/REPO", - // newRepoSelector: "NEW_REPO", - // flagRepo: true, - // }, - // wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", - // httpStubs: func(reg *httpmock.Registry) { - // reg.Register( - // httpmock.GraphQL(`query UserCurrent\b`), - // httpmock.StringResponse(`{"data":{"viewer":{"login":"OWNER"}}}`)) - // reg.Register( - // httpmock.REST("PATCH", "repos/OWNER/REPO"), - // httpmock.StatusStringResponse(204, "{}")) - // }, - // tty: true, - // }, - // { - // name: "owner repo change name prompt", - // opts: RenameOptions{ - // BaseRepo: func() (ghrepo.Interface, error) { - // return ghrepo.New("OWNER", "REPO"), nil - // }, - // oldRepoSelector: "NEW_REPO", - // }, - // wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", - // askStubs: func(q *prompt.AskStubber) { - // q.StubOne("NEW_REPO") - // }, - // httpStubs: func(reg *httpmock.Registry) { - // reg.Register( - // httpmock.REST("PATCH", "repos/OWNER/REPO"), - // httpmock.StatusStringResponse(204, "{}")) - // }, - // prompt: true, - // }, - // { - // name: "owner repo change name argument ", - // opts: RenameOptions{ - // newRepoSelector: "REPO", - // flagRepo: false, - // }, - // askStubs: func(q *prompt.AskStubber) { - // q.StubOne("OWNER/REPO") - // }, - // httpStubs: func(reg *httpmock.Registry) { - // reg.Register( - // httpmock.GraphQL(`query RepositoryInfo\b`), - // httpmock.StringResponse(` - // { - // "data": { - // "repository": { - // "id": "THE-ID", - // "name": "REPO", - // "owner": { - // "login": "OWNER" - // } - // } - // } - // }`)) - // reg.Register( - // httpmock.REST("PATCH", "repos/OWNER/REPO"), - // httpmock.StatusStringResponse(204, "{}")) - // }, - // }, - } +// { +// name: "owner repo change name using flag", +// opts: RenameOptions{ +// oldRepoSelector: "OWNER/REPO", +// newRepoSelector: "NEW_REPO", +// flagRepo: true, +// }, +// wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", +// httpStubs: func(reg *httpmock.Registry) { +// reg.Register( +// httpmock.GraphQL(`query UserCurrent\b`), +// httpmock.StringResponse(`{"data":{"viewer":{"login":"OWNER"}}}`)) +// reg.Register( +// httpmock.REST("PATCH", "repos/OWNER/REPO"), +// httpmock.StatusStringResponse(204, "{}")) +// }, +// tty: true, +// }, +// { +// name: "owner repo change name prompt", +// opts: RenameOptions{ +// BaseRepo: func() (ghrepo.Interface, error) { +// return ghrepo.New("OWNER", "REPO"), nil +// }, +// oldRepoSelector: "NEW_REPO", +// }, +// wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", +// askStubs: func(q *prompt.AskStubber) { +// q.StubOne("NEW_REPO") +// }, +// httpStubs: func(reg *httpmock.Registry) { +// reg.Register( +// httpmock.REST("PATCH", "repos/OWNER/REPO"), +// httpmock.StatusStringResponse(204, "{}")) +// }, +// prompt: true, +// }, +// { +// name: "owner repo change name argument ", +// opts: RenameOptions{ +// newRepoSelector: "REPO", +// flagRepo: false, +// }, +// askStubs: func(q *prompt.AskStubber) { +// q.StubOne("OWNER/REPO") +// }, +// httpStubs: func(reg *httpmock.Registry) { +// reg.Register( +// httpmock.GraphQL(`query RepositoryInfo\b`), +// httpmock.StringResponse(` +// { +// "data": { +// "repository": { +// "id": "THE-ID", +// "name": "REPO", +// "owner": { +// "login": "OWNER" +// } +// } +// } +// }`)) +// reg.Register( +// httpmock.REST("PATCH", "repos/OWNER/REPO"), +// httpmock.StatusStringResponse(204, "{}")) +// }, +// }, +// } // for _, tt := range testCases { // q, teardown := prompt.InitAskStubber() From 5946c98096d0d2f418072a3d00df0c9c0766d759 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 20 Oct 2021 16:23:08 -0400 Subject: [PATCH 036/253] fixed forr real --- pkg/cmd/repo/rename/rename_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 8b61b4ef3..173a79bc0 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -82,7 +82,7 @@ package rename // wantOut string // tty bool // prompt bool -// }{ +// }{ // { // name: "owner repo change name using flag", // opts: RenameOptions{ From dd98c7f51f2bd984ea409dc58f071860a6681a0c Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Thu, 21 Oct 2021 11:27:02 -0400 Subject: [PATCH 037/253] added requested changes --- pkg/cmd/repo/rename/rename.go | 108 ++++----- pkg/cmd/repo/rename/rename_test.go | 351 +++++++++++++++-------------- 2 files changed, 225 insertions(+), 234 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 43bd3c455..2999aa211 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -8,6 +8,7 @@ import ( "net/http" "github.com/AlecAivazis/survey/v2" + "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/context" "github.com/cli/cli/v2/git" @@ -25,7 +26,6 @@ type RenameOptions struct { Config func() (config.Config, error) BaseRepo func() (ghrepo.Interface, error) Remotes func() (context.Remotes, error) - oldRepoSelector string newRepoSelector string } @@ -46,32 +46,39 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co } cmd := &cobra.Command{ - Use: "rename [-R] [] []", + Use: "rename [] []", Short: "Rename a repository", - Long: `Rename a GitHub repository + Long: heredoc.Doc(`Rename a GitHub repository + With no argument, the repository for the current directory is renamed using a prompt + With one argument, the repository of the current directory is renamed using the argument - With '-R', and two arguments the given repository is replaced with the new name `, + + With '-R', and two arguments the given repository is replaced with the new name`), Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { if len(args) > 0 { + opts.BaseRepo = f.BaseRepo opts.newRepoSelector = args[0] - } else { - if !opts.IO.CanPrompt() { - return &cmdutil.FlagError{ - Err: errors.New("could not prompt: proceed with prompt")} - } + } else if !opts.IO.CanPrompt() { + return &cmdutil.FlagError{ + Err: errors.New("could not prompt: proceed with a repo name")} + } + + if runf != nil { + return runf(opts) } return renameRun(opts) }, } - cmd.Flags().StringVarP(&opts.oldRepoSelector, "repo", "R", "", "pass in two arguments to rename a repository") + cmdutil.EnableRepoOverride(cmd, f) return cmd } func renameRun(opts *RenameOptions) error { + cs := opts.IO.ColorScheme() httpClient, err := opts.HttpClient() if err != nil { @@ -80,71 +87,48 @@ func renameRun(opts *RenameOptions) error { apiClient := api.NewClientFromHTTP(httpClient) var input renameRepo - var oldRepo ghrepo.Interface var newRepo ghrepo.Interface + var baseRemote *context.Remote + newRepoName := opts.newRepoSelector - if opts.oldRepoSelector == "" { - var newRepoName string - currRepo, err := opts.BaseRepo() + currRepo, err := opts.BaseRepo() + if err != nil { + return err + } + + if opts.newRepoSelector == "" { + err = prompt.SurveyAskOne( + &survey.Input{ + Message: "Rename current repo to: ", + }, + &newRepoName, + ) if err != nil { return err } - - if opts.newRepoSelector != "" && opts.oldRepoSelector == "" { - newRepoName = opts.newRepoSelector - } else { - err = prompt.SurveyAskOne( - &survey.Input{ - Message: "Rename current repo to: ", - }, - &newRepoName, - ) - if err != nil { - return err - } - } - - oldRepo = ghrepo.NewWithHost(currRepo.RepoOwner(), currRepo.RepoName(), currRepo.RepoHost()) - newRepo = ghrepo.NewWithHost(currRepo.RepoOwner(), newRepoName, currRepo.RepoHost()) - - input = renameRepo{ - RepoHost: currRepo.RepoHost(), - RepoOwner: currRepo.RepoOwner(), - RepoName: currRepo.RepoName(), - Name: newRepoName, - } - - } else { - oldRepoURL := opts.oldRepoSelector - newRepoName := opts.newRepoSelector - - currRepo, err := ghrepo.FromFullName(oldRepoURL) - if err != nil { - return fmt.Errorf("argument error: %w", err) - } - - oldRepo = ghrepo.NewWithHost(currRepo.RepoOwner(), currRepo.RepoName(), currRepo.RepoHost()) - - input = renameRepo{ - RepoHost: currRepo.RepoHost(), - RepoOwner: currRepo.RepoOwner(), - RepoName: currRepo.RepoName(), - Name: newRepoName, - } } - err = runRename(apiClient, oldRepo.RepoHost(), input) + input = renameRepo{ + RepoHost: currRepo.RepoHost(), + RepoOwner: currRepo.RepoOwner(), + RepoName: currRepo.RepoName(), + Name: newRepoName, + } + + newRepo = ghrepo.NewWithHost(currRepo.RepoOwner(), newRepoName, currRepo.RepoHost()) + + err = runRename(apiClient, currRepo.RepoHost(), input) if err != nil { return fmt.Errorf("API called failed: %s, please check your parameters", err) } - if opts.oldRepoSelector == "" { + if opts.newRepoSelector == "" { cfg, err := opts.Config() if err != nil { return err } - protocol, err := cfg.Get(oldRepo.RepoHost(), "git_protocol") + protocol, err := cfg.Get(currRepo.RepoHost(), "git_protocol") if err != nil { return err } @@ -154,7 +138,7 @@ func renameRun(opts *RenameOptions) error { return err } - baseRemote, err := remotes.FindByRepo(oldRepo.RepoOwner(), oldRepo.RepoName()) + baseRemote, err = remotes.FindByRepo(currRepo.RepoOwner(), currRepo.RepoName()) if err != nil { return err } @@ -168,8 +152,8 @@ func renameRun(opts *RenameOptions) error { if opts.IO.IsStdoutTTY() { fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), input.RepoOwner+"/"+input.Name) - if opts.oldRepoSelector == "" { - fmt.Fprintf(opts.IO.Out, `%s Updated the "origin" remote`, cs.SuccessIcon()) + if opts.newRepoSelector == "" { + fmt.Fprintf(opts.IO.Out, "%s Updated the %q remote", cs.SuccessIcon(), baseRemote.Name) } } diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 173a79bc0..f2598abac 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -1,186 +1,193 @@ package rename -// import ( -// "fmt" -// "net/http" -// "testing" +import ( + "bytes" + "net/http" + "testing" -// "github.com/cli/cli/v2/pkg/cmdutil" -// "github.com/cli/cli/v2/internal/ghrepo" -// "github.com/cli/cli/v2/pkg/httpmock" -// "github.com/cli/cli/v2/pkg/iostreams" -// "github.com/cli/cli/v2/pkg/prompt" + "github.com/cli/cli/v2/context" + "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/pkg/cmdutil" + "github.com/cli/cli/v2/pkg/httpmock" + "github.com/cli/cli/v2/pkg/iostreams" + "github.com/cli/cli/v2/pkg/prompt" + "github.com/google/shlex" + "github.com/stretchr/testify/assert" +) -// "github.com/google/shlex" -// "github.com/stretchr/testify/assert" -// "github.com/stretchr/testify/require" -// ) +func TestNewCmdRename(t *testing.T) { + testCases := []struct { + name string + input string + output RenameOptions + errMsg string + tty bool + wantErr bool + }{ + { + name: "no arguments no tty", + input: "", + errMsg: "could not prompt: proceed with prompt", + wantErr: true, + }, + { + name: "one argument", + input: "REPO", + output: RenameOptions{ + newRepoSelector: "REPO", + }, + }, + } + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + io, _, _, _ := iostreams.Test() + io.SetStdinTTY(tt.tty) + io.SetStdoutTTY(tt.tty) + f := &cmdutil.Factory{ + IOStreams: io, + } -// func TestNewCmdRename(t *testing.T) { -// testCases := []struct { -// name string -// args string -// wantOpts RenameOptions -// wantErr string -// }{ -// { -// name: "no arguments", -// args: "", -// wantErr: "cannot rename: repository argument required", -// }, -// { -// name: "correct argument", -// args: "OWNER/REPO REPOS", -// wantOpts: RenameOptions{ -// oldRepoSelector: "OWNER/REPO", -// newRepoSelector: "REPOS", -// }, -// }, -// } -// for _, tt := range testCases { -// t.Run(tt.name, func(t *testing.T) { -// io, stdin, stdout, stderr := iostreams.Test() -// fac := &cmdutil.Factory{IOStreams: io} + argv, err := shlex.Split(tt.input) + assert.NoError(t, err) + var gotOpts *RenameOptions + cmd := NewCmdRename(f, func(opts *RenameOptions) error { + gotOpts = opts + return nil + }) + cmd.SetArgs(argv) + cmd.SetIn(&bytes.Buffer{}) + cmd.SetOut(&bytes.Buffer{}) + cmd.SetErr(&bytes.Buffer{}) -// var opts *RenameOptions -// cmd := NewCmdRename(fac, func(co *RenameOptions) error { -// opts = co -// return nil -// }) + _, err = cmd.ExecuteC() + if tt.wantErr { + assert.Error(t, err) + assert.Equal(t, tt.errMsg, err.Error()) + return + } + assert.NoError(t, err) + assert.Equal(t, tt.output.newRepoSelector, gotOpts.newRepoSelector) + }) + } +} -// argv, err := shlex.Split(tt.args) -// require.NoError(t, err) -// cmd.SetArgs(argv) +func TestRenameRun(t *testing.T) { + testCases := []struct { + name string + opts RenameOptions + httpStubs func(*httpmock.Registry) + askStubs func(*prompt.AskStubber) + wantOut string + tty bool + prompt bool + }{ + { + name: "none argument", + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote", + askStubs: func(q *prompt.AskStubber) { + q.StubOne("NEW_REPO") + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + tty: true, + }, + { + name: "owner repo change name prompt", + opts: RenameOptions{ + BaseRepo: func() (ghrepo.Interface, error) { + return ghrepo.New("OWNER", "REPO"), nil + }, + }, + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", + askStubs: func(q *prompt.AskStubber) { + q.StubOne("NEW_REPO") + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + prompt: true, + }, + { + name: "owner repo change name argument ", + opts: RenameOptions{ + newRepoSelector: "REPO", + }, + askStubs: func(q *prompt.AskStubber) { + q.StubOne("OWNER/REPO") + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.GraphQL(`query RepositoryInfo\b`), + httpmock.StringResponse(` + { + "data": { + "repository": { + "id": "THE-ID", + "name": "REPO", + "owner": { + "login": "OWNER" + } + } + } + }`)) + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + }, + } -// cmd.SetIn(stdin) -// cmd.SetOut(stdout) -// cmd.SetErr(stderr) + for _, tt := range testCases { + q, teardown := prompt.InitAskStubber() + defer teardown() + if tt.askStubs != nil { + tt.askStubs(q) + } -// _, err = cmd.ExecuteC() -// if tt.wantErr != "" { -// assert.EqualError(t, err, tt.wantErr) -// return -// } else { -// assert.NoError(t, err) -// } + tt.opts.BaseRepo = func() (ghrepo.Interface, error) { + repo, _ := ghrepo.FromFullName("OWNER/REPO") + return repo, nil + } -// assert.Equal(t, "", stdout.String()) -// assert.Equal(t, "", stderr.String()) + tt.opts.Config = func() (config.Config, error) { + return config.NewBlankConfig(), nil + } -// assert.Equal(t, tt.wantOpts.oldRepoSelector, opts.oldRepoSelector) -// assert.Equal(t, tt.wantOpts.newRepoSelector, opts.newRepoSelector) -// }) -// } -// } + tt.opts.Remotes = func() (context.Remotes, error) { + r, _ := ghrepo.FromFullName("OWNER/REPO") + var remotes context.Remotes + remotes = append(remotes, &context.Remote{ + Remote: &git.Remote{Name: "origin"}, + Repo: r, + }) + return remotes, nil + } -// func TestRenameRun(t *testing.T) { -// testCases := []struct { -// name string -// opts RenameOptions -// httpStubs func(*httpmock.Registry) -// askStubs func(*prompt.AskStubber) -// wantOut string -// tty bool -// prompt bool -// }{ -// { -// name: "owner repo change name using flag", -// opts: RenameOptions{ -// oldRepoSelector: "OWNER/REPO", -// newRepoSelector: "NEW_REPO", -// flagRepo: true, -// }, -// wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", -// httpStubs: func(reg *httpmock.Registry) { -// reg.Register( -// httpmock.GraphQL(`query UserCurrent\b`), -// httpmock.StringResponse(`{"data":{"viewer":{"login":"OWNER"}}}`)) -// reg.Register( -// httpmock.REST("PATCH", "repos/OWNER/REPO"), -// httpmock.StatusStringResponse(204, "{}")) -// }, -// tty: true, -// }, -// { -// name: "owner repo change name prompt", -// opts: RenameOptions{ -// BaseRepo: func() (ghrepo.Interface, error) { -// return ghrepo.New("OWNER", "REPO"), nil -// }, -// oldRepoSelector: "NEW_REPO", -// }, -// wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", -// askStubs: func(q *prompt.AskStubber) { -// q.StubOne("NEW_REPO") -// }, -// httpStubs: func(reg *httpmock.Registry) { -// reg.Register( -// httpmock.REST("PATCH", "repos/OWNER/REPO"), -// httpmock.StatusStringResponse(204, "{}")) -// }, -// prompt: true, -// }, -// { -// name: "owner repo change name argument ", -// opts: RenameOptions{ -// newRepoSelector: "REPO", -// flagRepo: false, -// }, -// askStubs: func(q *prompt.AskStubber) { -// q.StubOne("OWNER/REPO") -// }, -// httpStubs: func(reg *httpmock.Registry) { -// reg.Register( -// httpmock.GraphQL(`query RepositoryInfo\b`), -// httpmock.StringResponse(` -// { -// "data": { -// "repository": { -// "id": "THE-ID", -// "name": "REPO", -// "owner": { -// "login": "OWNER" -// } -// } -// } -// }`)) -// reg.Register( -// httpmock.REST("PATCH", "repos/OWNER/REPO"), -// httpmock.StatusStringResponse(204, "{}")) -// }, -// }, -// } + reg := &httpmock.Registry{} + if tt.httpStubs != nil { + tt.httpStubs(reg) + } + tt.opts.HttpClient = func() (*http.Client, error) { + return &http.Client{Transport: reg}, nil + } -// for _, tt := range testCases { -// q, teardown := prompt.InitAskStubber() -// defer teardown() -// if tt.askStubs != nil { -// tt.askStubs(q) -// } + io, _, stdout, _ := iostreams.Test() + io.SetStdinTTY(tt.tty) + io.SetStdoutTTY(tt.tty) + tt.opts.IO = io -// tt.opts.BaseRepo = func() (ghrepo.Interface, error) { -// repo, _ := ghrepo.FromFullName(tt.opts.oldRepoSelector) -// return repo, nil -// } - -// reg := &httpmock.Registry{} -// if tt.httpStubs != nil { -// tt.httpStubs(reg) -// } -// tt.opts.HttpClient = func() (*http.Client, error) { -// return &http.Client{Transport: reg}, nil -// } - -// io, _, stdout, _ := iostreams.Test() -// io.SetStdinTTY(tt.tty) -// io.SetStdoutTTY(tt.tty) -// tt.opts.IO = io - -// t.Run(tt.name, func(t *testing.T) { -// defer reg.Verify(t) -// err := renameRun(&tt.opts) -// assert.NoError(t, err) -// assert.Equal(t, tt.wantOut, stdout.String()) -// }) -// } -// } + t.Run(tt.name, func(t *testing.T) { + defer reg.Verify(t) + err := renameRun(&tt.opts) + assert.NoError(t, err) + assert.Equal(t, tt.wantOut, stdout.String()) + }) + } +} From 624f19764d2aff7653e726d33955297a9a1df30e Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Thu, 21 Oct 2021 11:28:18 -0400 Subject: [PATCH 038/253] minor fix --- pkg/cmd/repo/rename/rename.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 2999aa211..745d1b7a5 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -78,8 +78,6 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co } func renameRun(opts *RenameOptions) error { - - cs := opts.IO.ColorScheme() httpClient, err := opts.HttpClient() if err != nil { return err @@ -151,6 +149,7 @@ func renameRun(opts *RenameOptions) error { } if opts.IO.IsStdoutTTY() { + cs := opts.IO.ColorScheme() fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), input.RepoOwner+"/"+input.Name) if opts.newRepoSelector == "" { fmt.Fprintf(opts.IO.Out, "%s Updated the %q remote", cs.SuccessIcon(), baseRemote.Name) From d378dc84c6fd2acd1b7bf8b57b540bddde9fefff Mon Sep 17 00:00:00 2001 From: Parth Date: Thu, 21 Oct 2021 15:17:15 -0400 Subject: [PATCH 039/253] final changes made --- pkg/cmd/repo/rename/rename.go | 41 +++++++++++++++-------------------- pkg/cmd/repo/repo.go | 2 ++ 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 745d1b7a5..4e24a183c 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -26,6 +26,7 @@ type RenameOptions struct { Config func() (config.Config, error) BaseRepo func() (ghrepo.Interface, error) Remotes func() (context.Remotes, error) + HasRepoOverride bool newRepoSelector string } @@ -40,7 +41,6 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co opts := &RenameOptions{ IO: f.IOStreams, HttpClient: f.HttpClient, - BaseRepo: f.BaseRepo, Remotes: f.Remotes, Config: f.Config, } @@ -57,8 +57,10 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co With '-R', and two arguments the given repository is replaced with the new name`), Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + opts.BaseRepo = f.BaseRepo + opts.HasRepoOverride = cmd.Flags().Changed("repo") + if len(args) > 0 { - opts.BaseRepo = f.BaseRepo opts.newRepoSelector = args[0] } else if !opts.IO.CanPrompt() { return &cmdutil.FlagError{ @@ -87,6 +89,7 @@ func renameRun(opts *RenameOptions) error { var input renameRepo var newRepo ghrepo.Interface var baseRemote *context.Remote + remoteUpdateError := false newRepoName := opts.newRepoSelector currRepo, err := opts.BaseRepo() @@ -94,10 +97,10 @@ func renameRun(opts *RenameOptions) error { return err } - if opts.newRepoSelector == "" { + if newRepoName == "" { err = prompt.SurveyAskOne( &survey.Input{ - Message: "Rename current repo to: ", + Message: fmt.Sprintf("Rename %s to: ", currRepo.RepoOwner()+"/"+currRepo.RepoName()), }, &newRepoName, ) @@ -120,39 +123,29 @@ func renameRun(opts *RenameOptions) error { return fmt.Errorf("API called failed: %s, please check your parameters", err) } - if opts.newRepoSelector == "" { + if !opts.HasRepoOverride { cfg, err := opts.Config() if err != nil { return err } - - protocol, err := cfg.Get(currRepo.RepoHost(), "git_protocol") - if err != nil { - return err - } - - remotes, err := opts.Remotes() - if err != nil { - return err - } - - baseRemote, err = remotes.FindByRepo(currRepo.RepoOwner(), currRepo.RepoName()) - if err != nil { - return err - } - + + protocol, _ := cfg.Get(currRepo.RepoHost(), "git_protocol") + remotes, _ := opts.Remotes() + baseRemote, _ = remotes.FindByRepo(currRepo.RepoOwner(), currRepo.RepoName()) remoteURL := ghrepo.FormatRemoteURL(newRepo, protocol) err = git.UpdateRemoteURL(baseRemote.Name, remoteURL) if err != nil { - return err + cs := opts.IO.ColorScheme() + remoteUpdateError = true + fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s' \n", cs.WarningIcon(), err) } } if opts.IO.IsStdoutTTY() { cs := opts.IO.ColorScheme() fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), input.RepoOwner+"/"+input.Name) - if opts.newRepoSelector == "" { - fmt.Fprintf(opts.IO.Out, "%s Updated the %q remote", cs.SuccessIcon(), baseRemote.Name) + if !opts.HasRepoOverride && !remoteUpdateError { + fmt.Fprintf(opts.IO.Out, "%s Updated the %q remote \n", cs.SuccessIcon(), baseRemote.Name) } } diff --git a/pkg/cmd/repo/repo.go b/pkg/cmd/repo/repo.go index ec16d731b..3a5bddd82 100644 --- a/pkg/cmd/repo/repo.go +++ b/pkg/cmd/repo/repo.go @@ -37,6 +37,8 @@ func NewCmdRepo(f *cmdutil.Factory) *cobra.Command { }, } + cmdutil.EnableRepoOverride(cmd, f) + cmd.AddCommand(repoViewCmd.NewCmdView(f, nil)) cmd.AddCommand(repoForkCmd.NewCmdFork(f, nil)) cmd.AddCommand(repoCloneCmd.NewCmdClone(f, nil)) From de1d860bce15a1a223faedc22a7d40f01aa172bc Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Thu, 21 Oct 2021 17:33:24 -0400 Subject: [PATCH 040/253] lint fix --- pkg/cmd/repo/rename/rename.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 4e24a183c..af6620ea5 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -89,7 +89,7 @@ func renameRun(opts *RenameOptions) error { var input renameRepo var newRepo ghrepo.Interface var baseRemote *context.Remote - remoteUpdateError := false + var remoteUpdateError error newRepoName := opts.newRepoSelector currRepo, err := opts.BaseRepo() @@ -128,15 +128,14 @@ func renameRun(opts *RenameOptions) error { if err != nil { return err } - + protocol, _ := cfg.Get(currRepo.RepoHost(), "git_protocol") remotes, _ := opts.Remotes() baseRemote, _ = remotes.FindByRepo(currRepo.RepoOwner(), currRepo.RepoName()) remoteURL := ghrepo.FormatRemoteURL(newRepo, protocol) - err = git.UpdateRemoteURL(baseRemote.Name, remoteURL) - if err != nil { + remoteUpdateError = git.UpdateRemoteURL(baseRemote.Name, remoteURL) + if remoteUpdateError != nil { cs := opts.IO.ColorScheme() - remoteUpdateError = true fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s' \n", cs.WarningIcon(), err) } } @@ -144,11 +143,10 @@ func renameRun(opts *RenameOptions) error { if opts.IO.IsStdoutTTY() { cs := opts.IO.ColorScheme() fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), input.RepoOwner+"/"+input.Name) - if !opts.HasRepoOverride && !remoteUpdateError { + if !opts.HasRepoOverride && remoteUpdateError == nil { fmt.Fprintf(opts.IO.Out, "%s Updated the %q remote \n", cs.SuccessIcon(), baseRemote.Name) } } - return nil } From dc0b9bc6b08e4dae76325ccc76096efc345ca8e1 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 22 Oct 2021 12:41:06 -0400 Subject: [PATCH 041/253] finished up tests --- pkg/cmd/repo/rename/rename_test.go | 172 ++++++++++++++++------------- 1 file changed, 97 insertions(+), 75 deletions(-) diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index f2598abac..9bcbaa6aa 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -1,7 +1,6 @@ package rename import ( - "bytes" "net/http" "testing" @@ -9,69 +8,74 @@ import ( "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/pkg/cmdutil" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" "github.com/cli/cli/v2/pkg/prompt" - "github.com/google/shlex" "github.com/stretchr/testify/assert" ) -func TestNewCmdRename(t *testing.T) { - testCases := []struct { - name string - input string - output RenameOptions - errMsg string - tty bool - wantErr bool - }{ - { - name: "no arguments no tty", - input: "", - errMsg: "could not prompt: proceed with prompt", - wantErr: true, - }, - { - name: "one argument", - input: "REPO", - output: RenameOptions{ - newRepoSelector: "REPO", - }, - }, - } - for _, tt := range testCases { - t.Run(tt.name, func(t *testing.T) { - io, _, _, _ := iostreams.Test() - io.SetStdinTTY(tt.tty) - io.SetStdoutTTY(tt.tty) - f := &cmdutil.Factory{ - IOStreams: io, - } +// func TestNewCmdRename(t *testing.T) { +// testCases := []struct { +// name string +// input string +// output RenameOptions +// errMsg string +// tty bool +// wantErr bool +// }{ +// { +// name: "no arguments no tty", +// input: "", +// errMsg: "could not prompt: proceed with prompt", +// wantErr: true, +// tty: false, +// }, +// { +// name: "one argument", +// input: "REPO", +// output: RenameOptions{ +// newRepoSelector: "REPO", +// }, +// }, +// { +// name: "full flag argument", +// input: "--repo OWNER/REPO NEW_REPO", +// output: RenameOptions{ +// newRepoSelector: "NEW_REPO", +// }, +// }, +// } +// for _, tt := range testCases { +// t.Run(tt.name, func(t *testing.T) { +// io, _, _, _ := iostreams.Test() +// io.SetStdinTTY(tt.tty) +// io.SetStdoutTTY(tt.tty) +// f := &cmdutil.Factory{ +// IOStreams: io, +// } - argv, err := shlex.Split(tt.input) - assert.NoError(t, err) - var gotOpts *RenameOptions - cmd := NewCmdRename(f, func(opts *RenameOptions) error { - gotOpts = opts - return nil - }) - cmd.SetArgs(argv) - cmd.SetIn(&bytes.Buffer{}) - cmd.SetOut(&bytes.Buffer{}) - cmd.SetErr(&bytes.Buffer{}) +// argv, err := shlex.Split(tt.input) +// assert.NoError(t, err) +// var gotOpts *RenameOptions +// cmd := NewCmdRename(f, func(opts *RenameOptions) error { +// gotOpts = opts +// return nil +// }) +// cmd.SetArgs(argv) +// cmd.SetIn(&bytes.Buffer{}) +// cmd.SetOut(&bytes.Buffer{}) +// cmd.SetErr(&bytes.Buffer{}) - _, err = cmd.ExecuteC() - if tt.wantErr { - assert.Error(t, err) - assert.Equal(t, tt.errMsg, err.Error()) - return - } - assert.NoError(t, err) - assert.Equal(t, tt.output.newRepoSelector, gotOpts.newRepoSelector) - }) - } -} +// _, err = cmd.ExecuteC() +// if tt.wantErr { +// assert.Error(t, err) +// return +// } +// assert.NoError(t, err) +// assert.Equal(t, tt.output.newRepoSelector, gotOpts.newRepoSelector) +// }) +// } +// } func TestRenameRun(t *testing.T) { testCases := []struct { @@ -85,7 +89,7 @@ func TestRenameRun(t *testing.T) { }{ { name: "none argument", - wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote", + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", askStubs: func(q *prompt.AskStubber) { q.StubOne("NEW_REPO") }, @@ -103,7 +107,7 @@ func TestRenameRun(t *testing.T) { return ghrepo.New("OWNER", "REPO"), nil }, }, - wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", askStubs: func(q *prompt.AskStubber) { q.StubOne("NEW_REPO") }, @@ -112,31 +116,49 @@ func TestRenameRun(t *testing.T) { httpmock.REST("PATCH", "repos/OWNER/REPO"), httpmock.StatusStringResponse(204, "{}")) }, - prompt: true, + tty: true, }, { - name: "owner repo change name argument ", + name: "owner repo change name prompt no tty", opts: RenameOptions{ - newRepoSelector: "REPO", + BaseRepo: func() (ghrepo.Interface, error) { + return ghrepo.New("OWNER", "REPO"), nil + }, }, askStubs: func(q *prompt.AskStubber) { - q.StubOne("OWNER/REPO") + q.StubOne("NEW_REPO") }, httpStubs: func(reg *httpmock.Registry) { reg.Register( - httpmock.GraphQL(`query RepositoryInfo\b`), - httpmock.StringResponse(` - { - "data": { - "repository": { - "id": "THE-ID", - "name": "REPO", - "owner": { - "login": "OWNER" - } - } - } - }`)) + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + }, + { + name: "owner repo change name argument tty", + opts: RenameOptions{ + BaseRepo: func() (ghrepo.Interface, error) { + return ghrepo.New("OWNER", "REPO"), nil + }, + newRepoSelector: "NEW_REPO", + }, + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + tty: true, + }, + { + name: "owner repo change name argument no tty", + opts: RenameOptions{ + BaseRepo: func() (ghrepo.Interface, error) { + return ghrepo.New("OWNER", "REPO"), nil + }, + newRepoSelector: "REPO", + }, + httpStubs: func(reg *httpmock.Registry) { reg.Register( httpmock.REST("PATCH", "repos/OWNER/REPO"), httpmock.StatusStringResponse(204, "{}")) From 4e30fd5ba42b725501f8e56e8a231fc4967595b5 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 22 Oct 2021 12:43:23 -0400 Subject: [PATCH 042/253] uncommented tests --- pkg/cmd/repo/rename/rename_test.go | 123 +++++++++++++++-------------- 1 file changed, 63 insertions(+), 60 deletions(-) diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 9bcbaa6aa..b95146b5c 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -1,6 +1,7 @@ package rename import ( + "bytes" "net/http" "testing" @@ -8,74 +9,76 @@ import ( "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/pkg/cmdutil" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" "github.com/cli/cli/v2/pkg/prompt" + "github.com/google/shlex" "github.com/stretchr/testify/assert" ) -// func TestNewCmdRename(t *testing.T) { -// testCases := []struct { -// name string -// input string -// output RenameOptions -// errMsg string -// tty bool -// wantErr bool -// }{ -// { -// name: "no arguments no tty", -// input: "", -// errMsg: "could not prompt: proceed with prompt", -// wantErr: true, -// tty: false, -// }, -// { -// name: "one argument", -// input: "REPO", -// output: RenameOptions{ -// newRepoSelector: "REPO", -// }, -// }, -// { -// name: "full flag argument", -// input: "--repo OWNER/REPO NEW_REPO", -// output: RenameOptions{ -// newRepoSelector: "NEW_REPO", -// }, -// }, -// } -// for _, tt := range testCases { -// t.Run(tt.name, func(t *testing.T) { -// io, _, _, _ := iostreams.Test() -// io.SetStdinTTY(tt.tty) -// io.SetStdoutTTY(tt.tty) -// f := &cmdutil.Factory{ -// IOStreams: io, -// } +func TestNewCmdRename(t *testing.T) { + testCases := []struct { + name string + input string + output RenameOptions + errMsg string + tty bool + wantErr bool + }{ + { + name: "no arguments no tty", + input: "", + errMsg: "could not prompt: proceed with prompt", + wantErr: true, + tty: false, + }, + { + name: "one argument", + input: "REPO", + output: RenameOptions{ + newRepoSelector: "REPO", + }, + }, + { + name: "full flag argument", + input: "--repo OWNER/REPO NEW_REPO", + output: RenameOptions{ + newRepoSelector: "NEW_REPO", + }, + }, + } + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + io, _, _, _ := iostreams.Test() + io.SetStdinTTY(tt.tty) + io.SetStdoutTTY(tt.tty) + f := &cmdutil.Factory{ + IOStreams: io, + } -// argv, err := shlex.Split(tt.input) -// assert.NoError(t, err) -// var gotOpts *RenameOptions -// cmd := NewCmdRename(f, func(opts *RenameOptions) error { -// gotOpts = opts -// return nil -// }) -// cmd.SetArgs(argv) -// cmd.SetIn(&bytes.Buffer{}) -// cmd.SetOut(&bytes.Buffer{}) -// cmd.SetErr(&bytes.Buffer{}) + argv, err := shlex.Split(tt.input) + assert.NoError(t, err) + var gotOpts *RenameOptions + cmd := NewCmdRename(f, func(opts *RenameOptions) error { + gotOpts = opts + return nil + }) + cmd.SetArgs(argv) + cmd.SetIn(&bytes.Buffer{}) + cmd.SetOut(&bytes.Buffer{}) + cmd.SetErr(&bytes.Buffer{}) -// _, err = cmd.ExecuteC() -// if tt.wantErr { -// assert.Error(t, err) -// return -// } -// assert.NoError(t, err) -// assert.Equal(t, tt.output.newRepoSelector, gotOpts.newRepoSelector) -// }) -// } -// } + _, err = cmd.ExecuteC() + if tt.wantErr { + assert.Error(t, err) + return + } + assert.NoError(t, err) + assert.Equal(t, tt.output.newRepoSelector, gotOpts.newRepoSelector) + }) + } +} func TestRenameRun(t *testing.T) { testCases := []struct { From 1d382fa7caec68d7b541bebdfdf4a7f3a0dcb1c0 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Fri, 22 Oct 2021 12:46:07 -0400 Subject: [PATCH 043/253] lint fix? --- pkg/cmd/repo/rename/rename.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index af6620ea5..dc4f69556 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -63,8 +63,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co if len(args) > 0 { opts.newRepoSelector = args[0] } else if !opts.IO.CanPrompt() { - return &cmdutil.FlagError{ - Err: errors.New("could not prompt: proceed with a repo name")} + return &cmdutil.FlagError{Err: errors.New("could not prompt: proceed with a repo name")} } if runf != nil { From 96fe7616482f479954911d993efd336ea41ae45f Mon Sep 17 00:00:00 2001 From: Tobias Gruetzmacher Date: Mon, 25 Oct 2021 20:50:11 +0200 Subject: [PATCH 044/253] Don't use gpg in Debian instruction It's not really necessary, since apt can work with the keyring file hosted on cli.github.com. --- docs/install_linux.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/install_linux.md b/docs/install_linux.md index c14273d5d..b01cf5081 100644 --- a/docs/install_linux.md +++ b/docs/install_linux.md @@ -14,14 +14,12 @@ our release schedule. Install: ```bash -curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg +curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null sudo apt update sudo apt install gh ``` -**Note**: If you get the error _"gpg: failed to start the dirmngr '/usr/bin/dirmngr': No such file or directory"_, try installing the `dirmngr` package: `sudo apt install dirmngr`. - Upgrade: ```bash From b4d2bce6fcf15704fc0cdc8faba17f758a6e3899 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Mon, 25 Oct 2021 17:07:48 -0400 Subject: [PATCH 045/253] res comments --- pkg/cmd/repo/rename/http.go | 54 ++++++++++ pkg/cmd/repo/rename/http_test.go | 168 +++++++++++++++++++++++++++++ pkg/cmd/repo/rename/rename.go | 67 +++--------- pkg/cmd/repo/rename/rename_test.go | 144 ------------------------- 4 files changed, 238 insertions(+), 195 deletions(-) create mode 100644 pkg/cmd/repo/rename/http.go create mode 100644 pkg/cmd/repo/rename/http_test.go diff --git a/pkg/cmd/repo/rename/http.go b/pkg/cmd/repo/rename/http.go new file mode 100644 index 000000000..bc0bfd0ab --- /dev/null +++ b/pkg/cmd/repo/rename/http.go @@ -0,0 +1,54 @@ +package rename + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + + "github.com/cli/cli/v2/api" + "github.com/cli/cli/v2/internal/ghinstance" + "github.com/cli/cli/v2/internal/ghrepo" +) + +type renameRepo struct { + RepoHost string + RepoOwner string + RepoName string + Name string `json:"name,omitempty"` +} + +func runRename(client *http.Client, repo ghrepo.Interface, newRepoName string) error { + + input := renameRepo{ + RepoHost: repo.RepoHost(), + RepoOwner: repo.RepoOwner(), + RepoName: repo.RepoName(), + Name: newRepoName, + } + + body, err := json.Marshal(input) + if err != nil { + return err + } + + path := fmt.Sprintf("%srepos/%s", + ghinstance.RESTPrefix(repo.RepoHost()), + ghrepo.FullName(repo)) + + request, err := http.NewRequest("PATCH", path, bytes.NewBuffer(body)) + if err != nil { + return err + } + + response, err := client.Do(request) + if err != nil { + return err + } + defer response.Body.Close() + + if response.StatusCode > 299 { + return api.HandleHTTPError(response) + } + return nil +} diff --git a/pkg/cmd/repo/rename/http_test.go b/pkg/cmd/repo/rename/http_test.go new file mode 100644 index 000000000..56e8dc365 --- /dev/null +++ b/pkg/cmd/repo/rename/http_test.go @@ -0,0 +1,168 @@ +package rename + +import ( + "net/http" + "testing" + + "github.com/cli/cli/v2/context" + "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" + "github.com/cli/cli/v2/pkg/httpmock" + "github.com/cli/cli/v2/pkg/iostreams" + "github.com/cli/cli/v2/pkg/prompt" + "github.com/stretchr/testify/assert" +) + +func TestRenameRun(t *testing.T) { + testCases := []struct { + name string + opts RenameOptions + httpStubs func(*httpmock.Registry) + execStubs func(*run.CommandStubber) + askStubs func(*prompt.AskStubber) + wantOut string + tty bool + prompt bool + }{ + { + name: "none argument", + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", + askStubs: func(q *prompt.AskStubber) { + q.StubOne("NEW_REPO") + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + execStubs: func(cs *run.CommandStubber) { + cs.Register(`git remote set-url origin https://github.com/OWNER/REPO.git`, 0, "") + }, + tty: true, + }, + { + name: "owner repo change name prompt", + opts: RenameOptions{ + BaseRepo: func() (ghrepo.Interface, error) { + return ghrepo.New("OWNER", "REPO"), nil + }, + }, + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", + askStubs: func(q *prompt.AskStubber) { + q.StubOne("NEW_REPO") + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + execStubs: func(cs *run.CommandStubber) { + cs.Register(`git remote set-url origin https://github.com/OWNER/REPO.git`, 0, "") + }, + tty: true, + }, + { + name: "owner repo change name prompt no tty", + opts: RenameOptions{ + BaseRepo: func() (ghrepo.Interface, error) { + return ghrepo.New("OWNER", "REPO"), nil + }, + }, + askStubs: func(q *prompt.AskStubber) { + q.StubOne("NEW_REPO") + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + execStubs: func(cs *run.CommandStubber) { + cs.Register(`git remote set-url origin https://github.com/OWNER/REPO.git`, 0, "") + }, + }, + { + name: "owner repo change name argument tty", + opts: RenameOptions{ + BaseRepo: func() (ghrepo.Interface, error) { + return ghrepo.New("OWNER", "REPO"), nil + }, + newRepoSelector: "NEW_REPO", + }, + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + execStubs: func(cs *run.CommandStubber) { + cs.Register(`git remote set-url origin https://github.com/OWNER/REPO.git`, 0, "") + }, + tty: true, + }, + { + name: "owner repo change name argument no tty", + opts: RenameOptions{ + BaseRepo: func() (ghrepo.Interface, error) { + return ghrepo.New("OWNER", "REPO"), nil + }, + newRepoSelector: "REPO", + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + execStubs: func(cs *run.CommandStubber) { + cs.Register(`git remote set-url origin https://github.com/OWNER/REPO.git`, 0, "") + }, + }, + } + + for _, tt := range testCases { + q, teardown := prompt.InitAskStubber() + defer teardown() + if tt.askStubs != nil { + tt.askStubs(q) + } + + repo, _ := ghrepo.FromFullName("OWNER/REPO") + tt.opts.BaseRepo = func() (ghrepo.Interface, error) { + return repo, nil + } + + tt.opts.Config = func() (config.Config, error) { + return config.NewBlankConfig(), nil + } + + tt.opts.Remotes = func() (context.Remotes, error) { + return []*context.Remote{ + { + Remote: &git.Remote{Name: "origin"}, + Repo: repo, + }, + }, nil + } + + reg := &httpmock.Registry{} + if tt.httpStubs != nil { + tt.httpStubs(reg) + } + tt.opts.HttpClient = func() (*http.Client, error) { + return &http.Client{Transport: reg}, nil + } + + io, _, stdout, _ := iostreams.Test() + io.SetStdinTTY(tt.tty) + io.SetStdoutTTY(tt.tty) + tt.opts.IO = io + + t.Run(tt.name, func(t *testing.T) { + defer reg.Verify(t) + err := renameRun(&tt.opts) + assert.NoError(t, err) + assert.Equal(t, tt.wantOut, stdout.String()) + }) + } +} diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index dc4f69556..6a961067a 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -1,15 +1,12 @@ package rename import ( - "bytes" - "encoding/json" "errors" "fmt" "net/http" "github.com/AlecAivazis/survey/v2" "github.com/MakeNowJust/heredoc" - "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/context" "github.com/cli/cli/v2/git" "github.com/cli/cli/v2/internal/config" @@ -30,13 +27,6 @@ type RenameOptions struct { newRepoSelector string } -type renameRepo struct { - RepoHost string - RepoOwner string - RepoName string - Name string `json:"name,omitempty"` -} - func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Command { opts := &RenameOptions{ IO: f.IOStreams, @@ -46,15 +36,11 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co } cmd := &cobra.Command{ - Use: "rename [] []", + Use: "rename []", Short: "Rename a repository", Long: heredoc.Doc(`Rename a GitHub repository - - With no argument, the repository for the current directory is renamed using a prompt - - With one argument, the repository of the current directory is renamed using the argument - - With '-R', and two arguments the given repository is replaced with the new name`), + + By default, renames the current repository otherwise rename the specified repository.`), Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { opts.BaseRepo = f.BaseRepo @@ -63,7 +49,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co if len(args) > 0 { opts.newRepoSelector = args[0] } else if !opts.IO.CanPrompt() { - return &cmdutil.FlagError{Err: errors.New("could not prompt: proceed with a repo name")} + return &cmdutil.FlagError{Err: errors.New("could not prompt: new name required when not running interactively")} } if runf != nil { @@ -83,12 +69,9 @@ func renameRun(opts *RenameOptions) error { if err != nil { return err } - apiClient := api.NewClientFromHTTP(httpClient) - var input renameRepo var newRepo ghrepo.Interface var baseRemote *context.Remote - var remoteUpdateError error newRepoName := opts.newRepoSelector currRepo, err := opts.BaseRepo() @@ -99,7 +82,7 @@ func renameRun(opts *RenameOptions) error { if newRepoName == "" { err = prompt.SurveyAskOne( &survey.Input{ - Message: fmt.Sprintf("Rename %s to: ", currRepo.RepoOwner()+"/"+currRepo.RepoName()), + Message: fmt.Sprintf("Rename %s to: ", ghrepo.FullName(currRepo)), }, &newRepoName, ) @@ -108,21 +91,20 @@ func renameRun(opts *RenameOptions) error { } } - input = renameRepo{ - RepoHost: currRepo.RepoHost(), - RepoOwner: currRepo.RepoOwner(), - RepoName: currRepo.RepoName(), - Name: newRepoName, - } - newRepo = ghrepo.NewWithHost(currRepo.RepoOwner(), newRepoName, currRepo.RepoHost()) - err = runRename(apiClient, currRepo.RepoHost(), input) + err = runRename(httpClient, currRepo, newRepoName) if err != nil { - return fmt.Errorf("API called failed: %s, please check your parameters", err) + return fmt.Errorf("API called failed: %s", err) + } + + if opts.IO.IsStdoutTTY() { + cs := opts.IO.ColorScheme() + fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), ghrepo.FullName(newRepo)) } if !opts.HasRepoOverride { + cs := opts.IO.ColorScheme() cfg, err := opts.Config() if err != nil { return err @@ -132,30 +114,13 @@ func renameRun(opts *RenameOptions) error { remotes, _ := opts.Remotes() baseRemote, _ = remotes.FindByRepo(currRepo.RepoOwner(), currRepo.RepoName()) remoteURL := ghrepo.FormatRemoteURL(newRepo, protocol) - remoteUpdateError = git.UpdateRemoteURL(baseRemote.Name, remoteURL) - if remoteUpdateError != nil { - cs := opts.IO.ColorScheme() + err = git.UpdateRemoteURL(baseRemote.Name, remoteURL) + if err != nil { fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s' \n", cs.WarningIcon(), err) } - } - - if opts.IO.IsStdoutTTY() { - cs := opts.IO.ColorScheme() - fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), input.RepoOwner+"/"+input.Name) - if !opts.HasRepoOverride && remoteUpdateError == nil { + if opts.IO.IsStdoutTTY() { fmt.Fprintf(opts.IO.Out, "%s Updated the %q remote \n", cs.SuccessIcon(), baseRemote.Name) } } return nil } - -func runRename(apiClient *api.Client, hostname string, input renameRepo) error { - path := fmt.Sprintf("repos/%s/%s", input.RepoOwner, input.RepoName) - body := &bytes.Buffer{} - enc := json.NewEncoder(body) - if err := enc.Encode(input); err != nil { - return err - } - - return apiClient.REST(hostname, "PATCH", path, body, nil) -} diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index b95146b5c..1a2d507df 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -2,17 +2,10 @@ package rename import ( "bytes" - "net/http" "testing" - "github.com/cli/cli/v2/context" - "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/pkg/cmdutil" - "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" "github.com/google/shlex" "github.com/stretchr/testify/assert" ) @@ -79,140 +72,3 @@ func TestNewCmdRename(t *testing.T) { }) } } - -func TestRenameRun(t *testing.T) { - testCases := []struct { - name string - opts RenameOptions - httpStubs func(*httpmock.Registry) - askStubs func(*prompt.AskStubber) - wantOut string - tty bool - prompt bool - }{ - { - name: "none argument", - wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", - askStubs: func(q *prompt.AskStubber) { - q.StubOne("NEW_REPO") - }, - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - tty: true, - }, - { - name: "owner repo change name prompt", - opts: RenameOptions{ - BaseRepo: func() (ghrepo.Interface, error) { - return ghrepo.New("OWNER", "REPO"), nil - }, - }, - wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", - askStubs: func(q *prompt.AskStubber) { - q.StubOne("NEW_REPO") - }, - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - tty: true, - }, - { - name: "owner repo change name prompt no tty", - opts: RenameOptions{ - BaseRepo: func() (ghrepo.Interface, error) { - return ghrepo.New("OWNER", "REPO"), nil - }, - }, - askStubs: func(q *prompt.AskStubber) { - q.StubOne("NEW_REPO") - }, - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - }, - { - name: "owner repo change name argument tty", - opts: RenameOptions{ - BaseRepo: func() (ghrepo.Interface, error) { - return ghrepo.New("OWNER", "REPO"), nil - }, - newRepoSelector: "NEW_REPO", - }, - wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - tty: true, - }, - { - name: "owner repo change name argument no tty", - opts: RenameOptions{ - BaseRepo: func() (ghrepo.Interface, error) { - return ghrepo.New("OWNER", "REPO"), nil - }, - newRepoSelector: "REPO", - }, - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - }, - } - - for _, tt := range testCases { - q, teardown := prompt.InitAskStubber() - defer teardown() - if tt.askStubs != nil { - tt.askStubs(q) - } - - tt.opts.BaseRepo = func() (ghrepo.Interface, error) { - repo, _ := ghrepo.FromFullName("OWNER/REPO") - return repo, nil - } - - tt.opts.Config = func() (config.Config, error) { - return config.NewBlankConfig(), nil - } - - tt.opts.Remotes = func() (context.Remotes, error) { - r, _ := ghrepo.FromFullName("OWNER/REPO") - var remotes context.Remotes - remotes = append(remotes, &context.Remote{ - Remote: &git.Remote{Name: "origin"}, - Repo: r, - }) - return remotes, nil - } - - reg := &httpmock.Registry{} - if tt.httpStubs != nil { - tt.httpStubs(reg) - } - tt.opts.HttpClient = func() (*http.Client, error) { - return &http.Client{Transport: reg}, nil - } - - io, _, stdout, _ := iostreams.Test() - io.SetStdinTTY(tt.tty) - io.SetStdoutTTY(tt.tty) - tt.opts.IO = io - - t.Run(tt.name, func(t *testing.T) { - defer reg.Verify(t) - err := renameRun(&tt.opts) - assert.NoError(t, err) - assert.Equal(t, tt.wantOut, stdout.String()) - }) - } -} From ccdea2db6d83ee30c415ff23b43549bf15a1c086 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Mon, 25 Oct 2021 17:19:27 -0400 Subject: [PATCH 046/253] lint fix --- pkg/cmd/repo/rename/rename.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 6a961067a..998a45d6e 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -1,7 +1,6 @@ package rename import ( - "errors" "fmt" "net/http" @@ -49,7 +48,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co if len(args) > 0 { opts.newRepoSelector = args[0] } else if !opts.IO.CanPrompt() { - return &cmdutil.FlagError{Err: errors.New("could not prompt: new name required when not running interactively")} + return cmdutil.FlagErrorf("could not prompt: new name required when not running interactively") } if runf != nil { From ea0e8d5c23501c6e62915e70f17e8c87a6f33858 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Tue, 26 Oct 2021 11:38:12 -0400 Subject: [PATCH 047/253] fixed http_tests git stub --- pkg/cmd/repo/rename/http_test.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pkg/cmd/repo/rename/http_test.go b/pkg/cmd/repo/rename/http_test.go index 56e8dc365..eac25f97e 100644 --- a/pkg/cmd/repo/rename/http_test.go +++ b/pkg/cmd/repo/rename/http_test.go @@ -38,7 +38,7 @@ func TestRenameRun(t *testing.T) { httpmock.StatusStringResponse(204, "{}")) }, execStubs: func(cs *run.CommandStubber) { - cs.Register(`git remote set-url origin https://github.com/OWNER/REPO.git`, 0, "") + cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") }, tty: true, }, @@ -59,7 +59,7 @@ func TestRenameRun(t *testing.T) { httpmock.StatusStringResponse(204, "{}")) }, execStubs: func(cs *run.CommandStubber) { - cs.Register(`git remote set-url origin https://github.com/OWNER/REPO.git`, 0, "") + cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") }, tty: true, }, @@ -79,7 +79,7 @@ func TestRenameRun(t *testing.T) { httpmock.StatusStringResponse(204, "{}")) }, execStubs: func(cs *run.CommandStubber) { - cs.Register(`git remote set-url origin https://github.com/OWNER/REPO.git`, 0, "") + cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") }, }, { @@ -97,7 +97,7 @@ func TestRenameRun(t *testing.T) { httpmock.StatusStringResponse(204, "{}")) }, execStubs: func(cs *run.CommandStubber) { - cs.Register(`git remote set-url origin https://github.com/OWNER/REPO.git`, 0, "") + cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") }, tty: true, }, @@ -107,7 +107,7 @@ func TestRenameRun(t *testing.T) { BaseRepo: func() (ghrepo.Interface, error) { return ghrepo.New("OWNER", "REPO"), nil }, - newRepoSelector: "REPO", + newRepoSelector: "NEW_REPO", }, httpStubs: func(reg *httpmock.Registry) { reg.Register( @@ -115,7 +115,7 @@ func TestRenameRun(t *testing.T) { httpmock.StatusStringResponse(204, "{}")) }, execStubs: func(cs *run.CommandStubber) { - cs.Register(`git remote set-url origin https://github.com/OWNER/REPO.git`, 0, "") + cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") }, }, } @@ -145,6 +145,12 @@ func TestRenameRun(t *testing.T) { }, nil } + cs, restoreRun := run.Stub() + defer restoreRun(t) + if tt.execStubs != nil { + tt.execStubs(cs) + } + reg := &httpmock.Registry{} if tt.httpStubs != nil { tt.httpStubs(reg) From 333f0ec5305a58167cbb616260dfec87850e9212 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Tue, 26 Oct 2021 11:55:46 -0400 Subject: [PATCH 048/253] remove repooverride from repo --- pkg/cmd/repo/repo.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/cmd/repo/repo.go b/pkg/cmd/repo/repo.go index 3a5bddd82..ec16d731b 100644 --- a/pkg/cmd/repo/repo.go +++ b/pkg/cmd/repo/repo.go @@ -37,8 +37,6 @@ func NewCmdRepo(f *cmdutil.Factory) *cobra.Command { }, } - cmdutil.EnableRepoOverride(cmd, f) - cmd.AddCommand(repoViewCmd.NewCmdView(f, nil)) cmd.AddCommand(repoForkCmd.NewCmdFork(f, nil)) cmd.AddCommand(repoCloneCmd.NewCmdClone(f, nil)) From 95dbd677e0c106c1a3b9d70f389ce52a51d24411 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Wed, 27 Oct 2021 12:12:09 -0400 Subject: [PATCH 049/253] resolved comments --- pkg/cmd/repo/rename/http.go | 16 +-- pkg/cmd/repo/rename/http_test.go | 174 ----------------------------- pkg/cmd/repo/rename/rename.go | 32 ++++-- pkg/cmd/repo/rename/rename_test.go | 141 ++++++++++++++++++++++- 4 files changed, 165 insertions(+), 198 deletions(-) delete mode 100644 pkg/cmd/repo/rename/http_test.go diff --git a/pkg/cmd/repo/rename/http.go b/pkg/cmd/repo/rename/http.go index bc0bfd0ab..8ed7740ef 100644 --- a/pkg/cmd/repo/rename/http.go +++ b/pkg/cmd/repo/rename/http.go @@ -11,22 +11,8 @@ import ( "github.com/cli/cli/v2/internal/ghrepo" ) -type renameRepo struct { - RepoHost string - RepoOwner string - RepoName string - Name string `json:"name,omitempty"` -} - func runRename(client *http.Client, repo ghrepo.Interface, newRepoName string) error { - - input := renameRepo{ - RepoHost: repo.RepoHost(), - RepoOwner: repo.RepoOwner(), - RepoName: repo.RepoName(), - Name: newRepoName, - } - + input := map[string]string{"name": newRepoName} body, err := json.Marshal(input) if err != nil { return err diff --git a/pkg/cmd/repo/rename/http_test.go b/pkg/cmd/repo/rename/http_test.go deleted file mode 100644 index eac25f97e..000000000 --- a/pkg/cmd/repo/rename/http_test.go +++ /dev/null @@ -1,174 +0,0 @@ -package rename - -import ( - "net/http" - "testing" - - "github.com/cli/cli/v2/context" - "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" - "github.com/cli/cli/v2/pkg/httpmock" - "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" - "github.com/stretchr/testify/assert" -) - -func TestRenameRun(t *testing.T) { - testCases := []struct { - name string - opts RenameOptions - httpStubs func(*httpmock.Registry) - execStubs func(*run.CommandStubber) - askStubs func(*prompt.AskStubber) - wantOut string - tty bool - prompt bool - }{ - { - name: "none argument", - wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", - askStubs: func(q *prompt.AskStubber) { - q.StubOne("NEW_REPO") - }, - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - execStubs: func(cs *run.CommandStubber) { - cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") - }, - tty: true, - }, - { - name: "owner repo change name prompt", - opts: RenameOptions{ - BaseRepo: func() (ghrepo.Interface, error) { - return ghrepo.New("OWNER", "REPO"), nil - }, - }, - wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", - askStubs: func(q *prompt.AskStubber) { - q.StubOne("NEW_REPO") - }, - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - execStubs: func(cs *run.CommandStubber) { - cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") - }, - tty: true, - }, - { - name: "owner repo change name prompt no tty", - opts: RenameOptions{ - BaseRepo: func() (ghrepo.Interface, error) { - return ghrepo.New("OWNER", "REPO"), nil - }, - }, - askStubs: func(q *prompt.AskStubber) { - q.StubOne("NEW_REPO") - }, - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - execStubs: func(cs *run.CommandStubber) { - cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") - }, - }, - { - name: "owner repo change name argument tty", - opts: RenameOptions{ - BaseRepo: func() (ghrepo.Interface, error) { - return ghrepo.New("OWNER", "REPO"), nil - }, - newRepoSelector: "NEW_REPO", - }, - wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote \n", - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - execStubs: func(cs *run.CommandStubber) { - cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") - }, - tty: true, - }, - { - name: "owner repo change name argument no tty", - opts: RenameOptions{ - BaseRepo: func() (ghrepo.Interface, error) { - return ghrepo.New("OWNER", "REPO"), nil - }, - newRepoSelector: "NEW_REPO", - }, - httpStubs: func(reg *httpmock.Registry) { - reg.Register( - httpmock.REST("PATCH", "repos/OWNER/REPO"), - httpmock.StatusStringResponse(204, "{}")) - }, - execStubs: func(cs *run.CommandStubber) { - cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") - }, - }, - } - - for _, tt := range testCases { - q, teardown := prompt.InitAskStubber() - defer teardown() - if tt.askStubs != nil { - tt.askStubs(q) - } - - repo, _ := ghrepo.FromFullName("OWNER/REPO") - tt.opts.BaseRepo = func() (ghrepo.Interface, error) { - return repo, nil - } - - tt.opts.Config = func() (config.Config, error) { - return config.NewBlankConfig(), nil - } - - tt.opts.Remotes = func() (context.Remotes, error) { - return []*context.Remote{ - { - Remote: &git.Remote{Name: "origin"}, - Repo: repo, - }, - }, nil - } - - cs, restoreRun := run.Stub() - defer restoreRun(t) - if tt.execStubs != nil { - tt.execStubs(cs) - } - - reg := &httpmock.Registry{} - if tt.httpStubs != nil { - tt.httpStubs(reg) - } - tt.opts.HttpClient = func() (*http.Client, error) { - return &http.Client{Transport: reg}, nil - } - - io, _, stdout, _ := iostreams.Test() - io.SetStdinTTY(tt.tty) - io.SetStdoutTTY(tt.tty) - tt.opts.IO = io - - t.Run(tt.name, func(t *testing.T) { - defer reg.Verify(t) - err := renameRun(&tt.opts) - assert.NoError(t, err) - assert.Equal(t, tt.wantOut, stdout.String()) - }) - } -} diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 998a45d6e..3a18881d5 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -48,7 +48,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co if len(args) > 0 { opts.newRepoSelector = args[0] } else if !opts.IO.CanPrompt() { - return cmdutil.FlagErrorf("could not prompt: new name required when not running interactively") + return cmdutil.FlagErrorf("could not prompt: new name required when not running interactively\n") } if runf != nil { @@ -106,19 +106,37 @@ func renameRun(opts *RenameOptions) error { cs := opts.IO.ColorScheme() cfg, err := opts.Config() if err != nil { - return err + fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s'\n", cs.WarningIcon(), baseRemote.Name) + return nil + } + + protocol, err := cfg.Get(currRepo.RepoHost(), "git_protocol") + if err != nil { + fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s'\n", cs.WarningIcon(), baseRemote.Name) + return nil + } + + remotes, err := opts.Remotes() + if err != nil { + fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s'\n", cs.WarningIcon(), baseRemote.Name) + return nil + } + + baseRemote, err = remotes.FindByRepo(currRepo.RepoOwner(), currRepo.RepoName()) + if err != nil { + fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s'\n", cs.WarningIcon(), baseRemote.Name) + return nil } - protocol, _ := cfg.Get(currRepo.RepoHost(), "git_protocol") - remotes, _ := opts.Remotes() - baseRemote, _ = remotes.FindByRepo(currRepo.RepoOwner(), currRepo.RepoName()) remoteURL := ghrepo.FormatRemoteURL(newRepo, protocol) err = git.UpdateRemoteURL(baseRemote.Name, remoteURL) if err != nil { - fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s' \n", cs.WarningIcon(), err) + fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s'\n", cs.WarningIcon(), baseRemote.Name) + return nil } + if opts.IO.IsStdoutTTY() { - fmt.Fprintf(opts.IO.Out, "%s Updated the %q remote \n", cs.SuccessIcon(), baseRemote.Name) + fmt.Fprintf(opts.IO.Out, "%s Updated the %q remote\n", cs.SuccessIcon(), baseRemote.Name) } } return nil diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 1a2d507df..176d09cd9 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -2,10 +2,18 @@ package rename import ( "bytes" + "net/http" "testing" + "github.com/cli/cli/v2/context" + "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" "github.com/cli/cli/v2/pkg/cmdutil" + "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" + "github.com/cli/cli/v2/pkg/prompt" "github.com/google/shlex" "github.com/stretchr/testify/assert" ) @@ -22,7 +30,7 @@ func TestNewCmdRename(t *testing.T) { { name: "no arguments no tty", input: "", - errMsg: "could not prompt: proceed with prompt", + errMsg: "could not prompt: new name required when not running interactively\n", wantErr: true, tty: false, }, @@ -64,7 +72,7 @@ func TestNewCmdRename(t *testing.T) { _, err = cmd.ExecuteC() if tt.wantErr { - assert.Error(t, err) + assert.EqualError(t, err, tt.errMsg) return } assert.NoError(t, err) @@ -72,3 +80,132 @@ func TestNewCmdRename(t *testing.T) { }) } } + +func TestRenameRun(t *testing.T) { + testCases := []struct { + name string + opts RenameOptions + httpStubs func(*httpmock.Registry) + execStubs func(*run.CommandStubber) + askStubs func(*prompt.AskStubber) + wantOut string + tty bool + HasRepoOverride bool + }{ + { + name: "none argument", + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote\n", + askStubs: func(q *prompt.AskStubber) { + q.StubOne("NEW_REPO") + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + execStubs: func(cs *run.CommandStubber) { + cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") + }, + tty: true, + }, + { + name: "owner repo change name prompt", + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote\n", + askStubs: func(q *prompt.AskStubber) { + q.StubOne("NEW_REPO") + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + execStubs: func(cs *run.CommandStubber) { + cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") + }, + tty: true, + HasRepoOverride: true, + }, + { + name: "owner repo change name argument tty", + opts: RenameOptions{ + newRepoSelector: "NEW_REPO", + }, + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote\n", + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + execStubs: func(cs *run.CommandStubber) { + cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") + }, + tty: true, + }, + { + name: "owner repo change name argument no tty", + opts: RenameOptions{ + newRepoSelector: "NEW_REPO", + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + execStubs: func(cs *run.CommandStubber) { + cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") + }, + }, + } + + for _, tt := range testCases { + q, teardown := prompt.InitAskStubber() + defer teardown() + if tt.askStubs != nil { + tt.askStubs(q) + } + + repo, _ := ghrepo.FromFullName("OWNER/REPO") + tt.opts.BaseRepo = func() (ghrepo.Interface, error) { + return repo, nil + } + + tt.opts.Config = func() (config.Config, error) { + return config.NewBlankConfig(), nil + } + + tt.opts.Remotes = func() (context.Remotes, error) { + return []*context.Remote{ + { + Remote: &git.Remote{Name: "origin"}, + Repo: repo, + }, + }, nil + } + + cs, restoreRun := run.Stub() + defer restoreRun(t) + if tt.execStubs != nil { + tt.execStubs(cs) + } + + reg := &httpmock.Registry{} + if tt.httpStubs != nil { + tt.httpStubs(reg) + } + tt.opts.HttpClient = func() (*http.Client, error) { + return &http.Client{Transport: reg}, nil + } + + io, _, stdout, _ := iostreams.Test() + io.SetStdinTTY(tt.tty) + io.SetStdoutTTY(tt.tty) + tt.opts.IO = io + + t.Run(tt.name, func(t *testing.T) { + defer reg.Verify(t) + err := renameRun(&tt.opts) + assert.NoError(t, err) + assert.Equal(t, tt.wantOut, stdout.String()) + }) + } +} From 296cf381a28538385f5f7753cb32de915036a248 Mon Sep 17 00:00:00 2001 From: Sam Coe Date: Wed, 27 Oct 2021 14:07:00 -0400 Subject: [PATCH 050/253] Reduce duplicate warning message code --- pkg/cmd/repo/rename/rename.go | 76 ++++++++++++++---------------- pkg/cmd/repo/rename/rename_test.go | 30 ++++++------ 2 files changed, 50 insertions(+), 56 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index 3a18881d5..fee37b2be 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -39,7 +39,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co Short: "Rename a repository", Long: heredoc.Doc(`Rename a GitHub repository - By default, renames the current repository otherwise rename the specified repository.`), + By default, renames the current repository otherwise renames the specified repository.`), Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { opts.BaseRepo = f.BaseRepo @@ -48,7 +48,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co if len(args) > 0 { opts.newRepoSelector = args[0] } else if !opts.IO.CanPrompt() { - return cmdutil.FlagErrorf("could not prompt: new name required when not running interactively\n") + return cmdutil.FlagErrorf("new name argument required when not running interactively\n") } if runf != nil { @@ -69,8 +69,6 @@ func renameRun(opts *RenameOptions) error { return err } - var newRepo ghrepo.Interface - var baseRemote *context.Remote newRepoName := opts.newRepoSelector currRepo, err := opts.BaseRepo() @@ -90,54 +88,52 @@ func renameRun(opts *RenameOptions) error { } } - newRepo = ghrepo.NewWithHost(currRepo.RepoOwner(), newRepoName, currRepo.RepoHost()) - err = runRename(httpClient, currRepo, newRepoName) if err != nil { return fmt.Errorf("API called failed: %s", err) } + cs := opts.IO.ColorScheme() + newRepo := ghrepo.NewWithHost(currRepo.RepoOwner(), newRepoName, currRepo.RepoHost()) + if opts.IO.IsStdoutTTY() { - cs := opts.IO.ColorScheme() fmt.Fprintf(opts.IO.Out, "%s Renamed repository %s\n", cs.SuccessIcon(), ghrepo.FullName(newRepo)) } if !opts.HasRepoOverride { - cs := opts.IO.ColorScheme() - cfg, err := opts.Config() + remote, err := updateRemote(currRepo, newRepo, opts) if err != nil { - fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s'\n", cs.WarningIcon(), baseRemote.Name) - return nil - } - - protocol, err := cfg.Get(currRepo.RepoHost(), "git_protocol") - if err != nil { - fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s'\n", cs.WarningIcon(), baseRemote.Name) - return nil - } - - remotes, err := opts.Remotes() - if err != nil { - fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s'\n", cs.WarningIcon(), baseRemote.Name) - return nil - } - - baseRemote, err = remotes.FindByRepo(currRepo.RepoOwner(), currRepo.RepoName()) - if err != nil { - fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s'\n", cs.WarningIcon(), baseRemote.Name) - return nil - } - - remoteURL := ghrepo.FormatRemoteURL(newRepo, protocol) - err = git.UpdateRemoteURL(baseRemote.Name, remoteURL) - if err != nil { - fmt.Fprintf(opts.IO.ErrOut, "%s warning: unable to update remote '%s'\n", cs.WarningIcon(), baseRemote.Name) - return nil - } - - if opts.IO.IsStdoutTTY() { - fmt.Fprintf(opts.IO.Out, "%s Updated the %q remote\n", cs.SuccessIcon(), baseRemote.Name) + fmt.Fprintf(opts.IO.ErrOut, "%s Warning: unable to update remote %q\n", cs.WarningIcon(), remote.Name) + } else if opts.IO.IsStdoutTTY() { + fmt.Fprintf(opts.IO.Out, "%s Updated the %q remote\n", cs.SuccessIcon(), remote.Name) } } + return nil } + +func updateRemote(repo ghrepo.Interface, renamed ghrepo.Interface, opts *RenameOptions) (*context.Remote, error) { + cfg, err := opts.Config() + if err != nil { + return nil, err + } + + protocol, err := cfg.Get(repo.RepoHost(), "git_protocol") + if err != nil { + return nil, err + } + + remotes, err := opts.Remotes() + if err != nil { + return nil, err + } + + remote, err := remotes.FindByRepo(repo.RepoOwner(), repo.RepoName()) + if err != nil { + return nil, err + } + + remoteURL := ghrepo.FormatRemoteURL(renamed, protocol) + err = git.UpdateRemoteURL(remote.Name, remoteURL) + return remote, err +} diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 176d09cd9..63dad9245 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -30,7 +30,7 @@ func TestNewCmdRename(t *testing.T) { { name: "no arguments no tty", input: "", - errMsg: "could not prompt: new name required when not running interactively\n", + errMsg: "new name argument required when not running interactively\n", wantErr: true, tty: false, }, @@ -83,14 +83,13 @@ func TestNewCmdRename(t *testing.T) { func TestRenameRun(t *testing.T) { testCases := []struct { - name string - opts RenameOptions - httpStubs func(*httpmock.Registry) - execStubs func(*run.CommandStubber) - askStubs func(*prompt.AskStubber) - wantOut string - tty bool - HasRepoOverride bool + name string + opts RenameOptions + httpStubs func(*httpmock.Registry) + execStubs func(*run.CommandStubber) + askStubs func(*prompt.AskStubber) + wantOut string + tty bool }{ { name: "none argument", @@ -109,8 +108,11 @@ func TestRenameRun(t *testing.T) { tty: true, }, { - name: "owner repo change name prompt", - wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote\n", + name: "repo override", + opts: RenameOptions{ + HasRepoOverride: true, + }, + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n", askStubs: func(q *prompt.AskStubber) { q.StubOne("NEW_REPO") }, @@ -119,11 +121,7 @@ func TestRenameRun(t *testing.T) { httpmock.REST("PATCH", "repos/OWNER/REPO"), httpmock.StatusStringResponse(204, "{}")) }, - execStubs: func(cs *run.CommandStubber) { - cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") - }, - tty: true, - HasRepoOverride: true, + tty: true, }, { name: "owner repo change name argument tty", From c18e54189ce3ced76d95278a6deb96c38e50582a Mon Sep 17 00:00:00 2001 From: Jeff Hubbard Date: Wed, 27 Oct 2021 15:40:49 -0700 Subject: [PATCH 051/253] Adds a timeout context to the ssh waiter to prevent indefinite hanging --- pkg/liveshare/rpc.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/liveshare/rpc.go b/pkg/liveshare/rpc.go index bfd214c89..3645f85c0 100644 --- a/pkg/liveshare/rpc.go +++ b/pkg/liveshare/rpc.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "time" "github.com/opentracing/opentracing-go" "github.com/sourcegraph/jsonrpc2" @@ -32,7 +33,11 @@ func (r *rpcClient) do(ctx context.Context, method string, args, result interfac return fmt.Errorf("error dispatching %q call: %w", method, err) } - return waiter.Wait(ctx, result) + // timeout for waiter in case a connection cannot be made + waitCtx, cancel := context.WithTimeout(ctx, 2*time.Second) + defer cancel() + + return waiter.Wait(waitCtx, result) } type nullHandler struct{} From da258fb4f4cdbc28741bc5a8135ae75098e9c82c Mon Sep 17 00:00:00 2001 From: nate smith Date: Thu, 28 Oct 2021 12:26:01 -0500 Subject: [PATCH 052/253] confirm when inferring repository --- pkg/cmd/repo/rename/rename.go | 26 +++++++++++++ pkg/cmd/repo/rename/rename_test.go | 61 ++++++++++++++++++++++++++++-- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/repo/rename/rename.go b/pkg/cmd/repo/rename/rename.go index fee37b2be..d476a9600 100644 --- a/pkg/cmd/repo/rename/rename.go +++ b/pkg/cmd/repo/rename/rename.go @@ -22,6 +22,7 @@ type RenameOptions struct { Config func() (config.Config, error) BaseRepo func() (ghrepo.Interface, error) Remotes func() (context.Remotes, error) + DoConfirm bool HasRepoOverride bool newRepoSelector string } @@ -34,6 +35,8 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co Config: f.Config, } + var confirm bool + cmd := &cobra.Command{ Use: "rename []", Short: "Rename a repository", @@ -51,6 +54,13 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co return cmdutil.FlagErrorf("new name argument required when not running interactively\n") } + if len(args) == 1 && !confirm && !opts.HasRepoOverride { + if !opts.IO.CanPrompt() { + return cmdutil.FlagErrorf("--confirm required when passing a single argument") + } + opts.DoConfirm = true + } + if runf != nil { return runf(opts) } @@ -59,6 +69,7 @@ func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Co } cmdutil.EnableRepoOverride(cmd, f) + cmd.Flags().BoolVarP(&confirm, "confirm", "y", false, "skip confirmation prompt") return cmd } @@ -88,6 +99,21 @@ func renameRun(opts *RenameOptions) error { } } + if opts.DoConfirm { + var confirmed bool + p := &survey.Confirm{ + Message: fmt.Sprintf("Rename %s to %s?", ghrepo.FullName(currRepo), newRepoName), + Default: false, + } + err = prompt.SurveyAskOne(p, &confirmed) + if err != nil { + return fmt.Errorf("failed to prompt: %w", err) + } + if !confirmed { + return nil + } + } + err = runRename(httpClient, currRepo, newRepoName) if err != nil { return fmt.Errorf("API called failed: %s", err) diff --git a/pkg/cmd/repo/rename/rename_test.go b/pkg/cmd/repo/rename/rename_test.go index 63dad9245..e91317f82 100644 --- a/pkg/cmd/repo/rename/rename_test.go +++ b/pkg/cmd/repo/rename/rename_test.go @@ -32,15 +32,37 @@ func TestNewCmdRename(t *testing.T) { input: "", errMsg: "new name argument required when not running interactively\n", wantErr: true, - tty: false, }, { - name: "one argument", - input: "REPO", + name: "one argument no tty confirmed", + input: "REPO --confirm", output: RenameOptions{ newRepoSelector: "REPO", }, }, + { + name: "one argument no tty", + input: "REPO", + errMsg: "--confirm required when passing a single argument", + wantErr: true, + }, + { + name: "one argument tty confirmed", + input: "REPO --confirm", + tty: true, + output: RenameOptions{ + newRepoSelector: "REPO", + }, + }, + { + name: "one argument tty", + input: "REPO", + tty: true, + output: RenameOptions{ + newRepoSelector: "REPO", + DoConfirm: true, + }, + }, { name: "full flag argument", input: "--repo OWNER/REPO NEW_REPO", @@ -153,6 +175,39 @@ func TestRenameRun(t *testing.T) { cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") }, }, + { + name: "confirmation with yes", + tty: true, + opts: RenameOptions{ + newRepoSelector: "NEW_REPO", + DoConfirm: true, + }, + wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote\n", + askStubs: func(q *prompt.AskStubber) { + q.StubOne(true) + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("PATCH", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + execStubs: func(cs *run.CommandStubber) { + cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "") + }, + }, + + { + name: "confirmation with no", + tty: true, + opts: RenameOptions{ + newRepoSelector: "NEW_REPO", + DoConfirm: true, + }, + askStubs: func(q *prompt.AskStubber) { + q.StubOne(false) + }, + wantOut: "", + }, } for _, tt := range testCases { From 97d85d0ac069bc8c99336d2e0bef71d044cff7ba Mon Sep 17 00:00:00 2001 From: Jeff Hubbard Date: Thu, 28 Oct 2021 16:33:13 -0700 Subject: [PATCH 053/253] Oops, left it as second from debugging --- pkg/liveshare/rpc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/liveshare/rpc.go b/pkg/liveshare/rpc.go index 3645f85c0..4ab8fbb88 100644 --- a/pkg/liveshare/rpc.go +++ b/pkg/liveshare/rpc.go @@ -34,7 +34,7 @@ func (r *rpcClient) do(ctx context.Context, method string, args, result interfac } // timeout for waiter in case a connection cannot be made - waitCtx, cancel := context.WithTimeout(ctx, 2*time.Second) + waitCtx, cancel := context.WithTimeout(ctx, 2*time.Minute) defer cancel() return waiter.Wait(waitCtx, result) From 48baf50b8e07178325a1ac1961707d571f104877 Mon Sep 17 00:00:00 2001 From: meiji163 Date: Sun, 31 Oct 2021 14:22:43 -0700 Subject: [PATCH 054/253] add base repo resolution to archive --- pkg/cmd/repo/archive/archive.go | 67 ++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 14 deletions(-) diff --git a/pkg/cmd/repo/archive/archive.go b/pkg/cmd/repo/archive/archive.go index eb2af2175..56b13ee3a 100644 --- a/pkg/cmd/repo/archive/archive.go +++ b/pkg/cmd/repo/archive/archive.go @@ -5,20 +5,26 @@ import ( "net/http" "strings" + "github.com/AlecAivazis/survey/v2" + "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/pkg/cmdutil" + "github.com/cli/cli/v2/pkg/prompt" "github.com/cli/cli/v2/pkg/iostreams" "github.com/spf13/cobra" ) type ArchiveOptions struct { - HttpClient func() (*http.Client, error) - IO *iostreams.IOStreams - Config func() (config.Config, error) - RepoArg string + HttpClient func() (*http.Client, error) + IO *iostreams.IOStreams + Config func() (config.Config, error) + BaseRepo func() (ghrepo.Interface, error) + RepoArg string + HasRepoOverride bool + Confirmed bool } func NewCmdArchive(f *cmdutil.Factory, runF func(*ArchiveOptions) error) *cobra.Command { @@ -29,14 +35,23 @@ func NewCmdArchive(f *cmdutil.Factory, runF func(*ArchiveOptions) error) *cobra. } cmd := &cobra.Command{ - DisableFlagsInUseLine: true, - - Use: "archive ", + Use: "archive []", Short: "Archive a repository", - Long: "Archive a GitHub repository.", - Args: cmdutil.ExactArgs(1, "cannot archive: repository argument required"), + Long: heredoc.Doc(`Archive a GitHub repository. + +With no argument, archives the current repository.`), + Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - opts.RepoArg = args[0] + if len(args) > 0 { + opts.RepoArg = args[0] + } + opts.BaseRepo = f.BaseRepo + opts.HasRepoOverride = cmd.Flags().Changed("repo") + + if !opts.Confirmed && !opts.IO.CanPrompt() { + return cmdutil.FlagErrorf("could not prompt: confirmation with prompt or --confirm flag required") + } + if runF != nil { return runF(opts) } @@ -44,6 +59,8 @@ func NewCmdArchive(f *cmdutil.Factory, runF func(*ArchiveOptions) error) *cobra. }, } + cmdutil.EnableRepoOverride(cmd, f) + cmd.Flags().BoolVarP(&opts.Confirmed, "confirm", "y", false, "skip confirmation prompt") return cmd } @@ -57,8 +74,16 @@ func archiveRun(opts *ArchiveOptions) error { var toArchive ghrepo.Interface - archiveURL := opts.RepoArg - if !strings.Contains(archiveURL, "/") { + repoSelector := opts.RepoArg + if repoSelector == "" { + currRepo, err := opts.BaseRepo() + if err != nil { + return err + } + repoSelector = ghrepo.FullName(currRepo) + } + + if !strings.Contains(repoSelector, "/") { cfg, err := opts.Config() if err != nil { return err @@ -72,9 +97,9 @@ func archiveRun(opts *ArchiveOptions) error { if err != nil { return err } - archiveURL = currentUser + "/" + archiveURL + repoSelector = currentUser + "/" + repoSelector } - toArchive, err = ghrepo.FromFullName(archiveURL) + toArchive, err = ghrepo.FromFullName(repoSelector) if err != nil { return fmt.Errorf("argument error: %w", err) } @@ -94,6 +119,20 @@ func archiveRun(opts *ArchiveOptions) error { return nil } + if !opts.Confirmed { + p := &survey.Confirm{ + Message: fmt.Sprintf("Archive %s?", fullName), + Default: false, + } + err = prompt.SurveyAskOne(p, &opts.Confirmed) + if err != nil { + return fmt.Errorf("failed to prompt: %w", err) + } + if !opts.Confirmed { + return nil + } + } + err = archiveRepo(httpClient, repo) if err != nil { return fmt.Errorf("API called failed: %w", err) From 001b1a36e7e32b16e8a604de6e6229d39ffcbb69 Mon Sep 17 00:00:00 2001 From: meiji163 Date: Sun, 31 Oct 2021 14:46:57 -0700 Subject: [PATCH 055/253] add base resolution to delete --- pkg/cmd/repo/delete/delete.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/repo/delete/delete.go b/pkg/cmd/repo/delete/delete.go index 3036f7697..16604cb65 100644 --- a/pkg/cmd/repo/delete/delete.go +++ b/pkg/cmd/repo/delete/delete.go @@ -18,6 +18,7 @@ import ( type DeleteOptions struct { HttpClient func() (*http.Client, error) + BaseRepo func() (ghrepo.Interface, error) IO *iostreams.IOStreams RepoArg string Confirmed bool @@ -30,15 +31,17 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co } cmd := &cobra.Command{ - Use: "delete ", + Use: "delete []", Short: "Delete a repository", Long: `Delete a GitHub repository. Deletion requires authorization with the "delete_repo" scope. To authorize, run "gh auth refresh -s delete_repo"`, - Args: cmdutil.ExactArgs(1, "cannot delete: repository argument required"), + Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - opts.RepoArg = args[0] + if len(args) > 0 { + opts.RepoArg = args[0] + } if !opts.IO.CanPrompt() && !opts.Confirmed { return cmdutil.FlagErrorf("could not prompt: confirmation with prompt or --confirm flag required") } @@ -60,8 +63,15 @@ func deleteRun(opts *DeleteOptions) error { } apiClient := api.NewClientFromHTTP(httpClient) - repoSelector := opts.RepoArg var toDelete ghrepo.Interface + repoSelector := opts.RepoArg + if repoSelector == "" { + currRepo, err := opts.BaseRepo() + if err != nil { + return err + } + repoSelector = ghrepo.FullName(currRepo) + } if !strings.Contains(repoSelector, "/") { currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) From b0dce5b04d9c587026d8e9ffa64698d9e7ef6b3c Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Mon, 1 Nov 2021 13:49:11 -0400 Subject: [PATCH 056/253] minor fix in base repo functionality --- pkg/cmd/repo/archive/archive.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pkg/cmd/repo/archive/archive.go b/pkg/cmd/repo/archive/archive.go index 56b13ee3a..413e8ce20 100644 --- a/pkg/cmd/repo/archive/archive.go +++ b/pkg/cmd/repo/archive/archive.go @@ -35,20 +35,17 @@ func NewCmdArchive(f *cmdutil.Factory, runF func(*ArchiveOptions) error) *cobra. } cmd := &cobra.Command{ - Use: "archive []", + Use: "archive", Short: "Archive a repository", Long: heredoc.Doc(`Archive a GitHub repository. With no argument, archives the current repository.`), - Args: cobra.MaximumNArgs(1), + Args: cobra.MaximumNArgs(0), RunE: func(cmd *cobra.Command, args []string) error { - if len(args) > 0 { - opts.RepoArg = args[0] - } opts.BaseRepo = f.BaseRepo opts.HasRepoOverride = cmd.Flags().Changed("repo") - if !opts.Confirmed && !opts.IO.CanPrompt() { + if !opts.Confirmed && !opts.IO.CanPrompt() && !opts.HasRepoOverride { return cmdutil.FlagErrorf("could not prompt: confirmation with prompt or --confirm flag required") } From 13a97c29edb2a59ad571a914d8cd7b90f3009f58 Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Mon, 1 Nov 2021 14:21:10 -0400 Subject: [PATCH 057/253] removed unnecessary things --- pkg/cmd/repo/archive/archive.go | 53 ++++++--------------------------- 1 file changed, 9 insertions(+), 44 deletions(-) diff --git a/pkg/cmd/repo/archive/archive.go b/pkg/cmd/repo/archive/archive.go index 413e8ce20..1a47133f9 100644 --- a/pkg/cmd/repo/archive/archive.go +++ b/pkg/cmd/repo/archive/archive.go @@ -3,7 +3,6 @@ package archive import ( "fmt" "net/http" - "strings" "github.com/AlecAivazis/survey/v2" "github.com/MakeNowJust/heredoc" @@ -22,7 +21,6 @@ type ArchiveOptions struct { IO *iostreams.IOStreams Config func() (config.Config, error) BaseRepo func() (ghrepo.Interface, error) - RepoArg string HasRepoOverride bool Confirmed bool } @@ -69,50 +67,20 @@ func archiveRun(opts *ArchiveOptions) error { } apiClient := api.NewClientFromHTTP(httpClient) - var toArchive ghrepo.Interface - - repoSelector := opts.RepoArg - if repoSelector == "" { - currRepo, err := opts.BaseRepo() - if err != nil { - return err - } - repoSelector = ghrepo.FullName(currRepo) - } - - if !strings.Contains(repoSelector, "/") { - cfg, err := opts.Config() - if err != nil { - return err - } - hostname, err := cfg.DefaultHost() - if err != nil { - return err - } - - currentUser, err := api.CurrentLoginName(apiClient, hostname) - if err != nil { - return err - } - repoSelector = currentUser + "/" + repoSelector - } - toArchive, err = ghrepo.FromFullName(repoSelector) - if err != nil { - return fmt.Errorf("argument error: %w", err) - } - - fields := []string{"name", "owner", "isArchived", "id"} - repo, err := api.FetchRepository(apiClient, toArchive, fields) + currRepo, err := opts.BaseRepo() if err != nil { return err } - fullName := ghrepo.FullName(toArchive) + fields := []string{"name", "owner", "isArchived", "id"} + repo, err := api.FetchRepository(apiClient, currRepo, fields) + if err != nil { + return err + } + + fullName := ghrepo.FullName(currRepo) if repo.IsArchived { - fmt.Fprintf(opts.IO.ErrOut, - "%s Repository %s is already archived\n", - cs.WarningIcon(), - fullName) + fmt.Fprintf(opts.IO.ErrOut, "%s Repository %s is already archived\n", cs.WarningIcon(), fullName) return nil } @@ -125,9 +93,6 @@ func archiveRun(opts *ArchiveOptions) error { if err != nil { return fmt.Errorf("failed to prompt: %w", err) } - if !opts.Confirmed { - return nil - } } err = archiveRepo(httpClient, repo) From dbebd74a9f4bcc7e2d6fba23472b55ffca27471b Mon Sep 17 00:00:00 2001 From: Parth Patel Date: Mon, 1 Nov 2021 17:14:04 -0400 Subject: [PATCH 058/253] final changes made --- pkg/cmd/repo/archive/archive.go | 3 ++ pkg/cmd/repo/archive/archive_test.go | 78 ++++++++++++++++------------ 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/pkg/cmd/repo/archive/archive.go b/pkg/cmd/repo/archive/archive.go index 1a47133f9..165aa7280 100644 --- a/pkg/cmd/repo/archive/archive.go +++ b/pkg/cmd/repo/archive/archive.go @@ -93,6 +93,9 @@ func archiveRun(opts *ArchiveOptions) error { if err != nil { return fmt.Errorf("failed to prompt: %w", err) } + if !opts.Confirmed { + return nil + } } err = archiveRepo(httpClient, repo) diff --git a/pkg/cmd/repo/archive/archive_test.go b/pkg/cmd/repo/archive/archive_test.go index 6ed5ecb8f..6d2a0d61c 100644 --- a/pkg/cmd/repo/archive/archive_test.go +++ b/pkg/cmd/repo/archive/archive_test.go @@ -5,9 +5,11 @@ import ( "net/http" "testing" + "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" + "github.com/cli/cli/v2/pkg/prompt" "github.com/google/shlex" "github.com/stretchr/testify/assert" ) @@ -17,42 +19,25 @@ func TestNewCmdArchive(t *testing.T) { tests := []struct { name string input string - tty bool - output ArchiveOptions wantErr bool errMsg string }{ { - name: "valid repo", - input: "cli/cli", - tty: true, - output: ArchiveOptions{ - RepoArg: "cli/cli", - }, - }, - { - name: "no argument", + name: "no arguments tty", input: "", + errMsg: "could not prompt: confirmation with prompt or --confirm flag required", wantErr: true, - tty: true, - output: ArchiveOptions{ - RepoArg: "", - }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { io, _, _, _ := iostreams.Test() - io.SetStdinTTY(tt.tty) - io.SetStdoutTTY(tt.tty) f := &cmdutil.Factory{ IOStreams: io, } argv, err := shlex.Split(tt.input) assert.NoError(t, err) - var gotOpts *ArchiveOptions cmd := NewCmdArchive(f, func(opts *ArchiveOptions) error { - gotOpts = opts return nil }) cmd.SetArgs(argv) @@ -66,7 +51,6 @@ func TestNewCmdArchive(t *testing.T) { return } assert.NoError(t, err) - assert.Equal(t, tt.output.RepoArg, gotOpts.RepoArg) }) } } @@ -76,15 +60,18 @@ func Test_ArchiveRun(t *testing.T) { name string opts ArchiveOptions httpStubs func(*httpmock.Registry) + askStubs func(*prompt.AskStubber) isTTY bool wantStdout string wantStderr string }{ { name: "unarchived repo tty", - opts: ArchiveOptions{RepoArg: "OWNER/REPO"}, wantStdout: "✓ Archived repository OWNER/REPO\n", - isTTY: true, + askStubs: func(q *prompt.AskStubber) { + q.StubOne(true) + }, + isTTY: true, httpStubs: func(reg *httpmock.Registry) { reg.Register( httpmock.GraphQL(`query RepositoryInfo\b`), @@ -97,9 +84,15 @@ func Test_ArchiveRun(t *testing.T) { }, }, { - name: "unarchived repo notty", - opts: ArchiveOptions{RepoArg: "OWNER/REPO"}, - isTTY: false, + name: "unarchived override repo tty", + wantStdout: "✓ Archived repository OWNER/REPO\n", + opts: ArchiveOptions{ + HasRepoOverride: true, + }, + askStubs: func(q *prompt.AskStubber) { + q.StubOne(true) + }, + isTTY: true, httpStubs: func(reg *httpmock.Registry) { reg.Register( httpmock.GraphQL(`query RepositoryInfo\b`), @@ -113,33 +106,54 @@ func Test_ArchiveRun(t *testing.T) { }, { name: "archived repo tty", - opts: ArchiveOptions{RepoArg: "OWNER/REPO"}, wantStderr: "! Repository OWNER/REPO is already archived\n", - isTTY: true, + opts: ArchiveOptions{ + HasRepoOverride: true, + }, + askStubs: func(q *prompt.AskStubber) { + q.StubOne(true) + }, + isTTY: true, httpStubs: func(reg *httpmock.Registry) { reg.Register( httpmock.GraphQL(`query RepositoryInfo\b`), httpmock.StringResponse(`{ "data": { "repository": { "id": "THE-ID", - "isArchived": true } } }`)) + "isArchived": true} } }`)) }, }, { - name: "archived repo notty", - opts: ArchiveOptions{RepoArg: "OWNER/REPO"}, - isTTY: false, + name: "archived override repo tty", wantStderr: "! Repository OWNER/REPO is already archived\n", + opts: ArchiveOptions{ + HasRepoOverride: true, + }, + askStubs: func(q *prompt.AskStubber) { + q.StubOne(true) + }, + isTTY: true, httpStubs: func(reg *httpmock.Registry) { reg.Register( httpmock.GraphQL(`query RepositoryInfo\b`), httpmock.StringResponse(`{ "data": { "repository": { "id": "THE-ID", - "isArchived": true } } }`)) + "isArchived": true} } }`)) }, }, } for _, tt := range tests { + repo, _ := ghrepo.FromFullName("OWNER/REPO") + tt.opts.BaseRepo = func() (ghrepo.Interface, error) { + return repo, nil + } + + q, teardown := prompt.InitAskStubber() + defer teardown() + if tt.askStubs != nil { + tt.askStubs(q) + } + reg := &httpmock.Registry{} if tt.httpStubs != nil { tt.httpStubs(reg) From 175da0f58ae622d8290d7a95218ef1fbd8019fba Mon Sep 17 00:00:00 2001 From: Peter Benjamin Date: Tue, 2 Nov 2021 10:30:49 -0700 Subject: [PATCH 059/253] Fix rendering issue in "formatting" help topic (#4661) Signed-off-by: Peter Benjamin --- pkg/cmd/root/help_topic.go | 44 ++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/pkg/cmd/root/help_topic.go b/pkg/cmd/root/help_topic.go index ca39b6d2f..f94f577da 100644 --- a/pkg/cmd/root/help_topic.go +++ b/pkg/cmd/root/help_topic.go @@ -2,6 +2,7 @@ package root import ( "github.com/MakeNowJust/heredoc" + "github.com/cli/cli/v2/pkg/text" "github.com/spf13/cobra" ) @@ -104,31 +105,32 @@ var HelpTopics = map[string]map[string]string{ - %[1]stimeago