step 2: init command + SQLite storage + migrations + config

- storage.go: DB wrapper, migration runner (in-code SQL strings)
- migrations.go: 001_init (nodes + node_meta + indexes)
- vault.go: Init() creates .verstak/ dirs, config.yml, index.db
- config.go: YAML config read/write
- util/uuid.go: UUIDv7 generator
- cmd/verstak/main.go: init --vault PATH command
- main_test.go: TestInitCreatesVault, TestInitConfigYAML

Acceptance: go build ./... pass, go test ./... pass
Init creates test-vault with .verstak/index.db + config.yml
Repeat Init is safe.
This commit is contained in:
2026-05-30 18:58:47 +08:00
parent 982f3064ac
commit b8d8427c46
11 changed files with 474 additions and 10 deletions
+65
View File
@@ -0,0 +1,65 @@
package vault
import (
"fmt"
"os"
"path/filepath"
"verstak/internal/core/config"
"verstak/internal/core/storage"
"verstak/internal/core/util"
)
const currentVaultVersion = 1
// Init creates a vault directory structure at vaultRoot.
// Calling Init on an already-initialized vault is safe.
func Init(vaultRoot string) error {
vaultRoot = filepath.Clean(vaultRoot)
dirs := []string{
filepath.Join(vaultRoot, ".verstak"),
filepath.Join(vaultRoot, ".verstak", "trash"),
filepath.Join(vaultRoot, ".verstak", "history"),
filepath.Join(vaultRoot, ".verstak", "originals"),
filepath.Join(vaultRoot, ".verstak", "thumbnails"),
filepath.Join(vaultRoot, ".verstak", "blobs"),
filepath.Join(vaultRoot, "spaces"),
}
for _, d := range dirs {
if err := os.MkdirAll(d, 0o750); err != nil {
return fmt.Errorf("create %s: %w", d, err)
}
}
cfgPath := filepath.Join(vaultRoot, ".verstak", "config.yml")
if _, err := os.Stat(cfgPath); os.IsNotExist(err) {
cfg := &config.Config{
Engine: config.EngineConfig{
Version: currentVaultVersion,
VaultID: util.UUID7(),
},
Sync: config.SyncConfig{
AutoSync: false,
},
Browser: config.BrowserConfig{
Enabled: false,
LocalPort: 47731,
},
}
if err := config.Save(vaultRoot, cfg); err != nil {
return fmt.Errorf("write config: %w", err)
}
}
dbPath := filepath.Join(vaultRoot, ".verstak", "index.db")
if _, err := os.Stat(dbPath); os.IsNotExist(err) {
db, err := storage.Open(dbPath)
if err != nil {
return fmt.Errorf("create db: %w", err)
}
db.Close()
}
return nil
}