Update reclone command logging format (#223)

This commit is contained in:
Jay Gabriels
2022-08-06 10:09:55 -07:00
committed by GitHub
parent f683d98dac
commit c1f6f48452
5 changed files with 165 additions and 24 deletions

View File

@@ -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

View File

@@ -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
View 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)
}
})
}
}

View File

@@ -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)
}

View File

@@ -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