aboutsummaryrefslogtreecommitdiffstats
path: root/commands
diff options
context:
space:
mode:
Diffstat (limited to 'commands')
-rw-r--r--commands/bug/bug.go33
-rw-r--r--commands/bug/bug_test.go89
-rw-r--r--commands/cmdtest/regex.go62
-rw-r--r--commands/cmdtest/regex_test.go25
-rw-r--r--commands/root.go65
5 files changed, 225 insertions, 49 deletions
diff --git a/commands/bug/bug.go b/commands/bug/bug.go
index 4c83ffa5..55a1fa59 100644
--- a/commands/bug/bug.go
+++ b/commands/bug/bug.go
@@ -21,17 +21,18 @@ import (
)
type bugOptions struct {
- statusQuery []string
- authorQuery []string
- metadataQuery []string
- participantQuery []string
- actorQuery []string
- labelQuery []string
- titleQuery []string
- noQuery []string
- sortBy string
- sortDirection string
- outputFormat string
+ statusQuery []string
+ authorQuery []string
+ metadataQuery []string
+ participantQuery []string
+ actorQuery []string
+ labelQuery []string
+ titleQuery []string
+ noQuery []string
+ sortBy string
+ sortDirection string
+ outputFormat string
+ outputFormatChanged bool
}
func NewBugCommand(env *execenv.Env) *cobra.Command {
@@ -57,6 +58,7 @@ git bug status:open --by creation "foo bar" baz
`,
PreRunE: execenv.LoadBackend(env),
RunE: execenv.CloseBackend(env, func(cmd *cobra.Command, args []string) error {
+ options.outputFormatChanged = cmd.Flags().Changed("format")
return runBug(env, options, args)
}),
ValidArgsFunction: completion.Ls(env),
@@ -93,7 +95,7 @@ git bug status:open --by creation "foo bar" baz
flags.StringVarP(&options.sortDirection, "direction", "d", "asc",
"Select the sorting direction. Valid values are [asc,desc]")
cmd.RegisterFlagCompletionFunc("direction", completion.From([]string{"asc", "desc"}))
- flags.StringVarP(&options.outputFormat, "format", "f", "",
+ flags.StringVarP(&options.outputFormat, "format", "f", "default",
"Select the output formatting style. Valid values are [default,plain,id,json,org-mode]")
cmd.RegisterFlagCompletionFunc("format",
completion.From([]string{"default", "plain", "id", "json", "org-mode"}))
@@ -156,14 +158,15 @@ func runBug(env *execenv.Env, opts bugOptions, args []string) error {
}
switch opts.outputFormat {
- case "":
+ case "default":
+ if opts.outputFormatChanged {
+ return bugsDefaultFormatter(env, excerpts)
+ }
if env.Out.IsTerminal() {
return bugsDefaultFormatter(env, excerpts)
} else {
return bugsPlainFormatter(env, excerpts)
}
- case "default":
- return bugsDefaultFormatter(env, excerpts)
case "id":
return bugsIDFormatter(env, excerpts)
case "plain":
diff --git a/commands/bug/bug_test.go b/commands/bug/bug_test.go
index e6fadd6f..c13e8db7 100644
--- a/commands/bug/bug_test.go
+++ b/commands/bug/bug_test.go
@@ -1,13 +1,12 @@
package bugcmd
import (
- "encoding/json"
"testing"
"github.com/stretchr/testify/require"
"github.com/MichaelMure/git-bug/commands/bug/testenv"
- "github.com/MichaelMure/git-bug/commands/cmdjson"
+ . "github.com/MichaelMure/git-bug/commands/cmdtest"
)
func Test_repairQuery(t *testing.T) {
@@ -47,24 +46,69 @@ func Test_repairQuery(t *testing.T) {
}
func TestBug_Format(t *testing.T) {
- const expOrgMode = `^#+TODO: OPEN | CLOSED
-[*] OPEN [0-9a-f]{7} \[\d\d\d\d-\d\d-\d\d [[:alpha:]]{3} \d\d:\d\d\] John Doe: this is a bug title ::
-[*]{2} Last Edited: \[\d\d\d\d-\d\d-\d\d [[:alpha:]]{3} \d\d:\d\d\]
-[*]{2} Actors:
-: [0-9a-f]{7} John Doe
-[*]{2} Participants:
-: [0-9a-f]{7} John Doe
-$`
+ const expOrgMode = `#+TODO: OPEN | CLOSED
+* OPEN ` + ExpHumanId + ` [` + ExpOrgModeDate + `] John Doe: this is a bug title ::
+** Last Edited: [` + ExpOrgModeDate + `]
+** Actors:
+: ` + ExpHumanId + ` John Doe
+** Participants:
+: ` + ExpHumanId + ` John Doe
+`
+
+ const expJson = `[
+ {
+ "id": "` + ExpId + `",
+ "human_id": "` + ExpHumanId + `",
+ "create_time": {
+ "timestamp": ` + ExpTimestamp + `,
+ "time": "` + ExpISO8601 + `",
+ "lamport": 2
+ },
+ "edit_time": {
+ "timestamp": ` + ExpTimestamp + `,
+ "time": "` + ExpISO8601 + `",
+ "lamport": 2
+ },
+ "status": "open",
+ "labels": null,
+ "title": "this is a bug title",
+ "actors": [
+ {
+ "id": "` + ExpId + `",
+ "human_id": "` + ExpHumanId + `",
+ "name": "John Doe",
+ "login": ""
+ }
+ ],
+ "participants": [
+ {
+ "id": "` + ExpId + `",
+ "human_id": "` + ExpHumanId + `",
+ "name": "John Doe",
+ "login": ""
+ }
+ ],
+ "author": {
+ "id": "` + ExpId + `",
+ "human_id": "` + ExpHumanId + `",
+ "name": "John Doe",
+ "login": ""
+ },
+ "comments": 1,
+ "metadata": {}
+ }
+]
+`
cases := []struct {
format string
exp string
}{
- {"default", "^[0-9a-f]{7}\topen\tthis is a bug title John Doe \n$"},
- {"plain", "^[0-9a-f]{7}\topen\tthis is a bug title\n$"},
- {"id", "^[0-9a-f]{64}\n$"},
+ {"default", ExpHumanId + "\topen\tthis is a bug title John Doe \n"},
+ {"plain", ExpHumanId + "\topen\tthis is a bug title\n"},
+ {"id", ExpId + "\n"},
{"org-mode", expOrgMode},
- {"json", ".*"},
+ {"json", expJson},
}
for _, testcase := range cases {
@@ -72,21 +116,14 @@ $`
env, _ := testenv.NewTestEnvAndBug(t)
opts := bugOptions{
- sortDirection: "asc",
- sortBy: "creation",
- outputFormat: testcase.format,
+ sortDirection: "asc",
+ sortBy: "creation",
+ outputFormat: testcase.format,
+ outputFormatChanged: true, // disable auto-detect
}
require.NoError(t, runBug(env, opts, []string{}))
-
- switch testcase.format {
- case "json":
- var bugs []cmdjson.BugExcerpt
- require.NoError(t, json.Unmarshal(env.Out.Bytes(), &bugs))
- require.Len(t, bugs, 1)
- default:
- require.Regexp(t, testcase.exp, env.Out.String())
- }
+ require.Regexp(t, MakeExpectedRegex(testcase.exp), env.Out.String())
})
}
}
diff --git a/commands/cmdtest/regex.go b/commands/cmdtest/regex.go
new file mode 100644
index 00000000..0b9cb672
--- /dev/null
+++ b/commands/cmdtest/regex.go
@@ -0,0 +1,62 @@
+package cmdtest
+
+import (
+ "regexp"
+ "strings"
+)
+
+const ExpId = "\x07id\x07"
+const ExpHumanId = "\x07human-id\x07"
+const ExpTimestamp = "\x07timestamp\x07"
+const ExpISO8601 = "\x07iso8601\x07"
+
+const ExpOrgModeDate = "\x07org-mode-date\x07"
+
+// MakeExpectedRegex transform a raw string of an expected output into a regex suitable for testing.
+// Some markers like ExpId are available to substitute the appropriate regex for element that can vary randomly.
+func MakeExpectedRegex(input string) string {
+ var substitutes = map[string]string{
+ ExpId: `[0-9a-f]{64}`,
+ ExpHumanId: `[0-9a-f]{7}`,
+ ExpTimestamp: `[0-9]{7,10}`,
+ ExpISO8601: `\d{4}(-\d\d(-\d\d(T\d\d:\d\d(:\d\d)?(\.\d+)?(([+-]\d\d:\d\d)|Z)?)?)?)?`,
+ ExpOrgModeDate: `\d\d\d\d-\d\d-\d\d [[:alpha:]]{3} \d\d:\d\d`,
+ }
+
+ escaped := []rune(regexp.QuoteMeta(input))
+
+ var result strings.Builder
+ var inSubstitute bool
+ var substitute strings.Builder
+
+ result.WriteString("^")
+
+ for i := 0; i < len(escaped); i++ {
+ r := escaped[i]
+ if !inSubstitute && r == '\x07' {
+ substitute.Reset()
+ substitute.WriteRune(r)
+ inSubstitute = true
+ continue
+ }
+ if inSubstitute && r == '\x07' {
+ substitute.WriteRune(r)
+ sub, ok := substitutes[substitute.String()]
+ if !ok {
+ panic("unknown substitute: " + substitute.String())
+ }
+ result.WriteString(sub)
+ inSubstitute = false
+ continue
+ }
+ if inSubstitute {
+ substitute.WriteRune(r)
+ } else {
+ result.WriteRune(r)
+ }
+ }
+
+ result.WriteString("$")
+
+ return result.String()
+}
diff --git a/commands/cmdtest/regex_test.go b/commands/cmdtest/regex_test.go
new file mode 100644
index 00000000..7f2e75fa
--- /dev/null
+++ b/commands/cmdtest/regex_test.go
@@ -0,0 +1,25 @@
+package cmdtest
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestMakeExpectedRegex(t *testing.T) {
+ cases := []struct {
+ sub string
+ text string
+ }{
+ {ExpId, "d96dc877077a571414168c946eb013035888715b561e75682cfae9ef785e3227"},
+ {ExpHumanId, "d96dc87"},
+ {ExpTimestamp, "1674368486"},
+ {ExpISO8601, "2023-01-22T07:21:26+01:00"},
+ }
+
+ for _, tc := range cases {
+ t.Run(tc.sub, func(t *testing.T) {
+ require.Regexp(t, MakeExpectedRegex(tc.text), tc.text)
+ })
+ }
+}
diff --git a/commands/root.go b/commands/root.go
index aace1956..01c817ee 100644
--- a/commands/root.go
+++ b/commands/root.go
@@ -4,6 +4,7 @@ package commands
import (
"fmt"
"os"
+ "runtime/debug"
"github.com/spf13/cobra"
@@ -32,14 +33,7 @@ the same git remote you are already using to collaborate with other people.
PersistentPreRun: func(cmd *cobra.Command, args []string) {
root := cmd.Root()
-
- if GitExactTag == "undefined" {
- GitExactTag = ""
- }
- root.Version = GitLastTag
- if GitExactTag == "" {
- root.Version = fmt.Sprintf("%s-dev-%.10s", root.Version, GitCommit)
- }
+ root.Version = getVersion()
},
// For the root command, force the execution of the PreRun
@@ -93,3 +87,58 @@ func Execute() {
os.Exit(1)
}
}
+
+func getVersion() string {
+ if GitExactTag == "undefined" {
+ GitExactTag = ""
+ }
+
+ if GitExactTag != "" {
+ // we are exactly on a tag --> release version
+ return GitLastTag
+ }
+
+ if GitLastTag != "" {
+ // not exactly on a tag --> dev version
+ return fmt.Sprintf("%s-dev-%.10s", GitLastTag, GitCommit)
+ }
+
+ // we don't have commit information, try golang build info
+ if commit, dirty, err := getCommitAndDirty(); err == nil {
+ if dirty {
+ return fmt.Sprintf("dev-%.10s-dirty", commit)
+ }
+ return fmt.Sprintf("dev-%.10s", commit)
+ }
+
+ return "dev-unknown"
+}
+
+func getCommitAndDirty() (commit string, dirty bool, err error) {
+ info, ok := debug.ReadBuildInfo()
+ if !ok {
+ return "", false, fmt.Errorf("unable to read build info")
+ }
+
+ var commitFound bool
+
+ // get the commit and modified status
+ // (that is the flag for repository dirty or not)
+ for _, kv := range info.Settings {
+ switch kv.Key {
+ case "vcs.revision":
+ commit = kv.Value
+ commitFound = true
+ case "vcs.modified":
+ if kv.Value == "true" {
+ dirty = true
+ }
+ }
+ }
+
+ if !commitFound {
+ return "", false, fmt.Errorf("no commit found")
+ }
+
+ return commit, dirty, nil
+}