feat: Brought back the docs generator.

This commit is contained in:
2026-07-27 12:39:13 -04:00
parent 222a0a3452
commit 86a4da6cba
20 changed files with 501 additions and 150 deletions
+1
View File
@@ -15,5 +15,6 @@ envr-prof
findr/findr findr/findr
findr/findr-prof findr/findr-prof
findr/bench-*.md findr/bench-*.md
gendocs
result result
version.odin version.odin
-2
View File
@@ -8,8 +8,6 @@
4. Test all command branches. 4. Test all command branches.
5. Generate md and man pages again.
6. Add tests for untested commands. 6. Add tests for untested commands.
7. Add purge command? 7. Add purge command?
+14 -16
View File
@@ -52,6 +52,7 @@ Positional_Arg :: struct {
ntype: string, // nushell type: "path", "string". "" defaults to "path" ntype: string, // nushell type: "path", "string". "" defaults to "path"
completion: string, completion: string,
optional: bool, optional: bool,
desc: string,
} }
CommandInfo :: struct { CommandInfo :: struct {
@@ -96,14 +97,14 @@ key somewhere, otherwise your data could be lost forever.`,
short = "Import a .env file into envr", short = "Import a .env file into envr",
aliases = {"add"}, aliases = {"add"},
flags = GLOBAL_FLAGS, flags = GLOBAL_FLAGS,
args = {{name = "path", completion = "untracked-paths"}}, args = {{name = "path", completion = "untracked-paths", desc = "Path to .env file to backup"}},
}, },
{ {
name = "restore", name = "restore",
usage = "envr restore <path>", usage = "envr restore <path>",
short = "Restore a .env file from the database", short = "Restore a .env file from the database",
flags = GLOBAL_FLAGS, flags = GLOBAL_FLAGS,
args = {{name = "path", completion = "tracked-paths"}}, args = {{name = "path", completion = "tracked-paths", desc = "Path to .env file to restore"}},
}, },
{ {
name = "list", name = "list",
@@ -116,14 +117,14 @@ key somewhere, otherwise your data could be lost forever.`,
usage = "envr remove <path>", usage = "envr remove <path>",
short = "Remove a .env file from your database", short = "Remove a .env file from your database",
flags = GLOBAL_FLAGS, flags = GLOBAL_FLAGS,
args = {{name = "path", completion = "tracked-paths"}}, args = {{name = "path", completion = "tracked-paths", desc = "Path to .env file to remove"}},
}, },
{ {
name = "check", name = "check",
usage = "envr check [path]", usage = "envr check [path]",
short = "Check if files are backed up", short = "Check if files are backed up",
flags = GLOBAL_FLAGS, flags = GLOBAL_FLAGS,
args = {{name = "path", optional = true}}, args = {{name = "path", optional = true, desc = "Path to check (defaults to current directory)"}},
}, },
{name = "version", usage = "envr version", short = "Show envr's version", flags = {.Help}}, {name = "version", usage = "envr version", short = "Show envr's version", flags = {.Help}},
{ {
@@ -141,7 +142,7 @@ key somewhere, otherwise your data could be lost forever.`,
nushell nushell
bash`, bash`,
flags = {.Help}, flags = {.Help},
args = {{name = "shell", ntype = "string", completion = "shells"}}, args = {{name = "shell", ntype = "string", completion = "shells", desc = "Shell to generate completions for"}},
}, },
{ {
name = "uninstall", name = "uninstall",
@@ -387,11 +388,7 @@ find_command :: proc(name: string) -> (CommandInfo, bool) {
return CommandInfo{}, false return CommandInfo{}, false
} }
// TODO: command args should be shown in usage. ENVR_DESCRIPTION :: `envr keeps your .env synced to a local, encrypted database.
write_usage :: proc(w: io.Writer) {
fmt.wprintf(
w,
`envr keeps your .env synced to a local, encrypted database.
Is a safe and easy way to gather all your .env files in one place where they can Is a safe and easy way to gather all your .env files in one place where they can
easily be backed by another tool such as restic or git. easily be backed by another tool such as restic or git.
@@ -420,13 +417,14 @@ Select the files you want to back up from the interactive list.
5. If you lose a repository, after re-cloning the repo into the same path it was 5. If you lose a repository, after re-cloning the repo into the same path it was
at before, restore your backup with: at before, restore your backup with:
> envr restore ~/<path to repository>/.env > envr restore ~/<path to repository>/.env`
%s // TODO: command args should be shown in usage.
write_usage :: proc(w: io.Writer) {
%s [command] fmt.wprintf(
w,
`, "%s\n\n%s\n\n %s [command]\n\n",
ENVR_DESCRIPTION,
colorize(.Heading, "Usage:"), colorize(.Heading, "Usage:"),
colorize(.Flag, "envr"), colorize(.Flag, "envr"),
flush = false, flush = false,
+11 -10
View File
@@ -5,7 +5,7 @@ Manage your .env files.
### Synopsis ### Synopsis
envr keeps your .env synced to a local, encrypted database. envr keeps your .env synced to a local, encrypted database.
Is a safe and eay way to gather all your .env files in one place where they can Is a safe and easy way to gather all your .env files in one place where they can
easily be backed by another tool such as restic or git. easily be backed by another tool such as restic or git.
All your data is stored in ~/.envr/data.envr All your data is stored in ~/.envr/data.envr
@@ -33,25 +33,26 @@ Select the files you want to back up from the interactive list.
5. If you lose a repository, after re-cloning the repo into the same path it was 5. If you lose a repository, after re-cloning the repo into the same path it was
at before, restore your backup with: at before, restore your backup with:
> envr restore ~/&lt;path to repository&gt;/.env > envr restore ~/<path to repository>/.env
### Options ### Options
``` ```
-h, --help help for envr -h, --help show this documentation
``` ```
### SEE ALSO ### SEE ALSO
* [envr backup](envr_backup.md) - Import a .env file into envr
* [envr check](envr_check.md) - check if files in the current directory are backed up
* [envr edit-config](envr_edit-config.md) - Edit your config with your default editor
* [envr init](envr_init.md) - Set up envr * [envr init](envr_init.md) - Set up envr
* [envr list](envr_list.md) - View your tracked files
* [envr nushell-completion](envr_nushell-completion.md) - Generate custom completions for nushell
* [envr remove](envr_remove.md) - Remove a .env file from your database
* [envr restore](envr_restore.md) - Install a .env file from the database into your file system
* [envr scan](envr_scan.md) - Find and select .env files for backup * [envr scan](envr_scan.md) - Find and select .env files for backup
* [envr sync](envr_sync.md) - Update or restore your env backups * [envr sync](envr_sync.md) - Update or restore your env backups
* [envr backup](envr_backup.md) - Import a .env file into envr
* [envr restore](envr_restore.md) - Restore a .env file from the database
* [envr list](envr_list.md) - View your tracked files
* [envr remove](envr_remove.md) - Remove a .env file from your database
* [envr check](envr_check.md) - Check if files are backed up
* [envr version](envr_version.md) - Show envr's version * [envr version](envr_version.md) - Show envr's version
* [envr edit-config](envr_edit-config.md) - Edit your config with your default editor
* [envr completion](envr_completion.md) - Generate shell completion scripts
* [envr uninstall](envr_uninstall.md) - Remove envr configuration and database
+9 -2
View File
@@ -6,13 +6,20 @@ Import a .env file into envr
envr backup <path> [flags] envr backup <path> [flags]
``` ```
**Arguments:**
* `path` — Path to .env file to backup
### Options ### Options
``` ```
-h, --help help for backup -h, --help show this documentation
-c, --config-file config file (default "~/.envr/config.json")
--color Whether or not to colorize output (default 'auto')
``` ```
*Alias: `add`*
### SEE ALSO ### SEE ALSO
* [envr](envr.md) - Manage your .env files. * [envr](envr.md) - Manage your .env files.
+8 -3
View File
@@ -1,18 +1,23 @@
## envr check ## envr check
check if files in the current directory are backed up Check if files are backed up
``` ```
envr check [path] [flags] envr check [path] [flags]
``` ```
**Arguments:**
* `path` — Path to check (defaults to current directory) (optional)
### Options ### Options
``` ```
-h, --help help for check -h, --help show this documentation
-c, --config-file config file (default "~/.envr/config.json")
--color Whether or not to colorize output (default 'auto')
``` ```
### SEE ALSO ### SEE ALSO
* [envr](envr.md) - Manage your .env files. * [envr](envr.md) - Manage your .env files.
+28
View File
@@ -0,0 +1,28 @@
## envr completion
Generate shell completion scripts
### Synopsis
Supported shells:
nushell
bash
```
envr completion <shell> [flags]
```
**Arguments:**
* `shell` — Shell to generate completions for
### Options
```
-h, --help show this documentation
```
### SEE ALSO
* [envr](envr.md) - Manage your .env files.
+3 -2
View File
@@ -9,10 +9,11 @@ envr edit-config [flags]
### Options ### Options
``` ```
-h, --help help for edit-config -h, --help show this documentation
-c, --config-file config file (default "~/.envr/config.json")
--color Whether or not to colorize output (default 'auto')
``` ```
### SEE ALSO ### SEE ALSO
* [envr](envr.md) - Manage your .env files. * [envr](envr.md) - Manage your .env files.
+5 -6
View File
@@ -5,9 +5,7 @@ Set up envr
### Synopsis ### Synopsis
The init command generates your initial config and saves it to The init command generates your initial config and saves it to
~/.envr/config in JSON format. ~/.envr/config in JSON format.\n\nDuring setup, you will be prompted to select one or more ssh keys with which to
During setup, you will be prompted to select one or more ssh keys with which to
encrypt your databse. **Make 100% sure** that you have **a remote copy** of this encrypt your databse. **Make 100% sure** that you have **a remote copy** of this
key somewhere, otherwise your data could be lost forever. key somewhere, otherwise your data could be lost forever.
@@ -18,11 +16,12 @@ envr init [flags]
### Options ### Options
``` ```
-f, --force Overwrite an existing config -h, --help show this documentation
-h, --help help for init -c, --config-file config file (default "~/.envr/config.json")
--color Whether or not to colorize output (default 'auto')
-f, --force Overwrite existing config
``` ```
### SEE ALSO ### SEE ALSO
* [envr](envr.md) - Manage your .env files. * [envr](envr.md) - Manage your .env files.
+4 -2
View File
@@ -9,10 +9,12 @@ envr list [flags]
### Options ### Options
``` ```
-h, --help help for list -h, --help show this documentation
-c, --config-file config file (default "~/.envr/config.json")
-o, --output the format of output data (default 'table')
--color Whether or not to colorize output (default 'auto')
``` ```
### SEE ALSO ### SEE ALSO
* [envr](envr.md) - Manage your .env files. * [envr](envr.md) - Manage your .env files.
-23
View File
@@ -1,23 +0,0 @@
## envr nushell-completion
Generate custom completions for nushell
### Synopsis
At time of writing, cobra does not natively support nushell,
so a custom command had to be written
```
envr nushell-completion [flags]
```
### Options
```
-h, --help help for nushell-completion
```
### SEE ALSO
* [envr](envr.md) - Manage your .env files.
+8 -3
View File
@@ -3,16 +3,21 @@
Remove a .env file from your database Remove a .env file from your database
``` ```
envr remove [flags] envr remove <path> [flags]
``` ```
**Arguments:**
* `path` — Path to .env file to remove
### Options ### Options
``` ```
-h, --help help for remove -h, --help show this documentation
-c, --config-file config file (default "~/.envr/config.json")
--color Whether or not to colorize output (default 'auto')
``` ```
### SEE ALSO ### SEE ALSO
* [envr](envr.md) - Manage your .env files. * [envr](envr.md) - Manage your .env files.
+9 -4
View File
@@ -1,18 +1,23 @@
## envr restore ## envr restore
Install a .env file from the database into your file system Restore a .env file from the database
``` ```
envr restore [flags] envr restore <path> [flags]
``` ```
**Arguments:**
* `path` — Path to .env file to restore
### Options ### Options
``` ```
-h, --help help for restore -h, --help show this documentation
-c, --config-file config file (default "~/.envr/config.json")
--color Whether or not to colorize output (default 'auto')
``` ```
### SEE ALSO ### SEE ALSO
* [envr](envr.md) - Manage your .env files. * [envr](envr.md) - Manage your .env files.
+3 -2
View File
@@ -9,10 +9,11 @@ envr scan [flags]
### Options ### Options
``` ```
-h, --help help for scan -h, --help show this documentation
-c, --config-file config file (default "~/.envr/config.json")
--color Whether or not to colorize output (default 'auto')
``` ```
### SEE ALSO ### SEE ALSO
* [envr](envr.md) - Manage your .env files. * [envr](envr.md) - Manage your .env files.
+4 -2
View File
@@ -9,10 +9,12 @@ envr sync [flags]
### Options ### Options
``` ```
-h, --help help for sync -h, --help show this documentation
-c, --config-file config file (default "~/.envr/config.json")
-o, --output the format of output data (default 'table')
--color Whether or not to colorize output (default 'auto')
``` ```
### SEE ALSO ### SEE ALSO
* [envr](envr.md) - Manage your .env files. * [envr](envr.md) - Manage your .env files.
+24
View File
@@ -0,0 +1,24 @@
## envr uninstall
Remove envr configuration and database
### Synopsis
This will remove all files generated by envr from your system.
```
envr uninstall [flags]
```
### Options
```
-h, --help show this documentation
-c, --config-file config file (default "~/.envr/config.json")
--color Whether or not to colorize output (default 'auto')
-f, --force Overwrite existing config
```
### SEE ALSO
* [envr](envr.md) - Manage your .env files.
+1 -3
View File
@@ -9,11 +9,9 @@ envr version [flags]
### Options ### Options
``` ```
-h, --help help for version -h, --help show this documentation
-l, --long Show all version information
``` ```
### SEE ALSO ### SEE ALSO
* [envr](envr.md) - Manage your .env files. * [envr](envr.md) - Manage your .env files.
+8
View File
@@ -91,6 +91,11 @@
buildPhase = '' buildPhase = ''
runHook preBuild runHook preBuild
echo '${version}' > version.txt echo '${version}' > version.txt
# Generate man pages before main build (binary gets clobbered)
odin build . -define:GENDOCS=true -out:gendocs
./gendocs --man
odin build . -o:speed -out:${pname} odin build . -o:speed -out:${pname}
runHook postBuild runHook postBuild
''; '';
@@ -98,6 +103,9 @@
installPhase = '' installPhase = ''
runHook preInstall runHook preInstall
install -Dm755 ${pname} $out/bin/${pname} install -Dm755 ${pname} $out/bin/${pname}
mkdir -p $out/share/man/man1
cp docs/man/*.1 $out/share/man/man1/
runHook postInstall runHook postInstall
''; '';
}; };
+289
View File
@@ -0,0 +1,289 @@
package main
import "core:fmt"
import "core:os"
import "core:strings"
import "core:time"
when #config(GENDOCS, false) {
main :: proc() {
args := os.args
if len(args) < 2 {
fmt.eprintln("Usage: gendocs --man | --md")
os.exit(1)
}
switch args[1] {
case "--man":
generate_man_pages()
case "--md":
generate_markdown()
case:
fmt.eprintf("Unknown format: %s\n", args[1])
os.exit(1)
}
}
}
generate_man_pages :: proc() {
os.mkdir_all("docs/man")
now := time.now()
month_year := fmt.tprintf("%s %d", time.month(now), time.year(now))
generate_man_main(month_year)
for &c in COMMANDS {
generate_man_command(&c, month_year)
}
fmt.println("Generated man pages in docs/man/")
}
generate_man_main :: proc(month_year: string) {
sb: strings.Builder
strings.builder_init(&sb, context.temp_allocator)
defer strings.builder_destroy(&sb)
fmt.sbprintf(&sb, ".TH ENVR 1 \"%s\" \"envr\" \"envr Manual\"\n", month_year)
fmt.sbprintf(&sb, ".SH NAME\nenvr \\- keep your .env files synced to an encrypted database\n")
fmt.sbprintf(&sb, ".SH SYNOPSIS\n\\fBenvr\\fR [\\fIcommand\\fR] [\\fIflags\\fR]\n")
fmt.sbprintf(
&sb,
".SH DESCRIPTION\nenvr keeps your .env synced to a local, encrypted database.\n",
)
fmt.sbprintf(
&sb,
"Is a safe and easy way to gather all your .env files in one place where they can\n",
)
fmt.sbprintf(&sb, "easily be backed by another tool such as restic or git.\n")
fmt.sbprintf(&sb, ".PP\nAll your data is stored in ~/.envr/data.envr\n")
fmt.sbprintf(&sb, ".SH COMMANDS\n")
for c in COMMANDS {
fmt.sbprintf(&sb, ".TP\n\\fB%s\\fR\n%s\n", c.name, c.short)
for a in c.aliases {
fmt.sbprintf(&sb, ".TP\n\\fB%s\\fR (alias for %s)\n%s\n", a, c.name, c.short)
}
}
fmt.sbprintf(&sb, ".SH GLOBAL OPTIONS\n")
for ft in Flag_Type {
if ft not_in GLOBAL_FLAGS do continue
write_man_flag(&sb, ft)
}
fmt.sbprintf(&sb, ".SH SEE ALSO\n")
for c, i in COMMANDS {
if i > 0 do fmt.sbprintf(&sb, ",\n")
fmt.sbprintf(&sb, ".BR envr-%s (1)", c.name)
}
fmt.sbprintf(&sb, "\n")
path := "docs/man/envr.1"
err := os.write_entire_file(path, transmute([]u8)strings.to_string(sb))
if err != nil {
fmt.eprintf("Error writing %s: %v\n", path, err)
}
}
generate_man_command :: proc(c: ^CommandInfo, month_year: string) {
sb: strings.Builder
strings.builder_init(&sb, context.temp_allocator)
defer strings.builder_destroy(&sb)
upper_name := strings.to_upper(fmt.tprintf("envr-%s", c.name))
fmt.sbprintf(&sb, ".TH %s 1 \"%s\" \"envr\" \"envr Manual\"\n", upper_name, month_year)
fmt.sbprintf(&sb, ".SH NAME\nenvr-%s \\- %s\n", c.name, c.short)
fmt.sbprintf(&sb, ".SH SYNOPSIS\n\\fB%s\\fR", c.usage)
has_positionals := false
for arg in c.args {
has_positionals = true
if arg.optional {
fmt.sbprintf(&sb, " [\\fI%s\\fR]", arg.name)
} else {
fmt.sbprintf(&sb, " \\fI%s\\fR", arg.name)
}
}
fmt.sbprintf(&sb, "\n")
if len(c.long) > 0 {
fmt.sbprintf(&sb, ".SH DESCRIPTION\n%s\n", c.long)
}
if has_positionals {
fmt.sbprintf(&sb, ".SH ARGUMENTS\n")
for arg in c.args {
fmt.sbprintf(&sb, ".TP\n\\fB%s\\fR\n%s\n", arg.name, arg.desc)
}
}
fmt.sbprintf(&sb, ".SH OPTIONS\n")
for ft in Flag_Type {
if ft not_in c.flags do continue
write_man_flag(&sb, ft)
}
path := fmt.tprintf("docs/man/envr-%s.1", c.name)
err := os.write_entire_file(path, transmute([]u8)strings.to_string(sb))
if err != nil {
fmt.eprintf("Error writing %s: %v\n", path, err)
}
}
write_man_flag :: proc(sb: ^strings.Builder, ft: Flag_Type) {
f := flag_field(ft)
fmt.sbprintf(sb, ".TP\n")
if len(f.short_name) > 0 {
fmt.sbprintf(sb, "\\fB-%s\\fR, \\fB--%s\\fR", f.short_name, f.long_name)
} else {
fmt.sbprintf(sb, "\\fB--%s\\fR", f.long_name)
}
#partial switch f.kind {
case .String:
fmt.sbprintf(sb, " \\fIvalue\\fR")
case .Enum:
values, _ := strings.replace(f.enum_values, "'", "", -1)
fmt.sbprintf(sb, " \\fI%s\\fR", values)
}
fmt.sbprintf(sb, "\n%s\n", f.usage)
if len(f.default_val) > 0 {
#partial switch f.kind {
case .String:
fmt.sbprintf(sb, "(default \"%s\")\n", f.default_val)
case .Enum:
fmt.sbprintf(sb, "(default '%s')\n", f.default_val)
}
}
}
generate_markdown :: proc() {
os.mkdir_all("docs/cli")
generate_md_main()
for &c in COMMANDS {
generate_md_command(&c)
}
fmt.println("Generated markdown in docs/cli/")
}
generate_md_main :: proc() {
sb: strings.Builder
strings.builder_init(&sb, context.temp_allocator)
defer strings.builder_destroy(&sb)
fmt.sbprintf(&sb, "## envr\n\n")
fmt.sbprintf(&sb, "Manage your .env files.\n\n")
fmt.sbprintf(&sb, "### Synopsis\n\n")
fmt.sbprint(&sb, ENVR_DESCRIPTION)
fmt.sbprintf(&sb, "\n\n### Options\n\n")
write_md_options(&sb, {.Help})
fmt.sbprintf(&sb, "\n### SEE ALSO\n\n")
for c in COMMANDS {
fmt.sbprintf(&sb, "* [envr %s](envr_%s.md)\t - %s\n", c.name, c.name, c.short)
}
fmt.sbprintf(&sb, "\n")
write_file("docs/cli/envr.md", strings.to_string(sb))
}
generate_md_command :: proc(c: ^CommandInfo) {
sb: strings.Builder
strings.builder_init(&sb, context.temp_allocator)
defer strings.builder_destroy(&sb)
fmt.sbprintf(&sb, "## envr %s\n\n", c.name)
fmt.sbprintf(&sb, "%s\n\n", c.short)
if len(c.long) > 0 {
fmt.sbprintf(&sb, "### Synopsis\n\n")
fmt.sbprint(&sb, c.long)
fmt.sbprintf(&sb, "\n\n")
}
fmt.sbprintf(&sb, "```\n%s [flags]\n```\n\n", c.usage)
if len(c.args) > 0 {
fmt.sbprintf(&sb, "**Arguments:**\n\n")
for arg in c.args {
optional := arg.optional ? " (optional)" : ""
fmt.sbprintf(&sb, "* `%s` — %s%s\n", arg.name, arg.desc, optional)
}
fmt.sbprintf(&sb, "\n")
}
fmt.sbprintf(&sb, "### Options\n\n")
write_md_options(&sb, c.flags)
for a in c.aliases {
fmt.sbprintf(&sb, "\n*Alias: `%s`*\n", a)
}
fmt.sbprintf(&sb, "\n### SEE ALSO\n\n")
fmt.sbprintf(&sb, "* [envr](envr.md)\t - Manage your .env files.\n")
path := fmt.tprintf("docs/cli/envr_%s.md", c.name)
write_file(path, strings.to_string(sb))
}
write_md_options :: proc(sb: ^strings.Builder, flags: bit_set[Flag_Type]) {
displays := make([dynamic]string, 0, 5, context.temp_allocator)
defer delete(displays)
descs := make([dynamic]string, 0, 5, context.temp_allocator)
defer delete(descs)
max_width := 0
for ft in Flag_Type {
if ft not_in flags do continue
f := flag_field(ft)
display: string
if len(f.short_name) > 0 {
display = fmt.tprintf("-%s, --%s", f.short_name, f.long_name)
} else {
display = fmt.tprintf(" --%s", f.long_name)
}
desc := f.usage
if len(f.default_val) > 0 {
#partial switch f.kind {
case .String:
desc = fmt.tprintf(`%s (default "%s")`, f.usage, f.default_val)
case .Enum:
desc = fmt.tprintf("%s (default '%s')", f.usage, f.default_val)
}
}
append(&displays, display)
append(&descs, desc)
if len(display) > max_width {
max_width = len(display)
}
}
fmt.sbprintf(sb, "```\n")
pad_buf: [64]u8
for i in 0..<len(displays) {
padding := max_width - len(displays[i]) + 3
for j in 0..<padding {
pad_buf[j] = ' '
}
fmt.sbprintf(sb, " %s%s%s\n", displays[i], string(pad_buf[:padding]), descs[i])
}
fmt.sbprintf(sb, "```\n")
}
write_file :: proc(path: string, content: string) {
err := os.write_entire_file(path, transmute([]u8)content)
if err != nil {
fmt.eprintf("Error writing %s: %v\n", path, err)
}
}
+72 -70
View File
@@ -14,79 +14,81 @@ when SPALL {
spall_buffer: spall.Buffer spall_buffer: spall.Buffer
} }
main :: proc() { when !#config(GENDOCS, false) {
when SPALL { main :: proc() {
ctx, spall_ok := spall.context_create_with_scale("envr.spall", false, 1.0) when SPALL {
if !spall_ok { ctx, spall_ok := spall.context_create_with_scale("envr.spall", false, 1.0)
fmt.eprintln("Failed to create spall trace file") if !spall_ok {
fmt.eprintln("Failed to create spall trace file")
os.exit(1)
}
spall_ctx = ctx
defer spall.context_destroy(&spall_ctx)
spall_backing := make([]u8, spall.BUFFER_DEFAULT_SIZE)
defer delete(spall_backing)
spall_buffer = spall.buffer_create(spall_backing, u32(sync.current_thread_id()))
defer spall.buffer_destroy(&spall_ctx, &spall_buffer)
}
when ODIN_DEBUG {
heap_track: mem.Tracking_Allocator
mem.tracking_allocator_init(&heap_track, context.allocator)
defer mem.tracking_allocator_destroy(&heap_track)
defer if len(heap_track.allocation_map) > 0 {
for _, leak in heap_track.allocation_map {
fmt.eprintf("LEAK: %v leaked %m\n", leak.location, leak.size)
}
}
context.allocator = mem.tracking_allocator(&heap_track)
temp_track: mem.Tracking_Allocator
mem.tracking_allocator_init(&temp_track, context.temp_allocator)
defer mem.tracking_allocator_destroy(&temp_track)
context.temp_allocator = mem.tracking_allocator(&temp_track)
}
defer free_all(context.temp_allocator)
cmd, ok := parse_args(os.args, os.to_writer(os.stdout), os.to_writer(os.stderr))
defer delete_command(&cmd) // delete flushes automatically
if !ok {
return
}
switch cmd.name {
case "init":
cmd_init(&cmd)
case "version":
cmd_version(&cmd)
case "list":
cmd_list(&cmd)
case "backup", "add":
cmd_backup(&cmd)
case "remove":
cmd_remove(&cmd)
case "restore":
cmd_restore(&cmd)
case "edit-config":
cmd_edit_config(&cmd)
case "check":
cmd_check(&cmd)
case "scan":
cmd_scan(&cmd)
case "sync":
cmd_sync(&cmd)
case "completion":
cmd_completion(&cmd)
case "uninstall":
cmd_uninstall(&cmd)
case:
fmt.wprintf(cmd.err, "Unknown command: %s\n", cmd.name)
write_usage(cmd.out)
os.exit(1) os.exit(1)
} }
spall_ctx = ctx
defer spall.context_destroy(&spall_ctx)
spall_backing := make([]u8, spall.BUFFER_DEFAULT_SIZE)
defer delete(spall_backing)
spall_buffer = spall.buffer_create(spall_backing, u32(sync.current_thread_id()))
defer spall.buffer_destroy(&spall_ctx, &spall_buffer)
} }
} // !GENDOCS
when ODIN_DEBUG {
heap_track: mem.Tracking_Allocator
mem.tracking_allocator_init(&heap_track, context.allocator)
defer mem.tracking_allocator_destroy(&heap_track)
defer if len(heap_track.allocation_map) > 0 {
for _, leak in heap_track.allocation_map {
fmt.eprintf("LEAK: %v leaked %m\n", leak.location, leak.size)
}
}
context.allocator = mem.tracking_allocator(&heap_track)
temp_track: mem.Tracking_Allocator
mem.tracking_allocator_init(&temp_track, context.temp_allocator)
defer mem.tracking_allocator_destroy(&temp_track)
context.temp_allocator = mem.tracking_allocator(&temp_track)
}
defer free_all(context.temp_allocator)
cmd, ok := parse_args(os.args, os.to_writer(os.stdout), os.to_writer(os.stderr))
defer delete_command(&cmd) // delete flushes automatically
if !ok {
return
}
switch cmd.name {
case "init":
cmd_init(&cmd)
case "version":
cmd_version(&cmd)
case "list":
cmd_list(&cmd)
case "backup", "add":
cmd_backup(&cmd)
case "remove":
cmd_remove(&cmd)
case "restore":
cmd_restore(&cmd)
case "edit-config":
cmd_edit_config(&cmd)
case "check":
cmd_check(&cmd)
case "scan":
cmd_scan(&cmd)
case "sync":
cmd_sync(&cmd)
case "completion":
cmd_completion(&cmd)
case "uninstall":
cmd_uninstall(&cmd)
case:
fmt.wprintf(cmd.err, "Unknown command: %s\n", cmd.name)
write_usage(cmd.out)
os.exit(1)
}
}
when SPALL { when SPALL {
@(instrumentation_enter) @(instrumentation_enter)