summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile42
-rw-r--r--deps.mk16
-rw-r--r--doc/uuid.en.1.adoc134
-rwxr-xr-xmkdeps.sh13
-rw-r--r--src/main.go7
-rw-r--r--src/uuid.go16
-rwxr-xr-xtests/cli-opts.sh0
-rwxr-xr-xtests/integration.sh0
9 files changed, 209 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
index 094db69..20b9ce0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/doc/*.[0-9]
/src/version.go
/*.bin
/src/*.a
diff --git a/Makefile b/Makefile
index 2ca519a..abd4ca9 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ GOLDFLAGS = -L $(GOLIBDIR)
.SUFFIXES:
-.SUFFIXES: .go .a .bin .bin-check
+.SUFFIXES: .go .a .bin .bin-check .adoc
.go.a:
go tool compile -I $(@D) $(GOCFLAGS) -o $@ -p $(*F) \
@@ -34,22 +34,27 @@ GOLDFLAGS = -L $(GOLIBDIR)
.a.bin:
go tool link -L $(@D) $(GOLDFLAGS) -o $@ --extldflags '$(LDLIBS)' $<
+.adoc:
+ asciidoctor -b manpage -o $@ $<
+
all:
include deps.mk
-libs.a = $(libs.go:.go=.a)
-mains.a = $(mains.go:.go=.a)
-mains.bin = $(mains.go:.go=.bin)
-functional/lib.a = $(functional/lib.go:.go=.a)
-fuzz/lib.a = $(fuzz/lib.go:.go=.a)
-benchmarks/lib.a = $(benchmarks/lib.go:.go=.a)
+libs.a = $(libs.go:.go=.a)
+mains.a = $(mains.go:.go=.a)
+mains.bin = $(mains.go:.go=.bin)
+functional-tests/lib.a = $(functional-tests/lib.go:.go=.a)
+fuzz-targets/lib.a = $(fuzz-targets/lib.go:.go=.a)
+benchmarks/lib.a = $(benchmarks/lib.go:.go=.a)
+manpages.N = $(manpages.N.adoc:.adoc=)
sources = \
src/$(NAME).go \
src/version.go \
+ src/main.go \
derived-assets = \
@@ -57,6 +62,8 @@ derived-assets = \
$(libs.a) \
$(mains.a) \
$(mains.bin) \
+ $(NAME).bin \
+ $(manpages.N) \
side-assets = \
tests/fuzz/corpus/ \
@@ -73,18 +80,21 @@ $(libs.a): Makefile deps.mk
$(libs.a): src/$(NAME).go src/version.go
-$(fuzz/lib.a):
+$(fuzz-targets/lib.a):
go tool compile $(GOCFLAGS) -o $@ -p $(NAME) -d=libfuzzer \
$*.go src/$(NAME).go src/version.go
src/version.go: Makefile
echo 'package $(NAME); const Version = "$(VERSION)"' > $@
+$(NAME).bin: src/main.bin
+ ln -fs src/main.bin $@
+
tests.bin-check = \
tests/main.bin-check \
- $(functional/main.go:.go=.bin-check) \
+ $(functional-tests/main.go:.go=.bin-check) \
$(tests.bin-check):
$(EXEC)$*.bin
@@ -93,6 +103,8 @@ check-unit: $(tests.bin-check)
integration-tests = \
+ tests/cli-opts.sh \
+ tests/integration.sh \
.PRECIOUS: $(integration-tests)
$(integration-tests): $(NAME).bin
@@ -111,12 +123,12 @@ check: check-unit check-integration
FUZZSEC=1
-fuzz/main.bin-check = $(fuzz/main.go:.go=.bin-check)
-$(fuzz/main.bin-check):
+fuzz-targets/main.bin-check = $(fuzz-targets/main.go:.go=.bin-check)
+$(fuzz-targets/main.bin-check):
$(EXEC)$*.bin --test.fuzztime=$(FUZZSEC)s \
--test.fuzz='.*' --test.fuzzcachedir=tests/fuzz/corpus
-fuzz: $(fuzz/main.bin-check)
+fuzz: $(fuzz-targets/main.bin-check)
@@ -140,20 +152,26 @@ clean:
## ensures that all installable artifacts are crafted beforehand.
install: all
mkdir -p \
+ '$(DESTDIR)$(BINDIR)' \
'$(DESTDIR)$(GOLIBDIR)' \
'$(DESTDIR)$(SRCDIR)' \
+ cp $(NAME).bin '$(DESTDIR)$(BINDIR)'/$(NAME)
cp src/$(NAME).a '$(DESTDIR)$(GOLIBDIR)'
cp $(sources) '$(DESTDIR)$(SRCDIR)'
+ mandir install '$(DESTDIR)$(MANDIR)' $(manpages.N)
## Uninstalls from $(DESTDIR)$(PREFIX). This is a perfect mirror
## of the "install" target, and removes *all* that was installed.
## A dedicated test asserts that this is always true.
uninstall:
rm -rf \
+ '$(DESTDIR)$(BINDIR)'/$(NAME) \
'$(DESTDIR)$(GOLIBDIR)'/$(NAME).a \
'$(DESTDIR)$(SRCDIR)' \
+ mandir uninstall '$(DESTDIR)$(MANDIR)' $(manpages.N)
+
ALWAYS:
diff --git a/deps.mk b/deps.mk
index 85a95ac..8630b53 100644
--- a/deps.mk
+++ b/deps.mk
@@ -7,23 +7,27 @@ libs.go = \
tests/uuid.go \
mains.go = \
+ src/main.go \
tests/benchmarks/string-roundtrip/main.go \
tests/functional/string-round-trip/main.go \
tests/fuzz/from-string/main.go \
tests/fuzz/new-from/main.go \
tests/main.go \
-functional/lib.go = \
+manpages.N.adoc = \
+ doc/uuid.en.1.adoc \
+
+functional-tests/lib.go = \
tests/functional/string-round-trip/uuid.go \
-functional/main.go = \
+functional-tests/main.go = \
tests/functional/string-round-trip/main.go \
-fuzz/lib.go = \
+fuzz-targets/lib.go = \
tests/fuzz/from-string/uuid.go \
tests/fuzz/new-from/uuid.go \
-fuzz/main.go = \
+fuzz-targets/main.go = \
tests/fuzz/from-string/main.go \
tests/fuzz/new-from/main.go \
@@ -33,6 +37,7 @@ benchmarks/lib.go = \
benchmarks/main.go = \
tests/benchmarks/string-roundtrip/main.go \
+src/main.a: src/main.go
src/uuid.a: src/uuid.go
tests/benchmarks/string-roundtrip/main.a: tests/benchmarks/string-roundtrip/main.go
tests/benchmarks/string-roundtrip/uuid.a: tests/benchmarks/string-roundtrip/uuid.go
@@ -44,16 +49,19 @@ tests/fuzz/new-from/main.a: tests/fuzz/new-from/main.go
tests/fuzz/new-from/uuid.a: tests/fuzz/new-from/uuid.go
tests/main.a: tests/main.go
tests/uuid.a: tests/uuid.go
+src/main.bin: src/main.a
tests/benchmarks/string-roundtrip/main.bin: tests/benchmarks/string-roundtrip/main.a
tests/functional/string-round-trip/main.bin: tests/functional/string-round-trip/main.a
tests/fuzz/from-string/main.bin: tests/fuzz/from-string/main.a
tests/fuzz/new-from/main.bin: tests/fuzz/new-from/main.a
tests/main.bin: tests/main.a
+src/main.bin-check: src/main.bin
tests/benchmarks/string-roundtrip/main.bin-check: tests/benchmarks/string-roundtrip/main.bin
tests/functional/string-round-trip/main.bin-check: tests/functional/string-round-trip/main.bin
tests/fuzz/from-string/main.bin-check: tests/fuzz/from-string/main.bin
tests/fuzz/new-from/main.bin-check: tests/fuzz/new-from/main.bin
tests/main.bin-check: tests/main.bin
+src/main.a: src/$(NAME).a
tests/benchmarks/string-roundtrip/main.a: tests/benchmarks/string-roundtrip/$(NAME).a
tests/functional/string-round-trip/main.a: tests/functional/string-round-trip/$(NAME).a
tests/fuzz/from-string/main.a: tests/fuzz/from-string/$(NAME).a
diff --git a/doc/uuid.en.1.adoc b/doc/uuid.en.1.adoc
new file mode 100644
index 0000000..6366acb
--- /dev/null
+++ b/doc/uuid.en.1.adoc
@@ -0,0 +1,134 @@
+= uuid(1)
+
+
+
+== NAME
+
+uuid - generate or validate a UUIDv4
+
+
+
+== SYNOPSYS
+
+*uuid* [_STRING_]
+
+
+
+== EXAMPLES
+
+
+=== Print a UUID on the terminal
+
+....
+$ uuid
+d3891787-c952-af17-d697-0df3b85981e1
+....
+
+
+=== Create a new UUID as part of a path
+
+....
+dir="$PWD"/"$(uuid)"/data
+....
+
+
+=== Validate a given UUID
+
+....
+ID="$(basename -- "$directory")"
+if ! uuid "$ID"; then
+ echo "Bad UUID in directory: $ID" >&2
+ exit 1
+fi
+....
+
+
+
+== DESCRIPTION
+
+The *uuid* utility generates a new UUID when no _STRING_ is given and write it
+to _stdout_. If a _STRING_ is given, *uuid* validates it and exits, and
+produces no output.
+
+
+
+== OPERANDS
+
+_STRING_:: If it is
+
+ *not given*::: generate a brand new random UUIDv4, print it to _stdout_ and exit
+ normally;
+ *given*::: test if it is a valid UUIDv4 and exit normally if so.
+
+
+
+== IO
+
+
+=== STDIN
+
+Not used.
+
+
+=== STDOUT
+
+The UUIDv4 format is made of byte blocks encoded as hexadecimals, using a
+<hyphen-minus>('`-`') as the block separator:
+
+....
+XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+....
+
+An example output is:
+
+....
+cb46d0c0-b2aa-4a6c-a119-8deace2544a2
+....
+
+
+=== STDERR
+
+Not used.
+
+
+=== INPUT FILES
+
+None.
+
+
+=== OUTPUT FILES
+
+None.
+
+
+
+== EXIT STATUS
+
+0:: Generating or validating a UUID was successfull.
+3:: UUID validation failed.
+
+
+
+== CONFORMING TO
+
+The v4 UUID defined in *RFC 9562*.
+
+
+
+== SEE ALSO
+
+
+
+== AUTHORS
+
+mailto:eu@euandre.org[EuAndreh] and contributors.
+
+
+
+== BUGS
+
+* Report bugs to the mailto:~euandreh/public-inbox@lists.sr.ht[mailing list].
+ Use the subject "[uuid] BUG or TASK: <description>".
+* Browse bugs https://euandre.org/git/uuid/TODOs.html[online].
+* https://euandre.org/git/uuid/[Homepage].
+* https://lists.sr.ht/~euandreh/public-inbox?search=%5Buuid%5D[Comments and discussions].
diff --git a/mkdeps.sh b/mkdeps.sh
index 156954c..dc685ec 100755
--- a/mkdeps.sh
+++ b/mkdeps.sh
@@ -13,13 +13,18 @@ mains() {
find src tests -name '*.go' | grep '/main\.go$'
}
+docs() {
+ find doc/*.adoc
+}
+
libs | varlist 'libs.go'
mains | varlist 'mains.go'
+docs | varlist 'manpages.N.adoc'
-find tests/functional/*/*.go -not -name main.go | varlist 'functional/lib.go'
-find tests/functional/*/main.go | varlist 'functional/main.go'
-find tests/fuzz/*/*.go -not -name main.go | varlist 'fuzz/lib.go'
-find tests/fuzz/*/main.go | varlist 'fuzz/main.go'
+find tests/functional/*/*.go -not -name main.go | varlist 'functional-tests/lib.go'
+find tests/functional/*/main.go | varlist 'functional-tests/main.go'
+find tests/fuzz/*/*.go -not -name main.go | varlist 'fuzz-targets/lib.go'
+find tests/fuzz/*/main.go | varlist 'fuzz-targets/main.go'
find tests/benchmarks/*/*.go -not -name main.go | varlist 'benchmarks/lib.go'
find tests/benchmarks/*/main.go | varlist 'benchmarks/main.go'
diff --git a/src/main.go b/src/main.go
new file mode 100644
index 0000000..d3c7f21
--- /dev/null
+++ b/src/main.go
@@ -0,0 +1,7 @@
+package main
+
+import "uuid"
+
+func main() {
+ uuid.Main()
+}
diff --git a/src/uuid.go b/src/uuid.go
index 8b953f8..6c4b8f6 100644
--- a/src/uuid.go
+++ b/src/uuid.go
@@ -4,7 +4,9 @@ import (
"crypto/rand"
"encoding/hex"
"errors"
+ "fmt"
"io"
+ "os"
"strings"
)
@@ -100,3 +102,17 @@ func FromString(str string) (UUID, error) {
return [ByteCount]byte(data), nil
}
+
+
+
+func Main() {
+ if len(os.Args) < 2 {
+ fmt.Println(New().String())
+ } else {
+ _, err := FromString(strings.TrimSpace(os.Args[1]))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(3)
+ }
+ }
+}
diff --git a/tests/cli-opts.sh b/tests/cli-opts.sh
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/tests/cli-opts.sh
diff --git a/tests/integration.sh b/tests/integration.sh
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/tests/integration.sh