6
0
mirror of https://github.com/grdl/git-get.git synced 2026-02-04 17:24:49 +00:00

Update help commands and errors messages

This commit is contained in:
Grzegorz Dlugoszewski
2020-06-19 16:39:26 +02:00
parent de51c05158
commit 4868713746
11 changed files with 100 additions and 73 deletions

View File

@@ -11,33 +11,36 @@ import (
"github.com/spf13/viper"
)
// Gitconfig section name and env var prefix
// GitgetPrefix is the name of the gitconfig section name and the env var prefix.
const GitgetPrefix = "gitget"
// Flag keys and their default values
// CLI flag keys and their default values.
const (
KeyBranch = "branch"
DefBranch = "master"
KeyDump = "dump"
KeyDefaultHost = "defaultHost"
KeyDefaultHost = "host"
DefDefaultHost = "github.com"
KeyFetch = "fetch"
KeyOutput = "out"
DefOutput = OutTree
KeyPrivateKey = "privateKey"
DefPrivateKey = "id_rsa"
KeyReposRoot = "reposRoot"
KeyReposRoot = "root"
DefReposRoot = "repositories"
)
// Allowed values for the --out flag
// Values for the --out flag.
const (
OutDump = "dump"
OutFlat = "flat"
OutTree = "tree"
OutSmart = "smart"
OutTree = "tree"
)
// AllowedOut are allowed values for the --out flag.
var AllowedOut = []string{OutDump, OutFlat, OutSmart, OutTree}
// Version metadata set by ldflags during the build.
var (
version string

View File

@@ -1,6 +1,7 @@
package cfg
import (
"fmt"
"os"
"path"
"strings"
@@ -10,9 +11,9 @@ import (
"github.com/spf13/viper"
)
const (
EnvDefaultHost = "GITGET_DEFAULTHOST"
EnvReposRoot = "GITGET_REPOSROOT"
var (
envDefaultHost = strings.ToUpper(fmt.Sprintf("%s_%s", GitgetPrefix, KeyDefaultHost))
envReposRoot = strings.ToUpper(fmt.Sprintf("%s_%s", GitgetPrefix, KeyReposRoot))
)
func newConfigWithFullGitconfig() *gitconfig {
@@ -64,8 +65,8 @@ func newConfigWithEmptyGitconfig() *gitconfig {
}
func newConfigWithEnvVars() *gitconfig {
_ = os.Setenv(EnvDefaultHost, "env.host")
_ = os.Setenv(EnvReposRoot, "env.root")
_ = os.Setenv(envDefaultHost, "env.host")
_ = os.Setenv(envReposRoot, "env.root")
return &gitconfig{
Config: nil,
@@ -79,8 +80,8 @@ func newConfigWithGitconfigAndEnvVars() *gitconfig {
gitget.AddOption(KeyReposRoot, "file.root")
gitget.AddOption(KeyDefaultHost, "file.host")
_ = os.Setenv(EnvDefaultHost, "env.host")
_ = os.Setenv(EnvReposRoot, "env.root")
_ = os.Setenv(envDefaultHost, "env.host")
_ = os.Setenv(envReposRoot, "env.root")
return &gitconfig{
Config: cfg,
@@ -92,8 +93,8 @@ func newConfigWithEmptySectionAndEnvVars() *gitconfig {
_ = cfg.Raw.Section(GitgetPrefix)
_ = os.Setenv(EnvDefaultHost, "env.host")
_ = os.Setenv(EnvReposRoot, "env.root")
_ = os.Setenv(envDefaultHost, "env.host")
_ = os.Setenv(envReposRoot, "env.root")
return &gitconfig{
Config: cfg,
@@ -107,7 +108,7 @@ func newConfigWithMixed() *gitconfig {
gitget.AddOption(KeyReposRoot, "file.root")
gitget.AddOption(KeyDefaultHost, "file.host")
_ = os.Setenv(EnvDefaultHost, "env.host")
_ = os.Setenv(envDefaultHost, "env.host")
return &gitconfig{
Config: cfg,
@@ -150,9 +151,9 @@ func TestConfig(t *testing.T) {
// Unset env variables and reset viper registry after each test
viper.Reset()
err := os.Unsetenv(EnvDefaultHost)
err := os.Unsetenv(envDefaultHost)
checkFatal(t, err)
err = os.Unsetenv(EnvReposRoot)
err = os.Unsetenv(envReposRoot)
checkFatal(t, err)
}
}

View File

@@ -9,8 +9,8 @@ import (
)
var (
errInvalidNumberOfElements = errors.New("More than two space-separated 2 elements on the line")
errEmptyLine = errors.New("Empty line")
errInvalidNumberOfElements = errors.New("more than two space-separated 2 elements on the line")
errEmptyLine = errors.New("empty line")
)
type parsedLine struct {
@@ -22,7 +22,7 @@ type parsedLine struct {
func parseDumpFile(path string) ([]parsedLine, error) {
file, err := os.Open(path)
if err != nil {
return nil, errors.Wrapf(err, "Failed opening dump file %s", path)
return nil, errors.Wrapf(err, "failed opening dump file %s", path)
}
defer file.Close()
@@ -34,7 +34,7 @@ func parseDumpFile(path string) ([]parsedLine, error) {
line++
parsed, err := parseLine(scanner.Text())
if err != nil && !errors.Is(errEmptyLine, err) {
return nil, errors.Wrapf(err, "Failed parsing line %d", line)
return nil, errors.Wrapf(err, "failed parsing dump file line %d", line)
}
parsedLines = append(parsedLines, parsed)

View File

@@ -1,6 +1,7 @@
package pkg
import (
"fmt"
"git-get/pkg/repo"
"path"
)
@@ -16,7 +17,9 @@ type GetCfg struct {
// Get executes the "git get" command.
func Get(c *GetCfg) error {
// TODO: show something when no args
if c.URL == "" && c.Dump == "" {
return fmt.Errorf("missing <REPO> argument or --dump flag")
}
if c.URL != "" {
return cloneSingleRepo(c)

View File

@@ -51,8 +51,7 @@ func List(c *ListCfg) error {
case cfg.OutDump:
printer = &print.DumpPrinter{}
default:
// TODO: fix
return fmt.Errorf("invalid --out flag; allowed values: %v", []string{cfg.OutFlat, cfg.OutTree, cfg.OutSmart})
return fmt.Errorf("invalid --out flag; allowed values: [%s]", strings.Join(cfg.AllowedOut, ", "))
}
fmt.Println(printer.Print(c.Root, repos))
@@ -63,7 +62,7 @@ func findRepos(root string) ([]string, error) {
repos = []string{}
if _, err := os.Stat(root); err != nil {
return nil, fmt.Errorf("Repos root %s does not exist or can't be accessed", root)
return nil, fmt.Errorf("repos root %s doesn't exist or can't be accessed", root)
}
walkOpts := &godirwalk.Options{
@@ -79,7 +78,7 @@ func findRepos(root string) ([]string, error) {
}
if len(repos) == 0 {
return nil, fmt.Errorf("No git repos found in repos root %s", root)
return nil, fmt.Errorf("no git repos found in root path %s", root)
}
return repos, nil

View File

@@ -35,6 +35,7 @@ type CloneOpts struct {
IgnoreExisting bool
}
// Clone clones repository specified in CloneOpts.
func Clone(opts *CloneOpts) (*Repo, error) {
var progress io.Writer
if !opts.Quiet {
@@ -82,25 +83,27 @@ func Clone(opts *CloneOpts) (*Repo, error) {
return nil, nil
}
return nil, errors.Wrap(err, "Failed cloning repo")
return nil, errors.Wrapf(err, "failed cloning %s", opts.URL.String())
}
return New(repo, opts.Path), nil
}
func Open(repoPath string) (*Repo, error) {
repo, err := git.PlainOpen(repoPath)
// Open opens a repository on a given path.
func Open(path string) (*Repo, error) {
repo, err := git.PlainOpen(path)
if err != nil {
return nil, errors.Wrap(err, "Failed opening repo")
return nil, errors.Wrapf(err, "failed opening repo %s", path)
}
return New(repo, repoPath), nil
return New(repo, path), nil
}
func New(repo *git.Repository, repoPath string) *Repo {
// New returns a new Repo instance from a given go-git Repository.
func New(repo *git.Repository, path string) *Repo {
return &Repo{
Repository: repo,
Path: repoPath,
Path: path,
Status: &RepoStatus{},
}
}
@@ -109,13 +112,13 @@ func New(repo *git.Repository, repoPath string) *Repo {
func (r *Repo) Fetch() error {
remotes, err := r.Remotes()
if err != nil {
return errors.Wrap(err, "Failed getting remotes")
return errors.Wrapf(err, "failed getting remotes of repo %s", r.Path)
}
for _, remote := range remotes {
err = remote.Fetch(&git.FetchOptions{})
if err != nil {
return errors.Wrapf(err, "Failed fetching remote %s", remote.Config().Name)
return errors.Wrapf(err, "failed fetching remote %s", remote.Config().Name)
}
}
@@ -126,12 +129,12 @@ func sshKeyAuth() (transport.AuthMethod, error) {
privateKey := viper.GetString(cfg.KeyPrivateKey)
sshKey, err := ioutil.ReadFile(privateKey)
if err != nil {
return nil, errors.Wrapf(err, "Failed to open ssh private key %s", privateKey)
return nil, errors.Wrapf(err, "failed to open ssh private key %s", privateKey)
}
signer, err := ssh.ParsePrivateKey([]byte(sshKey))
if err != nil {
return nil, errors.Wrapf(err, "Failed to parse ssh private key %s", privateKey)
return nil, errors.Wrapf(err, "failed to parse ssh private key %s", privateKey)
}
// TODO: can it ba a different user
@@ -139,6 +142,7 @@ func sshKeyAuth() (transport.AuthMethod, error) {
return auth, nil
}
// CurrentBranchStatus returns the BranchStatus of a currently checked out branch.
func (r *Repo) CurrentBranchStatus() *BranchStatus {
if r.Status.CurrentBranch == StatusDetached || r.Status.CurrentBranch == StatusUnknown {
return nil

View File

@@ -48,13 +48,13 @@ func (r *Repo) LoadStatus() error {
if viper.GetBool(cfg.KeyFetch) {
err := r.Fetch()
if err != nil && !errors.Is(err, git.NoErrAlreadyUpToDate) {
return errors.Wrap(err, "Failed fetching from remotes")
return errors.Wrapf(err, "failed running git fetch on a repo %s", r.Path)
}
}
wt, err := r.Worktree()
if err != nil {
return errors.Wrap(err, "Failed getting worktree")
return errors.Wrapf(err, "failed getting worktree %s", r.Path)
}
// worktree.Status doesn't load gitignore patterns that are defined outside of .gitignore file using excludesfile.
@@ -62,19 +62,19 @@ func (r *Repo) LoadStatus() error {
// TODO: variables are not expanded so if excludesfile is declared like "~/gitignore_global" or "$HOME/gitignore_global", this will fail to open it
globalPatterns, err := gitignore.LoadGlobalPatterns(osfs.New(""))
if err != nil {
return errors.Wrap(err, "Failed loading global gitignore patterns")
return errors.Wrap(err, "failed loading global gitignore patterns")
}
wt.Excludes = append(wt.Excludes, globalPatterns...)
systemPatterns, err := gitignore.LoadSystemPatterns(osfs.New(""))
if err != nil {
return errors.Wrap(err, "Failed loading system gitignore patterns")
return errors.Wrap(err, "failed loading system gitignore patterns")
}
wt.Excludes = append(wt.Excludes, systemPatterns...)
status, err := wt.Status()
if err != nil {
return errors.Wrap(err, "Failed getting worktree status")
return errors.Wrapf(err, "failed getting status of worktree %s", r.Path)
}
r.Status.HasUncommittedChanges = hasUncommitted(status)
@@ -133,7 +133,7 @@ func currentBranch(r *Repo) string {
func (r *Repo) loadBranchesStatus() error {
iter, err := r.Branches()
if err != nil {
return errors.Wrap(err, "Failed getting branches iterator")
return errors.Wrapf(err, "failed getting branches iterator for repo %s", r.Path)
}
err = iter.ForEach(func(reference *plumbing.Reference) error {
@@ -146,12 +146,12 @@ func (r *Repo) loadBranchesStatus() error {
return nil
})
if err != nil {
return errors.Wrap(err, "Failed iterating over branches")
return errors.Wrapf(err, "failed iterating over branches of repo %s", r.Path)
}
// Sort branches by name (but with "master" always at the top). It's useful to have them sorted for printing and testing.
sort.Slice(r.Status.Branches, func(i, j int) bool {
if r.Status.Branches[i].Name == "master" {
if r.Status.Branches[i].Name == cfg.DefBranch {
return true
}
@@ -196,7 +196,7 @@ func (r *Repo) newBranchStatus(branch string) (*BranchStatus, error) {
func (r *Repo) upstream(branch string) (string, error) {
cfg, err := r.Config()
if err != nil {
return "", errors.Wrap(err, "Failed getting repo config")
return "", errors.Wrapf(err, "failed getting config of repo %s", r.Path)
}
// Check if our branch exists in "branch" config sections. If not, it doesn't have an upstream configured.
@@ -220,22 +220,22 @@ func (r *Repo) upstream(branch string) (string, error) {
func (r *Repo) aheadBehind(localBranch string, upstreamBranch string) (ahead int, behind int, err error) {
localHash, err := r.ResolveRevision(plumbing.Revision(localBranch))
if err != nil {
return 0, 0, errors.Wrapf(err, "Failed resolving revision %s", localBranch)
return 0, 0, errors.Wrapf(err, "failed resolving revision %s", localBranch)
}
upstreamHash, err := r.ResolveRevision(plumbing.Revision(upstreamBranch))
if err != nil {
return 0, 0, errors.Wrapf(err, "Failed resolving revision %s", upstreamBranch)
return 0, 0, errors.Wrapf(err, "failed resolving revision %s", upstreamBranch)
}
behind, err = r.revlistCount(*localHash, *upstreamHash)
if err != nil {
return 0, 0, errors.Wrapf(err, "Failed counting commits behind %s", upstreamBranch)
return 0, 0, errors.Wrapf(err, "failed counting commits behind %s", upstreamBranch)
}
ahead, err = r.revlistCount(*upstreamHash, *localHash)
if err != nil {
return 0, 0, errors.Wrapf(err, "Failed counting commits ahead of %s", upstreamBranch)
return 0, 0, errors.Wrapf(err, "failed counting commits ahead of %s", upstreamBranch)
}
return ahead, behind, nil

View File

@@ -9,7 +9,7 @@ import (
"github.com/pkg/errors"
)
var errEmptyURLPath = errors.New("Parsed URL path is empty")
var errEmptyURLPath = errors.New("parsed URL path is empty")
// scpSyntax matches the SCP-like addresses used by the ssh protocol (eg, [user@]host.xz:path/to/repo.git/).
// See: https://golang.org/src/cmd/go/internal/get/vcs.go
@@ -30,7 +30,7 @@ func ParseURL(rawURL string, defaultHost string) (url *urlpkg.URL, err error) {
} else {
url, err = urlpkg.Parse(rawURL)
if err != nil {
return nil, errors.Wrap(err, "Failed parsing URL")
return nil, errors.Wrapf(err, "failed parsing URL %s", rawURL)
}
}