refactor: Fixed a number of memory leaks.

This commit is contained in:
2026-06-12 11:05:34 -04:00
parent 22a517340a
commit 1068458f32
9 changed files with 317 additions and 295 deletions

View File

@@ -1,6 +1,9 @@
package main
import "core:bufio"
import "core:fmt"
import "core:io"
import "core:mem"
import "core:os"
import "core:strings"
@@ -19,10 +22,14 @@ CommandInfo :: struct {
aliases: []string,
}
COMMANDS := []CommandInfo{
{"init", "envr init", "Set up envr",
COMMANDS := []CommandInfo {
{
"init",
"envr init",
"Set up envr",
"The init command generates your initial config and saves it to\n~/.envr/config in JSON format.\n\nDuring setup, you will be prompted to select one or more ssh keys with which to\nencrypt your databse. **Make 100% sure** that you have **a remote copy** of this\nkey somewhere, otherwise your data could be lost forever.",
{}},
{},
},
{"scan", "envr scan", "Find and select .env files for backup", "", {}},
{"sync", "envr sync", "Update or restore your env backups", "", {}},
{"backup", "envr backup <path>", "Import a .env file into envr", "", {"add"}},
@@ -30,9 +37,13 @@ COMMANDS := []CommandInfo{
{"list", "envr list", "View your tracked files", "", {}},
{"remove", "envr remove <path>", "Remove a .env file from your database", "", {}},
{"check", "envr check [path]", "Check if files are backed up", "", {}},
{"deps", "envr deps", "Check for missing binaries",
{
"deps",
"envr deps",
"Check for missing binaries",
"envr relies on external binaries for certain functionality.\n\nThe check command reports on which binaries are available and which are not.",
{}},
{},
},
{"version", "envr version", "Show envr's version", "", {}},
{"edit-config", "envr edit-config", "Edit your config with your default editor", "", {}},
}
@@ -60,8 +71,8 @@ parse_args :: proc() -> (cmd: Command, ok: bool) {
arg := args[i]
if strings.starts_with(arg, "--") {
key := arg[2:]
if i+1 < len(args) && !strings.starts_with(args[i+1], "-") {
cmd.flags[key] = args[i+1]
if i + 1 < len(args) && !strings.starts_with(args[i + 1], "-") {
cmd.flags[key] = args[i + 1]
i += 2
} else {
cmd.bool_set[key] = true
@@ -69,8 +80,8 @@ parse_args :: proc() -> (cmd: Command, ok: bool) {
}
} else if strings.starts_with(arg, "-") && len(arg) == 2 {
key_slice := arg[1:2]
if i+1 < len(args) && !strings.starts_with(args[i+1], "-") {
cmd.flags[key_slice] = args[i+1]
if i + 1 < len(args) && !strings.starts_with(args[i + 1], "-") {
cmd.flags[key_slice] = args[i + 1]
i += 2
} else {
cmd.bool_set[key_slice] = true
@@ -113,45 +124,43 @@ find_command :: proc(name: string) -> (CommandInfo, bool) {
return CommandInfo{}, false
}
command_help_text :: proc(name: string) -> (string, bool) {
write_command_help :: proc(name: string, w: io.Writer) -> bool {
info, found := find_command(name)
if !found {
return "", false
return false
}
b: strings.Builder
strings.builder_init(&b)
fmt.sbprintf(&b, "Usage: %s [flags]\n\n", info.usage)
fmt.sbprintf(&b, "%s\n", info.short)
fmt.wprintf(w, "Usage: %s [flags]\n\n", info.usage, flush = false)
fmt.wprintf(w, "%s\n", info.short, flush = false)
if len(info.aliases) > 0 {
fmt.sbprintf(&b, "\nAliases:\n %s", info.name)
fmt.wprintf(w, "\nAliases:\n %s", info.name, flush = false)
for a in info.aliases {
fmt.sbprintf(&b, ", %s", a)
fmt.wprintf(w, ", %s", a, flush = false)
}
fmt.sbprintf(&b, "\n")
fmt.wprintf(w, "\n", flush = false)
}
if len(info.long) > 0 {
fmt.sbprintf(&b, "\n%s\n", info.long)
fmt.wprintf(w, "\n%s\n", info.long, flush = false)
}
fmt.sbprintf(&b, "\nFlags:\n -h, --help help for %s\n", info.name)
s := strings.clone(strings.to_string(b))
strings.builder_destroy(&b)
return s, true
fmt.wprintf(w, "\nFlags:\n -h, --help help for %s\n", info.name, flush = false)
return true
}
print_command_help :: proc(name: string) {
text, ok := command_help_text(name)
bw: bufio.Writer
bufio.writer_init(&bw, io.to_writer(os.to_writer(os.stdout)), mem.DEFAULT_PAGE_SIZE)
defer bufio.writer_destroy(&bw)
w := bufio.writer_to_writer(&bw)
ok := write_command_help(name, w)
if !ok {
fmt.printf("Unknown command: %s\n", name)
print_usage()
return
}
fmt.println(text)
bufio.writer_flush(&bw)
}
usage_text :: proc() -> string {
@@ -159,7 +168,10 @@ usage_text :: proc() -> string {
strings.builder_init(&b)
fmt.sbprintf(&b, "envr keeps your .env synced to a local, age encrypted database.\n")
fmt.sbprintf(&b, "Is a safe and easy way to gather all your .env files in one place where they can\n")
fmt.sbprintf(
&b,
"Is a safe and easy way to gather all your .env files in one place where they can\n",
)
fmt.sbprintf(&b, "easily be backed by another tool such as restic or git.\n")
fmt.sbprintf(&b, "\n")
fmt.sbprintf(&b, "All your data is stored in ~/data.age\n")
@@ -184,7 +196,10 @@ usage_text :: proc() -> string {
fmt.sbprintf(&b, "\n")
fmt.sbprintf(&b, "> envr sync\n")
fmt.sbprintf(&b, "\n")
fmt.sbprintf(&b, "5. If you lose a repository, after re-cloning the repo into the same path it was\n")
fmt.sbprintf(
&b,
"5. If you lose a repository, after re-cloning the repo into the same path it was\n",
)
fmt.sbprintf(&b, "at before, restore your backup with:\n")
fmt.sbprintf(&b, "\n")
fmt.sbprintf(&b, "> envr restore ~/<path to repository>/.env\n")
@@ -203,7 +218,7 @@ usage_text :: proc() -> string {
name_len := len(b.buf) - name_start
padding := 20 - name_len
if padding > 0 {
for _ in 0..<padding {
for _ in 0 ..< padding {
strings.write_byte(&b, ' ')
}
}
@@ -224,3 +239,4 @@ usage_text :: proc() -> string {
print_usage :: proc() {
fmt.print(usage_text())
}