aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-09-12 21:23:18 +0900
committerOphestra <cat@gensokyo.uk>2026-09-12 21:23:18 +0900
commitb9872f5ee0823276a04bfe9a0f2b87265bda6be2 (patch)
tree27b444a45780b309dfc09a349cb0576411935667
parent8a1e5e69622098777f12428f48be2c9e5a32f513 (diff)
cmd/app: find next unused identity
This is a lot easier than grepping around. Verbose output is equivalent to assertion in the deprecated nix code. Signed-off-by: Ophestra <cat@gensokyo.uk>
-rw-r--r--cmd/app/main.go75
1 files changed, 75 insertions, 0 deletions
diff --git a/cmd/app/main.go b/cmd/app/main.go
index 41a513d5..ff932bdd 100644
--- a/cmd/app/main.go
+++ b/cmd/app/main.go
@@ -14,7 +14,9 @@ import (
"os/exec"
"os/signal"
"path/filepath"
+ "slices"
"strconv"
+ "strings"
"syscall"
"hakurei.app/check"
@@ -229,6 +231,79 @@ func main() {
},
)
+ c.NewCommand(
+ "next", "Find next unused identity",
+ func([]string) error {
+ var names []string
+ if dents, err := os.ReadDir(base.Append("app").String()); err != nil {
+ return err
+ } else {
+ names = make([]string, 0, len(dents))
+ for _, dent := range dents {
+ name := dent.Name()
+ if dent.IsDir() || (len(name) > 0 && name[0] == '.') {
+ continue
+ }
+ names = append(names, name)
+ }
+ }
+
+ apps := make([]*hst.Config, len(names))
+ for i, name := range names {
+ r, err := os.Open(base.Append("app", name).String())
+ if err != nil {
+ return err
+ }
+
+ apps[i], err = parse(name, base, r, nil)
+ if closeErr := r.Close(); err == nil {
+ err = closeErr
+ }
+ if err != nil {
+ return err
+ }
+ }
+
+ p := make(map[int][]*hst.Config)
+ for _, config := range apps {
+ p[config.Identity] = append(p[config.Identity], config)
+ }
+
+ identities := make([]int, 0, len(p))
+ for identity, a := range p {
+ identities = append(identities, identity)
+ if msg.IsVerbose() && len(a) != 1 {
+ ids := make([]string, len(a))
+ for i, config := range a {
+ ids[i] = config.ID
+ }
+ slices.Sort(ids)
+ msg.Verbosef(
+ "%s shares identity %d",
+ strings.Join(ids, ", "), identity,
+ )
+ }
+ }
+
+ if len(identities) == 0 {
+ // 0 is the reserved identity
+ fmt.Println(1)
+ return nil
+ }
+
+ slices.Sort(identities)
+ next := identities[0] - 1
+ for _, identity := range identities {
+ if identity != next+1 {
+ break
+ }
+ next = identity
+ }
+ fmt.Println(next + 1)
+ return nil
+ },
+ )
+
c.MustParse(os.Args[1:], func(err error) {
if e, ok := errors.AsType[*exec.ExitError](err); ok && e != nil {
os.Exit(e.ExitCode())