mirror of
https://github.com/outbackdingo/ghorg.git
synced 2026-01-27 10:19:03 +00:00
Update reclone command logging format (#223)
This commit is contained in:
@@ -3,9 +3,12 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
|
||||
## [1.8.2] - unreleased
|
||||
## [1.8.2] - 7/6/22
|
||||
### Added
|
||||
- GHORG_RECLONE_VERBOSE flag
|
||||
- GHORG_RECLONE_QUIET flag
|
||||
### Changed
|
||||
- reclone logging format
|
||||
### Deprecated
|
||||
### Removed
|
||||
### Fixed
|
||||
|
||||
@@ -25,6 +25,14 @@ type ReClone struct {
|
||||
Cmd string `yaml:"cmd"`
|
||||
}
|
||||
|
||||
func isVerboseReClone() bool {
|
||||
return os.Getenv("GHORG_RECLONE_VERBOSE") == "true"
|
||||
}
|
||||
|
||||
func isQuietReClone() bool {
|
||||
return os.Getenv("GHORG_RECLONE_QUIET") == "true"
|
||||
}
|
||||
|
||||
func reCloneFunc(cmd *cobra.Command, argz []string) {
|
||||
|
||||
if cmd.Flags().Changed("reclone-path") {
|
||||
@@ -32,19 +40,29 @@ func reCloneFunc(cmd *cobra.Command, argz []string) {
|
||||
os.Setenv("GHORG_RECLONE_PATH", path)
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("verbose") {
|
||||
os.Setenv("GHORG_RECLONE_VERBOSE", "true")
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("quiet") {
|
||||
os.Setenv("GHORG_RECLONE_QUIET", "true")
|
||||
}
|
||||
|
||||
path := configs.GhorgReCloneLocation()
|
||||
yamlBytes, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
e := fmt.Sprintf("ERROR: parsing reclone.yaml, error: %v", err)
|
||||
colorlog.PrintErrorAndExit(e)
|
||||
colorlog.PrintErrorAndExit(fmt.Sprintf("ERROR: parsing reclone.yaml, error: %v", err))
|
||||
}
|
||||
|
||||
mapOfReClones := make(map[string]ReClone)
|
||||
|
||||
err = yaml.Unmarshal(yamlBytes, &mapOfReClones)
|
||||
if err != nil {
|
||||
e := fmt.Sprintf("ERROR: unmarshaling reclone.yaml, error:%v", err)
|
||||
colorlog.PrintErrorAndExit(e)
|
||||
colorlog.PrintErrorAndExit(fmt.Sprintf("ERROR: unmarshaling reclone.yaml, error:%v", err))
|
||||
}
|
||||
|
||||
if !isVerboseReClone() && !isQuietReClone() {
|
||||
asciiTime()
|
||||
}
|
||||
|
||||
if len(argz) == 0 {
|
||||
@@ -54,8 +72,7 @@ func reCloneFunc(cmd *cobra.Command, argz []string) {
|
||||
} else {
|
||||
for _, arg := range argz {
|
||||
if _, ok := mapOfReClones[arg]; !ok {
|
||||
e := fmt.Sprintf("ERROR: The key %v was not found in reclone.yaml", arg)
|
||||
colorlog.PrintErrorAndExit(e)
|
||||
colorlog.PrintErrorAndExit(fmt.Sprintf("ERROR: The key %v was not found in reclone.yaml", arg))
|
||||
}
|
||||
runReClone(mapOfReClones[arg])
|
||||
}
|
||||
@@ -66,18 +83,46 @@ func reCloneFunc(cmd *cobra.Command, argz []string) {
|
||||
|
||||
func printFinalOutput(argz []string, reCloneMap map[string]ReClone) {
|
||||
fmt.Println("")
|
||||
fmt.Println("Completed! The following reclones were ran...")
|
||||
colorlog.PrintSuccess("Completed! The following reclones were ran successfully...")
|
||||
if len(argz) == 0 {
|
||||
for key, _ := range reCloneMap {
|
||||
fmt.Printf(" * %v\n", key)
|
||||
colorlog.PrintSuccess(fmt.Sprintf(" * %v", key))
|
||||
}
|
||||
} else {
|
||||
for _, arg := range argz {
|
||||
fmt.Printf(" * %v\n", arg)
|
||||
colorlog.PrintSuccess(fmt.Sprintf(" * %v", arg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sanitizeCmd(cmd string) string {
|
||||
if strings.Contains(cmd, "-t=") {
|
||||
splitCmd := strings.Split(cmd, "-t=")
|
||||
firstHalf := splitCmd[0]
|
||||
secondHalf := strings.Split(splitCmd[1], " ")[1:]
|
||||
return firstHalf + "-t=XXXXXXX " + strings.Join(secondHalf, " ")
|
||||
}
|
||||
if strings.Contains(cmd, "-t ") {
|
||||
splitCmd := strings.Split(cmd, "-t ")
|
||||
firstHalf := splitCmd[0]
|
||||
secondHalf := strings.Split(splitCmd[1], " ")[1:]
|
||||
return firstHalf + "-t XXXXXXX " + strings.Join(secondHalf, " ")
|
||||
}
|
||||
if strings.Contains(cmd, "--token=") {
|
||||
splitCmd := strings.Split(cmd, "--token=")
|
||||
firstHalf := splitCmd[0]
|
||||
secondHalf := strings.Split(splitCmd[1], " ")[1:]
|
||||
return firstHalf + "--token=XXXXXXX " + strings.Join(secondHalf, " ")
|
||||
}
|
||||
if strings.Contains(cmd, "--token ") {
|
||||
splitCmd := strings.Split(cmd, "--token ")
|
||||
firstHalf := splitCmd[0]
|
||||
secondHalf := strings.Split(splitCmd[1], " ")[1:]
|
||||
return firstHalf + "--token XXXXXXX " + strings.Join(secondHalf, " ")
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runReClone(rc ReClone) {
|
||||
// make sure command starts with ghorg clone
|
||||
splitCommand := strings.Split(rc.Cmd, " ")
|
||||
@@ -86,36 +131,51 @@ func runReClone(rc ReClone) {
|
||||
if ghorg != "ghorg" || clone != "clone" {
|
||||
colorlog.PrintErrorAndExit("ERROR: Only ghorg clone commands are permitted in your reclone.yaml")
|
||||
}
|
||||
|
||||
safeToLogCmd := sanitizeCmd(strings.Clone(rc.Cmd))
|
||||
|
||||
if !isQuietReClone() {
|
||||
colorlog.PrintInfo(fmt.Sprintf("$ %v", safeToLogCmd))
|
||||
}
|
||||
|
||||
ghorgClone := exec.Command("ghorg", remainingCommand...)
|
||||
|
||||
// have to unset all ghorg envs because root command will set them on initialization of ghorg cmd
|
||||
for _, e := range os.Environ() {
|
||||
keyValue := strings.SplitN(e, "=", 2)
|
||||
ghorgEnv := strings.HasPrefix(keyValue[0], "GHORG_")
|
||||
env := keyValue[0]
|
||||
ghorgEnv := strings.HasPrefix(env, "GHORG_")
|
||||
|
||||
// skip global flags
|
||||
if env == "GHORG_COLOR" || env == "GHORG_CONFIG" || env == "GHORG_RECLONE_VERBOSE" || env == "GHORG_RECLONE_QUIET" {
|
||||
continue
|
||||
}
|
||||
if ghorgEnv {
|
||||
os.Unsetenv(keyValue[0])
|
||||
os.Unsetenv(env)
|
||||
}
|
||||
}
|
||||
|
||||
stdout, err := ghorgClone.StdoutPipe()
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: Problem with piping to stdout, err: %v", err)
|
||||
colorlog.PrintErrorAndExit(fmt.Sprintf("ERROR: Problem with piping to stdout, err: %v", err))
|
||||
}
|
||||
|
||||
err = ghorgClone.Start()
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: Starting ghorg clone cmd: %v, err: %v", rc.Cmd, err)
|
||||
colorlog.PrintErrorAndExit(fmt.Sprintf("ERROR: Starting ghorg clone cmd: %v, err: %v", safeToLogCmd, err))
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(stdout)
|
||||
for scanner.Scan() {
|
||||
m := scanner.Text()
|
||||
fmt.Println(m)
|
||||
if isVerboseReClone() && !isQuietReClone() {
|
||||
scanner := bufio.NewScanner(stdout)
|
||||
for scanner.Scan() {
|
||||
m := scanner.Text()
|
||||
fmt.Println(m)
|
||||
}
|
||||
}
|
||||
|
||||
err = ghorgClone.Wait()
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: Running ghorg clone cmd: %v, err: %v", rc.Cmd, err)
|
||||
colorlog.PrintErrorAndExit(fmt.Sprintf("ERROR: Running ghorg clone cmd: %v, err: %v", safeToLogCmd, err))
|
||||
}
|
||||
}
|
||||
|
||||
52
cmd/reclone_test.go
Normal file
52
cmd/reclone_test.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package cmd
|
||||
|
||||
import "testing"
|
||||
|
||||
func Test_sanitizeCmd(t *testing.T) {
|
||||
type args struct {
|
||||
cmd string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "shorthand with space",
|
||||
args: args{cmd: "ghorg clone foo -t bGVhdmUgYSBjb21tZW50IG9uIGlzc3VlIDY2"},
|
||||
want: "ghorg clone foo -t XXXXXXX ",
|
||||
},
|
||||
{
|
||||
name: "shorthand with equals",
|
||||
args: args{cmd: "ghorg clone foo -t=bGVhdmUgYSBjb21tZW50IG9uIGlzc3VlIDY2"},
|
||||
want: "ghorg clone foo -t=XXXXXXX ",
|
||||
},
|
||||
{
|
||||
name: "longhand with space",
|
||||
args: args{cmd: "ghorg clone foo --token bGVhdmUgYSBjb21tZW50IG9uIGlzc3VlIDY2"},
|
||||
want: "ghorg clone foo --token XXXXXXX ",
|
||||
},
|
||||
{
|
||||
name: "longhand with equals",
|
||||
args: args{cmd: "ghorg clone foo --token=bGVhdmUgYSBjb21tZW50IG9uIGlzc3VlIDY2"},
|
||||
want: "ghorg clone foo --token=XXXXXXX ",
|
||||
},
|
||||
{
|
||||
name: "shorthand with equals does not pick up other flags with t",
|
||||
args: args{cmd: "ghorg clone foo -t=bGVhdmUgYSBjb21tZW50IG9uIGlzc3VlIDY2 --topics=foo,bar"},
|
||||
want: "ghorg clone foo -t=XXXXXXX --topics=foo,bar",
|
||||
},
|
||||
{
|
||||
name: "shorthand with space does not pick up other flags with t",
|
||||
args: args{cmd: "ghorg clone foo -t bGVhdmUgYSBjb21tZW50IG9uIGlzc3VlIDY2 --topics=foo,bar"},
|
||||
want: "ghorg clone foo -t XXXXXXX --topics=foo,bar",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := sanitizeCmd(tt.args.cmd); got != tt.want {
|
||||
t.Errorf("sanitizeCmd() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
11
cmd/root.go
11
cmd/root.go
@@ -40,6 +40,8 @@ var (
|
||||
preserveDir bool
|
||||
insecureGitlabClient bool
|
||||
fetchAll bool
|
||||
ghorgReCloneVerbose bool
|
||||
ghorgReCloneQuiet bool
|
||||
args []string
|
||||
cloneErrors []string
|
||||
cloneInfos []string
|
||||
@@ -119,6 +121,10 @@ func getOrSetDefaults(envVar string) {
|
||||
os.Setenv(envVar, "false")
|
||||
case "GHORG_BACKUP":
|
||||
os.Setenv(envVar, "false")
|
||||
case "GHORG_RECLONE_VERBOSE":
|
||||
os.Setenv(envVar, "false")
|
||||
case "GHORG_RECLONE_QUIET":
|
||||
os.Setenv(envVar, "false")
|
||||
case "GHORG_COLOR":
|
||||
os.Setenv(envVar, "disabled")
|
||||
case "GHORG_PRESERVE_DIRECTORY_STRUCTURE":
|
||||
@@ -198,6 +204,8 @@ func InitConfig() {
|
||||
getOrSetDefaults("GHORG_CLONE_WIKI")
|
||||
getOrSetDefaults("GHORG_INSECURE_GITLAB_CLIENT")
|
||||
getOrSetDefaults("GHORG_BACKUP")
|
||||
getOrSetDefaults("GHORG_RECLONE_VERBOSE")
|
||||
getOrSetDefaults("GHORG_RECLONE_QUIET")
|
||||
getOrSetDefaults("GHORG_CONCURRENCY")
|
||||
getOrSetDefaults("GHORG_EXIT_CODE_ON_CLONE_INFOS")
|
||||
getOrSetDefaults("GHORG_EXIT_CODE_ON_CLONE_ISSUES")
|
||||
@@ -273,6 +281,9 @@ func init() {
|
||||
cloneCmd.Flags().StringVarP(&exitCodeOnCloneIssues, "exit-code-on-clone-issues", "", "", "GHORG_EXIT_CODE_ON_CLONE_ISSUES - Allows you to control the exit code when ghorg runs into a problem (issue level message) cloning a repo from the remote. Issue messages will appear after a clone is complete, similar to success messages (default 1)")
|
||||
|
||||
reCloneCmd.Flags().StringVarP(&ghorgReClonePath, "reclone-path", "", "", "GHORG_RECLONE_PATH - If you want to set a path other than $HOME/.config/ghorg/reclone.yaml for your reclone configuration")
|
||||
reCloneCmd.Flags().BoolVar(&ghorgReCloneVerbose, "verbose", false, "GHORG_RECLONE_VERBOSE - Verbose logging output")
|
||||
reCloneCmd.Flags().BoolVar(&ghorgReCloneQuiet, "quiet", false, "GHORG_RECLONE_QUIET - Quiet logging output")
|
||||
|
||||
rootCmd.AddCommand(lsCmd, versionCmd, cloneCmd, reCloneCmd)
|
||||
}
|
||||
|
||||
|
||||
@@ -102,11 +102,6 @@ GHORG_FETCH_ALL: false
|
||||
# flag (--ghorgignore-path)
|
||||
GHORG_IGNORE_PATH:
|
||||
|
||||
# If set allows you to specify the location of your reclone.yaml
|
||||
# Defaults to $HOME/.config/ghorg/reclone.yaml
|
||||
# flag (--reclone-path)
|
||||
GHORG_RECLONE_PATH:
|
||||
|
||||
# Only emit critical output.
|
||||
# flag (--quiet)
|
||||
GHORG_QUIET: false
|
||||
@@ -191,3 +186,23 @@ GHORG_BITBUCKET_APP_PASSWORD:
|
||||
# Used with GHORG_BITBUCKET_APP_PASSWORD. Should not be set when using GHORG_BITBUCKET_OAUTH_TOKEN
|
||||
# flag (--bitbucket-username) eg: --bitbucket-username=user123
|
||||
GHORG_BITBUCKET_USERNAME:
|
||||
|
||||
# +-+-+-+-+-+ +-+-+-+-+-+-+-+
|
||||
# |G|H|O|R|G| |R|E|C|L|O|N|E|
|
||||
# +-+-+-+-+-+ +-+-+-+-+-+-+-+
|
||||
|
||||
# Configuration for ghorg reclone command
|
||||
# See https://github.com/gabrie30/ghorg#reclone-command for more information on how to setup and use
|
||||
|
||||
# If set allows you to specify the location of your reclone.yaml
|
||||
# Defaults to $HOME/.config/ghorg/reclone.yaml
|
||||
# flag (--reclone-path)
|
||||
GHORG_RECLONE_PATH:
|
||||
|
||||
# Get more verbose logging with reclone command
|
||||
# flag (--verbose)
|
||||
GHORG_RECLONE_VERBOSE: false
|
||||
|
||||
# Quiet logging output with reclone command
|
||||
# flag (--quiet)
|
||||
GHORG_RECLONE_QUIET: false
|
||||
|
||||
Reference in New Issue
Block a user