From 2c8b842f1728acb400c611131934ffd1e9b472da Mon Sep 17 00:00:00 2001 From: wispem-wantex Date: Sun, 24 Aug 2025 14:45:57 -0700 Subject: [PATCH] Add package initialization subcommand and package --- cmd/main.go | 8 ++--- cmd/subcmd_init.go | 68 ++++++++++++++++++++++++++++++++++++++ pkg/codegen/pkg.go | 51 ++++++++++++++++++++++++++++ pkg/codegen/tpl/mount.sh | 3 ++ pkg/codegen/tpl/reset.sh | 6 ++++ pkg/codegen/tpl/schema.sql | 10 ++++++ 6 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 cmd/subcmd_init.go create mode 100644 pkg/codegen/pkg.go create mode 100644 pkg/codegen/tpl/mount.sh create mode 100644 pkg/codegen/tpl/reset.sh create mode 100644 pkg/codegen/tpl/schema.sql diff --git a/cmd/main.go b/cmd/main.go index 9119edf..d35f667 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -14,17 +14,17 @@ const ( ) func main() { - rootCmd := &cobra.Command{ + root_cmd := &cobra.Command{ Use: "gas", SilenceErrors: true, SilenceUsage: true, } - rootCmd.AddCommand(sqlite_lint) - if err := rootCmd.Execute(); err != nil { + root_cmd.AddCommand(sqlite_lint) + root_cmd.AddCommand(cmd_init) + if err := root_cmd.Execute(); err != nil { fmt.Println(RED + err.Error() + RESET) os.Exit(1) } } -// Subcommand "init" // Subcommand "generate_models" diff --git a/cmd/subcmd_init.go b/cmd/subcmd_init.go new file mode 100644 index 0000000..8966bb1 --- /dev/null +++ b/cmd/subcmd_init.go @@ -0,0 +1,68 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/spf13/cobra" + + "git.offline-twitter.com/offline-labs/gas-stack/pkg/codegen" + . "git.offline-twitter.com/offline-labs/gas-stack/pkg/flowutils" +) + +var cmd_init = &cobra.Command{ + Use: "init [path]", + Short: "Initialize a new project", + Long: "Initialize a new Gas Stack project at the given path. If no path is given, defaults to current directory.", + + Args: cobra.MaximumNArgs(1), + + Run: func(cmd *cobra.Command, args []string) { + var target string + if len(args) != 0 { + target = args[0] + PanicIf(os.MkdirAll(target, 0o755)) + PanicIf(os.Chdir(target)) + } else { + // Default to current directory (".") + target = Must(os.Getwd()) + } + + // Get all the config values + get_val := func(prompt string, val *string) { + fmt.Printf("%s (%q): ", prompt, *val) + input := "" + Must(fmt.Scanln(&input)) + if input != "" { + *val = input + } + } + pkg_opts := codegen.PkgOpts{ + ModuleName: Must(cmd.Flags().GetString("module")), + DBFilename: Must(cmd.Flags().GetString("db")), + BinaryName: Must(cmd.Flags().GetString("binary")), + } + if pkg_opts.ModuleName == "" { + pkg_opts.ModuleName = filepath.Base(target) + get_val("module name", &pkg_opts.ModuleName) + } + if pkg_opts.DBFilename == "" { + pkg_opts.DBFilename = pkg_opts.ModuleName + ".db" + get_val("db name", &pkg_opts.DBFilename) + } + if pkg_opts.BinaryName == "" { + pkg_opts.BinaryName = pkg_opts.ModuleName + get_val("binary name", &pkg_opts.BinaryName) + } + + // Run project initialization + codegen.InitPkg(pkg_opts) + }, +} + +func init() { + cmd_init.Flags().String("module", "", "Module name") + cmd_init.Flags().String("db", "", "Database filename") + cmd_init.Flags().String("binary", "", "Binary name") +} diff --git a/pkg/codegen/pkg.go b/pkg/codegen/pkg.go new file mode 100644 index 0000000..c36347b --- /dev/null +++ b/pkg/codegen/pkg.go @@ -0,0 +1,51 @@ +package codegen + +import ( + "embed" + "fmt" + "os" + "os/exec" + + . "git.offline-twitter.com/offline-labs/gas-stack/pkg/flowutils" +) + +//go:embed "tpl" +var tpl embed.FS + +type PkgOpts struct { + ModuleName string + DBFilename string + BinaryName string +} + +func InitPkg(opts PkgOpts) { + // Run `go mod init` + fmt.Printf("Running... `go mod init %s`\n", opts.ModuleName) + PanicIf(exec.Command("go", "mod", "init", opts.ModuleName).Run()) + + // Run `git init`, if required + if exec.Command("git", "status").Run() != nil { + // Not in a git repo yet; init one + fmt.Println("Running... `git init`") + PanicIf(exec.Command("git", "init").Run()) + } + + // Create package structure + PanicIf(os.MkdirAll("pkg/db", 0o755)) + PanicIf(os.MkdirAll("cmd", 0o755)) + PanicIf(os.MkdirAll("doc", 0o755)) + PanicIf(os.MkdirAll("sample_data", 0o755)) + + PanicIf(os.WriteFile("pkg/db/schema.sql", Must(tpl.ReadFile("tpl/schema.sql")), 0o664)) + + PanicIf(os.WriteFile("sample_data/mount.sh", Must(tpl.ReadFile("tpl/mount.sh")), 0o775)) + PanicIf(os.WriteFile("sample_data/reset.sh", Must(tpl.ReadFile("tpl/reset.sh")), 0o775)) + PanicIf(os.WriteFile("pkg/db/schema.sql", Must(tpl.ReadFile("tpl/schema.sql")), 0o664)) + + // TODO: + // - create `pkg/db/errors.go` + // - create `sample_data/seed.sql` + // - create `sample_data/data/` + // - create `.gitignore` + // - do something with `db_setup.go` (should go in Gas Stack `pkg/db`) +} diff --git a/pkg/codegen/tpl/mount.sh b/pkg/codegen/tpl/mount.sh new file mode 100644 index 0000000..da18a26 --- /dev/null +++ b/pkg/codegen/tpl/mount.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +sudo mount -t tmpfs -o size=100M tmpfs sample_data/data diff --git a/pkg/codegen/tpl/reset.sh b/pkg/codegen/tpl/reset.sh new file mode 100644 index 0000000..fbdead8 --- /dev/null +++ b/pkg/codegen/tpl/reset.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +rm sample_data/data/* || true + +go run ./cmd init +sqlite3 sample_data/data/{{ .DBFilename }} < sample_data/seed.sql diff --git a/pkg/codegen/tpl/schema.sql b/pkg/codegen/tpl/schema.sql new file mode 100644 index 0000000..b077c89 --- /dev/null +++ b/pkg/codegen/tpl/schema.sql @@ -0,0 +1,10 @@ +PRAGMA foreign_keys = on; + +-- ======= +-- DB meta +-- ======= + +create table db_version ( + version integer not null +) strict; +insert into db_version values(0);