Skip to content

Commit b44c431

Browse files
authored
Adapted CLI Command (#1)
### Scope of changes Updates the CLI command with additional flags and functionality. ### Type of change - [x] new feature - [ ] bug fix - [ ] documentation - [ ] testing - [ ] technical debt - [ ] other (describe) ### Author checklist - [x] I have manually tested the change and/or added automation in the form of unit tests or integration tests - [ ] I have added new test fixtures as needed to support added tests
1 parent aff43d9 commit b44c431

File tree

2 files changed

+118
-42
lines changed

2 files changed

+118
-42
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/go.rtnl.ai/ulid)
77
[![Apache 2 licensed](https://img.shields.io/badge/license-Apache2-blue.svg)](https://raw.githubusercontent.com/oklog/ulid/master/LICENSE)
88

9-
This go module is a derivative work of [github.com/oklog/ulid](https://github.com/oklog/ulid), created under the terms of the [Apache 2](LICENSE). We created this port of the original package because we found ourselves wrapping the package with helper functionality that didn't seem useful to anyone but us. This package is intended for a Rotational audience; if you need ULIDs we do recommend that you use the original package.
9+
This go module is a derivative work of [github.com/oklog/ulid](https://github.com/oklog/ulid), created under the terms of the [Apache 2](LICENSE) license. We created this port of the original package because we found ourselves wrapping the package with helper functionality that didn't seem useful to anyone but us. This package is intended for a Rotational audience; if you need ULIDs we do recommend that you use the original package.
1010

1111
## Install
1212

cmd/ulid/main.go

+117-41
Original file line numberDiff line numberDiff line change
@@ -6,56 +6,104 @@ import (
66
"fmt"
77
mathrand "math/rand"
88
"os"
9+
"path/filepath"
910
"strings"
1011
"time"
1112

1213
"go.rtnl.ai/ulid"
1314
)
1415

16+
const usageText = `Rotational ULID debugging utility
17+
Usage: generate or inspect a ULID
18+
19+
Generate:
20+
21+
ulid [options]
22+
23+
-n INT, --num INT number of ULIDs to generate
24+
-q, --quick use quick entropy (not cryptographic)
25+
-m, --mono use monotonic entropy (for more than one ULID)
26+
-z, --zero use zero entropy
27+
28+
Inspect:
29+
30+
ulid [options] ULID [ULID ...]
31+
32+
-f, --format string time format (default, rfc3339, unix, ms)
33+
-l, --local use local time instead of UTC
34+
-p, --path assumes argument is a path with a ULID filename (strips directory and extension)
35+
36+
Options:
37+
38+
-h, --help display this help and exit
39+
`
40+
1541
const (
1642
defaultms = "Mon Jan 02 15:04:05.999 MST 2006"
1743
rfc3339ms = "2006-01-02T15:04:05.000Z07:00"
1844
)
1945

46+
var (
47+
num int
48+
quick bool
49+
mono bool
50+
zero bool
51+
format string
52+
local bool
53+
path bool
54+
help bool
55+
)
56+
2057
func main() {
21-
var (
22-
format = flag.String("format", "default", "when parsing, show times in this format: default, rfc3339, unix, ms")
23-
local = flag.Bool("local", false, "when parsing, show local time instead of UTC")
24-
quick = flag.Bool("quick", false, "when generating, use non-crypto-grade entropy")
25-
zero = flag.Bool("zero", false, "when generating, fix entropy to all-zeroes")
26-
help = flag.Bool("help", false, "print this help text")
27-
)
58+
// Set command line flags
59+
// Generate Options
60+
flag.IntVar(&num, "num", 1, "")
61+
flag.IntVar(&num, "n", 1, "")
62+
flag.BoolVar(&quick, "quick", false, "")
63+
flag.BoolVar(&quick, "q", false, "")
64+
flag.BoolVar(&mono, "mono", false, "")
65+
flag.BoolVar(&mono, "m", false, "")
66+
flag.BoolVar(&zero, "zero", false, "")
67+
flag.BoolVar(&zero, "z", false, "")
68+
69+
// Inspect Options
70+
flag.StringVar(&format, "format", "default", "")
71+
flag.StringVar(&format, "f", "default", "")
72+
flag.BoolVar(&local, "local", false, "")
73+
flag.BoolVar(&local, "l", false, "")
74+
flag.BoolVar(&path, "path", false, "")
75+
flag.BoolVar(&path, "p", false, "")
2876

77+
// General Options
78+
flag.BoolVar(&help, "help", false, "")
79+
flag.BoolVar(&help, "h", false, "")
80+
81+
// Parse command line flags
2982
flag.Parse()
30-
if *help {
31-
flag.Usage()
83+
if help {
84+
usage()
3285
os.Exit(0)
3386
}
3487

35-
var formatFunc func(time.Time) string
36-
switch strings.ToLower(*format) {
37-
case "default":
38-
formatFunc = func(t time.Time) string { return t.Format(defaultms) }
39-
case "rfc3339":
40-
formatFunc = func(t time.Time) string { return t.Format(rfc3339ms) }
41-
case "unix":
42-
formatFunc = func(t time.Time) string { return fmt.Sprint(t.Unix()) }
43-
case "ms":
44-
formatFunc = func(t time.Time) string { return fmt.Sprint(t.UnixNano() / 1e6) }
45-
default:
46-
fmt.Fprintf(os.Stderr, "invalid --format %s\n", *format)
47-
os.Exit(1)
48-
}
49-
5088
switch flag.NArg() {
5189
case 0:
52-
generate(*quick, *zero)
90+
generate()
5391
default:
54-
parse(flag.Arg(0), *local, formatFunc)
92+
parse()
5593
}
5694
}
5795

58-
func generate(quick, zero bool) {
96+
func usage() {
97+
fmt.Fprint(os.Stderr, usageText)
98+
}
99+
100+
func generate() {
101+
if num < 1 {
102+
fmt.Fprintf(os.Stderr, "invalid --num %d\n", num)
103+
os.Exit(1)
104+
}
105+
106+
// Create entropy from options
59107
entropy := cryptorand.Reader
60108
if quick {
61109
seed := time.Now().UnixNano()
@@ -65,28 +113,56 @@ func generate(quick, zero bool) {
65113
if zero {
66114
entropy = zeroReader{}
67115
}
68-
69-
id, err := ulid.New(ulid.Timestamp(time.Now()), entropy)
70-
if err != nil {
71-
fmt.Fprintf(os.Stderr, "%v\n", err)
72-
os.Exit(1)
116+
if mono {
117+
entropy = ulid.Monotonic(entropy, 0)
73118
}
74119

75-
fmt.Fprintf(os.Stdout, "%s\n", id)
120+
// Generate ULIDs
121+
for i := 0; i < num; i++ {
122+
id, err := ulid.New(ulid.Timestamp(time.Now()), entropy)
123+
if err != nil {
124+
fmt.Fprintf(os.Stderr, "%v\n", err)
125+
os.Exit(1)
126+
}
127+
128+
fmt.Fprintf(os.Stdout, "%s\n", id)
129+
}
76130
}
77131

78-
func parse(s string, local bool, f func(time.Time) string) {
79-
id, err := ulid.Parse(s)
80-
if err != nil {
81-
fmt.Fprintf(os.Stderr, "%v\n", err)
132+
func parse() {
133+
var formatFunc func(time.Time) string
134+
switch strings.ToLower(format) {
135+
case "default":
136+
formatFunc = func(t time.Time) string { return t.Format(defaultms) }
137+
case "rfc3339":
138+
formatFunc = func(t time.Time) string { return t.Format(rfc3339ms) }
139+
case "unix":
140+
formatFunc = func(t time.Time) string { return fmt.Sprint(t.Unix()) }
141+
case "ms":
142+
formatFunc = func(t time.Time) string { return fmt.Sprint(t.UnixNano() / 1e6) }
143+
default:
144+
fmt.Fprintf(os.Stderr, "invalid --format %s\n", format)
82145
os.Exit(1)
83146
}
84147

85-
t := ulid.Time(id.Time())
86-
if !local {
87-
t = t.UTC()
148+
for _, s := range flag.Args() {
149+
if path {
150+
s = filepath.Base(s)
151+
s = strings.TrimSuffix(s, filepath.Ext(s))
152+
}
153+
154+
id, err := ulid.Parse(s)
155+
if err != nil {
156+
fmt.Fprintf(os.Stderr, "%v\n", err)
157+
os.Exit(1)
158+
}
159+
160+
t := ulid.Time(id.Time())
161+
if !local {
162+
t = t.UTC()
163+
}
164+
fmt.Fprintf(os.Stderr, "%s\n", formatFunc(t))
88165
}
89-
fmt.Fprintf(os.Stderr, "%s\n", f(t))
90166
}
91167

92168
type zeroReader struct{}

0 commit comments

Comments
 (0)