Add uniqueid command that generates uniqueid.IDs and replaces them
in files
Change-Id: I7bd9ee4875f991a2988c04edfcbb3ac890ad7f93
diff --git a/tools/uniqueid/doc.go b/tools/uniqueid/doc.go
new file mode 100644
index 0000000..5fdbcab
--- /dev/null
+++ b/tools/uniqueid/doc.go
@@ -0,0 +1,57 @@
+// This file was auto-generated via go generate.
+// DO NOT UPDATE MANUALLY
+
+/*
+The uniqueid tool generates unique ids. It also has an option of automatically
+substituting unique ids with placeholders in files.
+
+Usage:
+ uniqueid <command>
+
+The uniqueid commands are:
+ generate Generates UniqueIds
+ inject Injects UniqueIds into existing files
+ help Display help for commands or topics
+Run "uniqueid help [command]" for command usage.
+
+Uniqueid Generate
+
+Generates unique ids and outputs them to standard out.
+
+Usage:
+ uniqueid generate
+
+Uniqueid Inject
+
+Injects UniqueIds into existing files. Strings of the form "$UNIQUEID$" will be
+replaced with generated ids.
+
+Usage:
+ uniqueid inject <filenames>
+
+<filenames> List of files to inject unique ids into
+
+Uniqueid Help
+
+Help with no args displays the usage of the parent command.
+
+Help with args displays the usage of the specified sub-command or help topic.
+
+"help ..." recursively displays help for all commands and topics.
+
+The output is formatted to a target width in runes. The target width is
+determined by checking the environment variable CMDLINE_WIDTH, falling back on
+the terminal width from the OS, falling back on 80 chars. By setting
+CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
+if x == 0 or is unset one of the fallbacks is used.
+
+Usage:
+ uniqueid help [flags] [command/topic ...]
+
+[command/topic ...] optionally identifies a specific sub-command or help topic.
+
+The uniqueid help flags are:
+ -style=text
+ The formatting style for help output, either "text" or "godoc".
+*/
+package main
diff --git a/tools/uniqueid/main.go b/tools/uniqueid/main.go
new file mode 100644
index 0000000..ce003d0
--- /dev/null
+++ b/tools/uniqueid/main.go
@@ -0,0 +1,110 @@
+// The following enables go generate to generate the doc.go file.
+//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/lib/cmdline/testdata/gendoc.go .
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "regexp"
+
+ "v.io/core/veyron2/uniqueid"
+ "v.io/lib/cmdline"
+)
+
+func main() {
+ os.Exit(cmdUniqueId.Main())
+}
+
+var cmdUniqueId = &cmdline.Command{
+ Name: "uniqueid",
+ Short: "Generates UniqueIds.",
+ Long: `
+The uniqueid tool generates unique ids.
+It also has an option of automatically substituting unique ids with placeholders in files.
+`,
+ Children: []*cmdline.Command{cmdGenerate, cmdInject},
+ Topics: []cmdline.Topic{},
+}
+
+var cmdGenerate = &cmdline.Command{
+ Run: runGenerate,
+ Name: "generate",
+ Short: "Generates UniqueIds",
+ Long: `
+Generates unique ids and outputs them to standard out.
+`,
+ ArgsName: "",
+ ArgsLong: "",
+}
+
+var cmdInject = &cmdline.Command{
+ Run: runInject,
+ Name: "inject",
+ Short: "Injects UniqueIds into existing files",
+ Long: `
+Injects UniqueIds into existing files.
+Strings of the form "$UNIQUEID$" will be replaced with generated ids.
+`,
+ ArgsName: "<filenames>",
+ ArgsLong: "<filenames> List of files to inject unique ids into",
+}
+
+// runGenerate implements the generate command which outputs generated ids to stdout.
+func runGenerate(command *cmdline.Command, args []string) error {
+ if len(args) > 0 {
+ return command.UsageErrorf("expected 0 args, got %d", len(args))
+ }
+ id, err := uniqueid.Random()
+ if err != nil {
+ return err
+ }
+ fmt.Printf("%#v", id)
+ return nil
+}
+
+// runInject implements the inject command which replaces $UNIQUEID$ strings with generated ids.
+func runInject(command *cmdline.Command, args []string) error {
+ if len(args) == 0 {
+ return command.UsageErrorf("expected at least one file arg, got 0")
+ }
+ for _, arg := range args {
+ if err := injectIntoFile(arg); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// injectIntoFile replaces $UNIQUEID$ strings when they exist in the specified file.
+func injectIntoFile(filename string) error {
+ inbytes, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return err
+ }
+
+ // Replace $UNIQUEID$ with generated ids.
+ re, err := regexp.Compile("[$]UNIQUEID")
+ if err != nil {
+ return err
+ }
+ replaced := re.ReplaceAllFunc(inbytes, func(match []byte) []byte {
+ id, randErr := uniqueid.Random()
+ if randErr != nil {
+ err = randErr
+ }
+ return []byte(fmt.Sprintf("%#v", id))
+ })
+ if err != nil {
+ return err
+ }
+
+ // If the file with injections is different, write it to disk.
+ if !bytes.Equal(inbytes, replaced) {
+ fmt.Printf("Updated: %s\n", filename)
+ return ioutil.WriteFile(filename, replaced, 0)
+ }
+ return nil
+}