Skip to content

Commit

Permalink
feat(re-ssh-clone): cloning via ssh
Browse files Browse the repository at this point in the history
Implemented ssh cloning. Now user can pass location of private key and passphrase and clone the links directly.
Previous attempt to add the feature resulted in merge conflicts in go.sum which could not be resolved manually.

#31
Closes #31
  • Loading branch information
theishanbh committed Aug 4, 2022
1 parent 4499cb5 commit 37223ed
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 14 deletions.
17 changes: 11 additions & 6 deletions cmd/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import (
)

var (
AccessToken string
Username string
cloneCmd = &cobra.Command{
AccessToken string
Username string
Password string
PrivateKeyFile string

cloneCmd = &cobra.Command{
Use: "clone",
Short: "Clones the repos",
Long: `Clones the repositories in the given directory`,
Expand All @@ -20,13 +23,13 @@ var (

// Check for the config file
if utils.IsConfigFilePresent() {
lib.Clone(Username, AccessToken)
lib.Clone(Username, AccessToken, PrivateKeyFile)
} else {
lib.FreezeClone(Username, AccessToken)
lib.FreezeClone(Username, AccessToken, PrivateKeyFile)
}

} else {
lib.Clone(Username, AccessToken)
lib.Clone(Username, AccessToken, PrivateKeyFile)
}

},
Expand All @@ -37,4 +40,6 @@ func init() {
rootCmd.AddCommand(cloneCmd)
cloneCmd.Flags().StringVarP(&AccessToken, "access", "a", "", "personal access token")
cloneCmd.Flags().StringVarP(&Username, "user", "u", "", "username")
cloneCmd.Flags().StringVarP(&Password, "password", "p", "", "password")
cloneCmd.Flags().StringVarP(&PrivateKeyFile, "privateKeyFile", "f", "", "location")
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ require (
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.3.1 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/xanzy/ssh-agent v0.3.1 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
Expand Down Expand Up @@ -178,6 +179,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
Expand Down Expand Up @@ -339,6 +342,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
67 changes: 60 additions & 7 deletions internal/lib/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,45 @@ package lib

import (
"fmt"
"os"
"sync"

"github.com/automation-co/borzoi/internal/config"
"github.com/automation-co/borzoi/internal/utils"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
"github.com/manifoldco/promptui"
)

// =============================================================================

// Clones the repos in the given config file
func Clone(username string, accessToken string) {
func Clone(username string, accessToken string, privateKeyFile string) {

fmt.Println("Cloning the repositories...")
fmt.Println("")

// Read the config file
conf := config.ReadConfig()

// Inputting password if privatekeyfile provided
var password string
if privateKeyFile != "" {

prompt := promptui.Prompt{
Label: "Password",
Mask: '*',
}

result, err := prompt.Run()
password = result
if err != nil {
fmt.Printf("Prompt failed %v\n", err)
return
}
}

// Get username
usernameLocal := utils.GetUsername()
if username == "" {
Expand All @@ -47,19 +67,52 @@ func Clone(username string, accessToken string) {
if err != nil {

if err.Error() == "authentication required" {
// Check if repo is ssh or http

auth := &http.BasicAuth{
Username: username,
Password: accessToken, // personal access token
// needs to be created using github api
}

_, err := git.PlainClone(path, false, &git.CloneOptions{
URL: repoUrl,
Auth: &http.BasicAuth{
Username: username,
Password: accessToken, // personal access token
// needs to be created using github api
},
URL: repoUrl,
Auth: auth,
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
})
if err != nil {
if err.Error() == "repository already exists" {
fmt.Println(" [o] Skipping " + path + " because it already exists")
} else {
panic(err)
}
} else {
panic(err)
}
} else if err.Error() == "error creating SSH agent: \"SSH agent requested, but could not detect Pageant or Windows native SSH agent\"" {
_, err := os.Stat(privateKeyFile)
if err != nil {
fmt.Printf("read file %s failed %s\n", privateKeyFile, err.Error())
return
}

// TODO: make public keys work
publicKeys, err := ssh.NewPublicKeysFromFile("git", privateKeyFile, password)
if err != nil {
fmt.Printf("generate publickeys failed: %s\n", err.Error())
return
}
auth := publicKeys
_, err = git.PlainClone(path, false, &git.CloneOptions{
URL: repoUrl,
Auth: auth,
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
})
if err != nil {
if err.Error() == "repository already exists" {
fmt.Println(" [o] Skipping " + path + " because it already exists")
} else {
fmt.Println("dint do shit")
panic(err)
}
}
Expand Down
49 changes: 48 additions & 1 deletion internal/lib/freeze.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
"github.com/manifoldco/promptui"
"github.com/mitchellh/mapstructure"
)

Expand Down Expand Up @@ -79,12 +81,29 @@ func Freeze() {

// =============================================================================

func FreezeClone(username string, accessToken string) {
func FreezeClone(username string, accessToken string, privateKeyFile string) {

fmt.Println("Cloning the state from borzoi-lock file...")

conf := config.ReadLockFile()

// Inputting password if privatekeyfile provided
var password string
if privateKeyFile != "" {

prompt := promptui.Prompt{
Label: "Password",
Mask: '*',
}

result, err := prompt.Run()
password = result
if err != nil {
fmt.Printf("Prompt failed %v\n", err)
return
}
}

// Get username
usernameLocal := utils.GetUsername()
if username == "" {
Expand Down Expand Up @@ -139,6 +158,34 @@ func FreezeClone(username string, accessToken string) {
}
}

} else if err.Error() == "error creating SSH agent: \"SSH agent requested, but could not detect Pageant or Windows native SSH agent\"" {
_, err := os.Stat(privateKeyFile)
if err != nil {
fmt.Printf("read file %s failed %s\n", privateKeyFile, err.Error())
return
}
// TODO: make public keys work
publicKeys, err := ssh.NewPublicKeysFromFile("git", privateKeyFile, password)
if err != nil {
fmt.Printf("generate publickeys failed: %s\n", err.Error())
return
}
auth := publicKeys
_, err = git.PlainClone(path, false, &git.CloneOptions{
URL: m.Repo,
Auth: auth,
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
SingleBranch: true,
ReferenceName: plumbing.ReferenceName(referenceName),
})
if err != nil {
if err.Error() == "repository already exists" {
fmt.Println(" [o] Skipping " + path + " because it already exists")
} else {
fmt.Println("dint do shit")
panic(err)
}
}
} else if err.Error() == "repository already exists" {
fmt.Println(" [o] Skipping " + path + " because it already exists")
} else {
Expand Down

0 comments on commit 37223ed

Please sign in to comment.