aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchris.lu@gmail.com <chris.lu@gmail.com@282b0af5-e82d-9cf1-ede4-77906d7719d0>2012-08-06 23:54:53 +0000
committerchris.lu@gmail.com <chris.lu@gmail.com@282b0af5-e82d-9cf1-ede4-77906d7719d0>2012-08-06 23:54:53 +0000
commit51860424a6036cd9bda3422f10849d180bd1d36e (patch)
treeab2b9945fcfa16bc633a49e5463d2e753dc4e4f4
parentc62794269165275361c1475ff803fc24784836a4 (diff)
downloadseaweedfs-51860424a6036cd9bda3422f10849d180bd1d36e.tar.xz
seaweedfs-51860424a6036cd9bda3422f10849d180bd1d36e.zip
moving to go style commands
git-svn-id: https://weed-fs.googlecode.com/svn/trunk@62 282b0af5-e82d-9cf1-ede4-77906d7719d0
-rw-r--r--weed-fs/src/cmd/weed/command.go53
-rw-r--r--weed-fs/src/cmd/weed/version.go25
-rw-r--r--weed-fs/src/cmd/weed/weed.go190
3 files changed, 268 insertions, 0 deletions
diff --git a/weed-fs/src/cmd/weed/command.go b/weed-fs/src/cmd/weed/command.go
new file mode 100644
index 000000000..aa59459bd
--- /dev/null
+++ b/weed-fs/src/cmd/weed/command.go
@@ -0,0 +1,53 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+)
+
+type Command struct {
+ // Run runs the command.
+ // The args are the arguments after the command name.
+ Run func(cmd *Command, args []string)
+
+ // UsageLine is the one-line usage message.
+ // The first word in the line is taken to be the command name.
+ UsageLine string
+
+ // Short is the short description shown in the 'go help' output.
+ Short string
+
+ // Long is the long message shown in the 'go help <this-command>' output.
+ Long string
+
+ // Flag is a set of flags specific to this command.
+ Flag flag.FlagSet
+
+ // CustomFlags indicates that the command will do its own
+ // flag parsing.
+ CustomFlags bool
+}
+
+// Name returns the command's name: the first word in the usage line.
+func (c *Command) Name() string {
+ name := c.UsageLine
+ i := strings.Index(name, " ")
+ if i >= 0 {
+ name = name[:i]
+ }
+ return name
+}
+
+func (c *Command) Usage() {
+ fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine)
+ fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
+ os.Exit(2)
+}
+
+// Runnable reports whether the command can be run; otherwise
+// it is a documentation pseudo-command such as importpath.
+func (c *Command) Runnable() bool {
+ return c.Run != nil
+}
diff --git a/weed-fs/src/cmd/weed/version.go b/weed-fs/src/cmd/weed/version.go
new file mode 100644
index 000000000..a04dd79f4
--- /dev/null
+++ b/weed-fs/src/cmd/weed/version.go
@@ -0,0 +1,25 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+var cmdVersion = &Command{
+ Run: runVersion,
+ UsageLine: "version",
+ Short: "print Weed File System version",
+ Long: `Version prints the Weed File System version`,
+}
+
+func runVersion(cmd *Command, args []string) {
+ if len(args) != 0 {
+ cmd.Usage()
+ }
+
+ fmt.Printf("version 0.15 %s %s\n",runtime.GOOS, runtime.GOARCH)
+}
diff --git a/weed-fs/src/cmd/weed/weed.go b/weed-fs/src/cmd/weed/weed.go
new file mode 100644
index 000000000..06668f448
--- /dev/null
+++ b/weed-fs/src/cmd/weed/weed.go
@@ -0,0 +1,190 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "strings"
+ "sync"
+ "text/template"
+ "unicode"
+ "unicode/utf8"
+)
+
+var commands = []*Command{
+ cmdVersion,
+}
+
+var exitStatus = 0
+var exitMu sync.Mutex
+
+func setExitStatus(n int) {
+ exitMu.Lock()
+ if exitStatus < n {
+ exitStatus = n
+ }
+ exitMu.Unlock()
+}
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+ log.SetFlags(0)
+
+ args := flag.Args()
+ if len(args) < 1 {
+ usage()
+ }
+
+ if args[0] == "help" {
+ help(args[1:])
+ return
+ }
+
+ for _, cmd := range commands {
+ if cmd.Name() == args[0] && cmd.Run != nil {
+ cmd.Flag.Usage = func() { cmd.Usage() }
+ if cmd.CustomFlags {
+ args = args[1:]
+ } else {
+ cmd.Flag.Parse(args[1:])
+ args = cmd.Flag.Args()
+ }
+ cmd.Run(cmd, args)
+ exit()
+ return
+ }
+ }
+
+ fmt.Fprintf(os.Stderr, "weed: unknown subcommand %q\nRun 'weed help' for usage.\n", args[0])
+ setExitStatus(2)
+ exit()
+}
+
+var usageTemplate = `Go is a tool for managing Go source code.
+
+Usage:
+
+ weed command [arguments]
+
+The commands are:
+{{range .}}{{if .Runnable}}
+ {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
+
+Use "weed help [command]" for more information about a command.
+
+Additional help topics:
+{{range .}}{{if not .Runnable}}
+ {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
+
+Use "weed help [topic]" for more information about that topic.
+
+`
+
+var helpTemplate = `{{if .Runnable}}usage: weed {{.UsageLine}}
+
+{{end}}{{.Long | trim}}
+`
+
+// tmpl executes the given template text on data, writing the result to w.
+func tmpl(w io.Writer, text string, data interface{}) {
+ t := template.New("top")
+ t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
+ template.Must(t.Parse(text))
+ if err := t.Execute(w, data); err != nil {
+ panic(err)
+ }
+}
+
+func capitalize(s string) string {
+ if s == "" {
+ return s
+ }
+ r, n := utf8.DecodeRuneInString(s)
+ return string(unicode.ToTitle(r)) + s[n:]
+}
+
+func printUsage(w io.Writer) {
+ tmpl(w, usageTemplate, commands)
+}
+
+func usage() {
+ printUsage(os.Stderr)
+ os.Exit(2)
+}
+
+// help implements the 'help' command.
+func help(args []string) {
+ if len(args) == 0 {
+ printUsage(os.Stdout)
+ // not exit 2: succeeded at 'weed help'.
+ return
+ }
+ if len(args) != 1 {
+ fmt.Fprintf(os.Stderr, "usage: weed help command\n\nToo many arguments given.\n")
+ os.Exit(2) // failed at 'weed help'
+ }
+
+ arg := args[0]
+
+ for _, cmd := range commands {
+ if cmd.Name() == arg {
+ tmpl(os.Stdout, helpTemplate, cmd)
+ // not exit 2: succeeded at 'weed help cmd'.
+ return
+ }
+ }
+
+ fmt.Fprintf(os.Stderr, "Unknown help topic %#q. Run 'weed help'.\n", arg)
+ os.Exit(2) // failed at 'weed help cmd'
+}
+
+var atexitFuncs []func()
+
+func atexit(f func()) {
+ atexitFuncs = append(atexitFuncs, f)
+}
+
+func exit() {
+ for _, f := range atexitFuncs {
+ f()
+ }
+ os.Exit(exitStatus)
+}
+
+func fatalf(format string, args ...interface{}) {
+ errorf(format, args...)
+ exit()
+}
+
+func errorf(format string, args ...interface{}) {
+ log.Printf(format, args...)
+ setExitStatus(1)
+}
+
+var logf = log.Printf
+
+func exitIfErrors() {
+ if exitStatus != 0 {
+ exit()
+ }
+}
+
+// stringList's arguments should be a sequence of string or []string values.
+// stringList flattens them into a single []string.
+func stringList(args ...interface{}) []string {
+ var x []string
+ for _, arg := range args {
+ switch arg := arg.(type) {
+ case []string:
+ x = append(x, arg...)
+ case string:
+ x = append(x, arg)
+ default:
+ panic("stringList: invalid argument")
+ }
+ }
+ return x
+}