Skip to content

Commit

Permalink
feat: add getscript command
Browse files Browse the repository at this point in the history
  • Loading branch information
anoriqq committed May 21, 2022
1 parent a388ddf commit 2bfda86
Show file tree
Hide file tree
Showing 3 changed files with 236 additions and 17 deletions.
159 changes: 159 additions & 0 deletions internal/cmd/script.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package cmd

import (
"errors"
"fmt"
"net/url"
"os"
"time"

"github.com/AlecAivazis/survey/v2"
"github.com/anoriqq/qpm/internal/config"
"github.com/anoriqq/qpm/internal/git"
"github.com/spf13/cobra"
)

var getscriptCmd = &cobra.Command{
Use: "getscript",
RunE: getscriptRun,
}

func init() {
rootCmd.AddCommand(getscriptCmd)
}

func getscriptRun(_ *cobra.Command, _ []string) error {
if !config.HasScriptDir() {
scriptDir, err := surveyScriptDir()
if err != nil {
return err
}

err = config.SetScriptDir(scriptDir)
if err != nil {
return err
}
}

if !config.HasScriptRepoURL() {
scriptRepoURL, err := surveyScriptRepoURL()
if err != nil {
return err
}

err = config.SetScriptRepoURL(scriptRepoURL.String())
if err != nil {
return err
}
}

if !config.HasGitHubUsername() {
githubUsername, err := surveyGitHubUsername()
if err != nil {
return err
}

err = config.SetGitHubUsername(githubUsername)
if err != nil {
return err
}
}

if !config.HasGitHubAccessToken() {
githubAccessToken, err := surveyGitHubAccessToken()
if err != nil {
return err
}

err = config.SetGitHubAccessToken(githubAccessToken)
if err != nil {
return err
}
}

err := surveyDeleteScriptDir()
if err != nil {
return err
}

err = os.Rename(config.Cfg.ScriptDir, fmt.Sprintf("%s.old_%s", config.Cfg.ScriptDir, time.Now().Format("20060102150405")))
if err != nil && !os.IsNotExist(err) {
return err
}

c, err := git.NewClient(config.Cfg.GitHubUsername, config.Cfg.GitHubAccessToken)
if err != nil {
return err
}

fmt.Println(config.Cfg.ScriptRepoURL)

err = c.Clone(config.Cfg.ScriptDir, config.Cfg.ScriptRepoURL)
if err != nil {
return err
}

return nil
}

func surveyScriptRepoURL() (*url.URL, error) {
var rawScriptRepoURL string
p := &survey.Input{
Message: "Please enter qpm script repository full URL.",
}
err := survey.AskOne(p, &rawScriptRepoURL, survey.WithValidator(survey.Required))
if err != nil {
return nil, err
}

scriptRepoURL, err := url.Parse(rawScriptRepoURL)
if err != nil {
return nil, err
}

return scriptRepoURL, nil
}

func surveyDeleteScriptDir() error {
var canDelete bool
p := &survey.Confirm{
Message: "Do you want to replace the script dir and continue?",
Default: false,
}
err := survey.AskOne(p, &canDelete)
if err != nil {
return err
}

if !canDelete {
return errors.New("To clone the script repository, the script dir must be deleted.")
}

return nil
}

func surveyGitHubUsername() (string, error) {
var githubUsername string
p := &survey.Input{
Message: "Please enter github username.",
}
err := survey.AskOne(p, &githubUsername, survey.WithValidator(survey.Required))
if err != nil {
return "", err
}

return githubUsername, nil
}

func surveyGitHubAccessToken() (string, error) {
var githubAccessToken string
p := &survey.Password{
Message: "Please enter github access token.",
}
err := survey.AskOne(p, &githubAccessToken, survey.WithValidator(survey.Required))
if err != nil {
return "", err
}

return githubAccessToken, nil
}
50 changes: 49 additions & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ func createIfNotExistConfigFile(configHome, configName, configType string) error
var Cfg Config

type Config struct {
ScriptDir string
ScriptDir string
ScriptRepoURL string
GitHubUsername string
GitHubAccessToken string
}

func Load() error {
Expand Down Expand Up @@ -94,3 +97,48 @@ func SetScriptDir(scriptDir string) error {

return viper.Unmarshal(&Cfg)
}

func HasScriptRepoURL() bool {
return len(Cfg.ScriptRepoURL) != 0
}

func SetScriptRepoURL(scriptRepoURL string) error {
viper.Set("ScriptRepoURL", scriptRepoURL)

err := viper.WriteConfig()
if err != nil {
return err
}

return viper.Unmarshal(&Cfg)
}

func HasGitHubUsername() bool {
return len(Cfg.GitHubUsername) != 0
}

func SetGitHubUsername(githubUsername string) error {
viper.Set("GitHubUsername", githubUsername)

err := viper.WriteConfig()
if err != nil {
return err
}

return viper.Unmarshal(&Cfg)
}

func HasGitHubAccessToken() bool {
return len(Cfg.GitHubAccessToken) != 0
}

func SetGitHubAccessToken(githubAccessToken string) error {
viper.Set("GitHubAccessToken", githubAccessToken)

err := viper.WriteConfig()
if err != nil {
return err
}

return viper.Unmarshal(&Cfg)
}
44 changes: 28 additions & 16 deletions internal/git/git.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package git

import (
"context"
"errors"
"net/http"

"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/transport/http"
ghttp "github.com/go-git/go-git/v5/plumbing/transport/http"
)

type client struct {
Expand All @@ -13,8 +14,15 @@ type client struct {
repo *git.Repository
}

func (c *client) Open(path string) error {
repo, err := git.PlainOpen(path)
func (c *client) Clone(path, url string) error {
o := &git.CloneOptions{
URL: url,
Auth: &ghttp.BasicAuth{
Username: c.username,
Password: c.accessToken,
},
}
repo, err := git.PlainClone(path, false, o)
if err != nil {
return err
}
Expand All @@ -24,27 +32,31 @@ func (c *client) Open(path string) error {
return nil
}

func (c *client) Clone(ctx context.Context, path, url string) error {
o := &git.CloneOptions{
URL: url,
Auth: &http.BasicAuth{
Username: c.username,
Password: c.accessToken,
},
}
repo, err := git.PlainCloneContext(ctx, path, false, o)
func (c *client) authTest() error {
req, err := http.NewRequest(http.MethodGet, "https://api.github.com/user", nil)
req.SetBasicAuth(c.username, c.accessToken)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}

c.repo = repo
if resp.StatusCode != http.StatusOK {
return errors.New("token is invalid")
}

return nil
}

func NewClient(username, accessToken string) *client {
return &client{
func NewClient(username, accessToken string) (*client, error) {
c := &client{
username: username,
accessToken: accessToken,
}

err := c.authTest()
if err != nil {
return nil, err
}

return c, nil
}

0 comments on commit 2bfda86

Please sign in to comment.