提交 111100c5 编写于 作者: J Jingwen Owen Ou

Merge pull request #764 from github/parse_global_flag

Properly parse global flags:
......@@ -2,13 +2,17 @@ package commands
import (
"fmt"
"io/ioutil"
"strings"
"github.com/github/hub/cmd"
flag "github.com/github/hub/Godeps/_workspace/src/github.com/ogier/pflag"
)
type Args struct {
Executable string
GlobalFlags []string
Command string
Params []string
beforeChain []*cmd.Cmd
......@@ -156,12 +160,13 @@ func (a *Args) HasFlags(flags ...string) bool {
func NewArgs(args []string) *Args {
var (
command string
params []string
noop bool
command string
params []string
noop bool
globalFlags []string
)
args, noop = slurpGlobalFlags(args)
slurpGlobalFlags(&args, &globalFlags, &noop)
if len(args) == 0 {
params = []string{}
......@@ -172,6 +177,7 @@ func NewArgs(args []string) *Args {
return &Args{
Executable: "git",
GlobalFlags: globalFlags,
Command: command,
Params: params,
Noop: noop,
......@@ -180,22 +186,90 @@ func NewArgs(args []string) *Args {
}
}
func slurpGlobalFlags(args []string) (aa []string, noop bool) {
aa = make([]string, 0)
for _, arg := range args {
if arg == "--noop" {
noop = true
continue
}
func slurpGlobalFlags(args *[]string, globalFlags *[]string, noop *bool) {
var (
globalFlagSet flag.FlagSet
configParam mapValue = make(mapValue)
paginate bool
noPaginate bool
noReplaceObjects bool
bare bool
version bool
help bool
execPath string
gitDir string
workTree string
)
if arg == "--version" || arg == "--help" {
arg = strings.TrimPrefix(arg, "--")
}
globalFlagSet.BoolVarP(noop, "noop", "", false, "")
globalFlagSet.VarP(configParam, "", "c", "")
globalFlagSet.BoolVarP(&paginate, "paginate", "p", false, "")
globalFlagSet.BoolVarP(&noPaginate, "no-pager", "", false, "")
globalFlagSet.BoolVarP(&noReplaceObjects, "no-replace-objects", "", false, "")
globalFlagSet.BoolVarP(&bare, "bare", "", false, "")
globalFlagSet.BoolVarP(&version, "version", "", false, "")
globalFlagSet.BoolVarP(&help, "help", "", false, "")
globalFlagSet.StringVarP(&execPath, "exec-path", "", "", "")
globalFlagSet.StringVarP(&gitDir, "git-dir", "", "", "")
globalFlagSet.StringVarP(&workTree, "work-tree", "", "", "")
globalFlagSet.SetOutput(ioutil.Discard)
globalFlagSet.Init("hub", flag.ContinueOnError)
aa := make([]string, 0)
err := globalFlagSet.Parse(*args)
if err == nil {
aa = globalFlagSet.Args()
} else {
aa = *args
}
// manipulate global flags
if version {
aa = append([]string{"version"}, aa...)
}
if help {
aa = append([]string{"help"}, aa...)
}
for k, v := range configParam {
*globalFlags = append(*globalFlags, "-c")
*globalFlags = append(*globalFlags, fmt.Sprintf("%s=%s", k, v))
}
if paginate {
*globalFlags = append(*globalFlags, "--paginate")
}
if noPaginate {
*globalFlags = append(*globalFlags, "--no-pager")
}
if noReplaceObjects {
*globalFlags = append(*globalFlags, "--no-replace-objects")
}
if bare {
*globalFlags = append(*globalFlags, "--bare")
}
if execPath != "" {
*globalFlags = append(*globalFlags, "--exec-path", execPath)
}
if gitDir != "" {
*globalFlags = append(*globalFlags, "--git-dir", gitDir)
}
aa = append(aa, arg)
if workTree != "" {
*globalFlags = append(*globalFlags, "--work-tree", workTree)
}
return
*args = aa
}
func removeItem(slice []string, index int) (newSlice []string, item string) {
......
package commands
import (
"strings"
"testing"
"github.com/github/hub/Godeps/_workspace/src/github.com/bmizerany/assert"
......@@ -31,6 +32,14 @@ func TestNewArgs(t *testing.T) {
args = NewArgs([]string{"--help"})
assert.Equal(t, "help", args.Command)
assert.Equal(t, 0, args.ParamsSize())
args = NewArgs([]string{"--noop", "--version"})
assert.T(t, args.Noop)
assert.Equal(t, "version", args.Command)
args = NewArgs([]string{"-c", "foo=bar", "--git-dir=path", "--bare"})
assert.Equal(t, 5, len(args.GlobalFlags))
assert.Equal(t, "-c foo=bar --bare --git-dir path", strings.Join(args.GlobalFlags, " "))
}
func TestArgs_Words(t *testing.T) {
......@@ -64,11 +73,3 @@ func TestArgs_Remove(t *testing.T) {
assert.Equal(t, "2", args.FirstParam())
assert.Equal(t, "4", args.GetParam(1))
}
func TestSlurpGlobalFlags(t *testing.T) {
args := []string{"--noop", "--version"}
aa, noop := slurpGlobalFlags(args)
assert.T(t, noop)
assert.Equal(t, []string{"version"}, aa)
}
......@@ -30,7 +30,7 @@ type Command struct {
}
func (c *Command) Call(args *Args) (err error) {
runCommand, err := lookupCommand(c, args)
runCommand, err := c.lookupSubCommand(args)
if err != nil {
fmt.Println(err)
return
......@@ -113,7 +113,7 @@ func (c *Command) List() bool {
return c.Short != ""
}
func lookupCommand(c *Command, args *Args) (runCommand *Command, err error) {
func (c *Command) lookupSubCommand(args *Args) (runCommand *Command, err error) {
if len(c.subCommands) > 0 && args.HasSubcommand() {
subCommandName := args.FirstParam()
if subCommand, ok := c.subCommands[subCommandName]; ok {
......
package commands
import (
"github.com/github/hub/Godeps/_workspace/src/github.com/bmizerany/assert"
"testing"
"github.com/github/hub/Godeps/_workspace/src/github.com/bmizerany/assert"
)
func TestCommandUseSelf(t *testing.T) {
......@@ -10,7 +11,7 @@ func TestCommandUseSelf(t *testing.T) {
args := NewArgs([]string{"foo"})
run, err := lookupCommand(c, args)
run, err := c.lookupSubCommand(args)
assert.Equal(t, nil, err)
assert.Equal(t, c, run)
......@@ -23,7 +24,7 @@ func TestCommandUseSubcommand(t *testing.T) {
args := NewArgs([]string{"foo", "bar"})
run, err := lookupCommand(c, args)
run, err := c.lookupSubCommand(args)
assert.Equal(t, nil, err)
assert.Equal(t, s, run)
......@@ -36,7 +37,7 @@ func TestCommandUseErrorWhenMissingSubcommand(t *testing.T) {
args := NewArgs([]string{"foo", "baz"})
_, err := lookupCommand(c, args)
_, err := c.lookupSubCommand(args)
assert.NotEqual(t, nil, err)
}
......@@ -46,7 +47,7 @@ func TestArgsForCommand(t *testing.T) {
args := NewArgs([]string{"foo", "bar", "baz"})
lookupCommand(c, args)
c.lookupSubCommand(args)
assert.Equal(t, 2, len(args.Params))
}
......@@ -58,7 +59,7 @@ func TestArgsForSubCommand(t *testing.T) {
args := NewArgs([]string{"foo", "bar", "baz"})
lookupCommand(c, args)
c.lookupSubCommand(args)
assert.Equal(t, 1, len(args.Params))
}
......
package commands
import (
"fmt"
"strings"
)
type stringSliceValue []string
func (s *stringSliceValue) Set(val string) error {
*s = append(*s, val)
return nil
}
func (s *stringSliceValue) String() string {
return fmt.Sprintf("%s", *s)
}
type mapValue map[string]string
func (m mapValue) Set(val string) error {
v := strings.SplitN(val, "=", 2)
if len(v) != 2 {
return fmt.Errorf("Flag should be in the format of <name>=<value>")
}
m[v[0]] = v[1]
return nil
}
func (m mapValue) String() string {
s := make([]string, 0)
for k, v := range m {
s = append(s, fmt.Sprintf("%s=%s", k, v))
}
return strings.Join(s, ",")
}
......@@ -15,17 +15,6 @@ import (
"github.com/github/hub/utils"
)
type stringSliceValue []string
func (s *stringSliceValue) Set(val string) error {
*s = append(*s, val)
return nil
}
func (s *stringSliceValue) String() string {
return fmt.Sprintf("%s", *s)
}
var (
cmdRelease = &Command{
Run: release,
......
......@@ -73,6 +73,7 @@ func (r *Runner) Execute() ExecError {
err := updater.PromptForUpdate()
utils.Check(err)
git.GlobalFlags = args.GlobalFlags // preserve git global flags
expandAlias(args)
cmd := r.Lookup(args.Command)
......
......@@ -10,8 +10,10 @@ import (
"github.com/github/hub/cmd"
)
var GlobalFlags []string
func Version() (string, error) {
output, err := execGitCmd("version")
output, err := gitOutput("version")
if err != nil {
return "", fmt.Errorf("Can't load git version")
}
......@@ -20,7 +22,7 @@ func Version() (string, error) {
}
func Dir() (string, error) {
output, err := execGitCmd("rev-parse", "-q", "--git-dir")
output, err := gitOutput("rev-parse", "-q", "--git-dir")
if err != nil {
return "", fmt.Errorf("Not a git repository (or any of the parent directories): .git")
}
......@@ -77,7 +79,7 @@ func BranchAtRef(paths ...string) (name string, err error) {
}
func Editor() (string, error) {
output, err := execGitCmd("var", "GIT_EDITOR")
output, err := gitOutput("var", "GIT_EDITOR")
if err != nil {
return "", fmt.Errorf("Can't load git var: GIT_EDITOR")
}
......@@ -90,7 +92,7 @@ func Head() (string, error) {
}
func SymbolicFullName(name string) (string, error) {
output, err := execGitCmd("rev-parse", "--symbolic-full-name", name)
output, err := gitOutput("rev-parse", "--symbolic-full-name", name)
if err != nil {
return "", fmt.Errorf("Unknown revision or path not in the working tree: %s", name)
}
......@@ -99,7 +101,7 @@ func SymbolicFullName(name string) (string, error) {
}
func Ref(ref string) (string, error) {
output, err := execGitCmd("rev-parse", "-q", ref)
output, err := gitOutput("rev-parse", "-q", ref)
if err != nil {
return "", fmt.Errorf("Unknown revision or path not in the working tree: %s", ref)
}
......@@ -109,7 +111,7 @@ func Ref(ref string) (string, error) {
func RefList(a, b string) ([]string, error) {
ref := fmt.Sprintf("%s...%s", a, b)
output, err := execGitCmd("rev-list", "--cherry-pick", "--right-only", "--no-merges", ref)
output, err := gitOutput("rev-list", "--cherry-pick", "--right-only", "--no-merges", ref)
if err != nil {
return []string{}, fmt.Errorf("Can't load rev-list for %s", ref)
}
......@@ -153,7 +155,7 @@ func Log(sha1, sha2 string) (string, error) {
}
func Remotes() ([]string, error) {
return execGitCmd("remote", "-v")
return gitOutput("remote", "-v")
}
func Config(name string) (string, error) {
......@@ -170,7 +172,7 @@ func SetGlobalConfig(name, value string) error {
}
func gitGetConfig(args ...string) (string, error) {
output, err := execGitCmd(gitConfigCommand(args)...)
output, err := gitOutput(gitConfigCommand(args)...)
if err != nil {
return "", fmt.Errorf("Unknown config %s", args[len(args)-1])
}
......@@ -179,7 +181,7 @@ func gitGetConfig(args ...string) (string, error) {
}
func gitConfig(args ...string) ([]string, error) {
return execGitCmd(gitConfigCommand(args)...)
return gitOutput(gitConfigCommand(args)...)
}
func gitConfigCommand(args []string) []string {
......@@ -193,7 +195,13 @@ func Alias(name string) (string, error) {
func Run(command string, args ...string) error {
cmd := cmd.New("git")
for _, v := range GlobalFlags {
cmd.WithArg(v)
}
cmd.WithArg(command)
for _, a := range args {
cmd.WithArg(a)
}
......@@ -201,8 +209,13 @@ func Run(command string, args ...string) error {
return cmd.Run()
}
func execGitCmd(input ...string) (outputs []string, err error) {
func gitOutput(input ...string) (outputs []string, err error) {
cmd := cmd.New("git")
for _, v := range GlobalFlags {
cmd.WithArg(v)
}
for _, i := range input {
cmd.WithArg(i)
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册