refactor: rename ephemeral → wisp throughout (bd-ldb0)
Standardize terminology for ephemeral molecule storage: - .beads-ephemeral/ → .beads-wisps/ - --ephemeral flag → --wisp flag - All Ephemeral* functions → Wisp* Wisps are the "steam" in Gas Town's engine metaphor - ephemeral molecules that evaporate after squash. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -32,9 +32,9 @@ Bond types:
|
|||||||
parallel - B runs alongside A
|
parallel - B runs alongside A
|
||||||
conditional - B runs only if A fails
|
conditional - B runs only if A fails
|
||||||
|
|
||||||
Ephemeral storage (wisps):
|
Wisp storage (ephemeral molecules):
|
||||||
Use --ephemeral to create molecules in .beads-ephemeral/ instead of .beads/.
|
Use --wisp to create molecules in .beads-wisps/ instead of .beads/.
|
||||||
Ephemeral molecules (wisps) are local-only, gitignored, and not synced.
|
Wisps are local-only, gitignored, and not synced - the "steam" of Gas Town.
|
||||||
Use bd mol squash to convert a wisp to a digest in permanent storage.
|
Use bd mol squash to convert a wisp to a digest in permanent storage.
|
||||||
Use bd mol burn to delete a wisp without creating a digest.
|
Use bd mol burn to delete a wisp without creating a digest.
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ Examples:
|
|||||||
bd mol bond mol-feature mol-deploy --type parallel # Run in parallel
|
bd mol bond mol-feature mol-deploy --type parallel # Run in parallel
|
||||||
bd mol bond mol-feature bd-abc123 # Attach proto to molecule
|
bd mol bond mol-feature bd-abc123 # Attach proto to molecule
|
||||||
bd mol bond bd-abc123 bd-def456 # Join two molecules
|
bd mol bond bd-abc123 bd-def456 # Join two molecules
|
||||||
bd mol bond mol-patrol --ephemeral # Create wisp for patrol cycle`,
|
bd mol bond mol-patrol --wisp # Create wisp for patrol cycle`,
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
Run: runMolBond,
|
Run: runMolBond,
|
||||||
}
|
}
|
||||||
@@ -78,22 +78,22 @@ func runMolBond(cmd *cobra.Command, args []string) {
|
|||||||
customTitle, _ := cmd.Flags().GetString("as")
|
customTitle, _ := cmd.Flags().GetString("as")
|
||||||
dryRun, _ := cmd.Flags().GetBool("dry-run")
|
dryRun, _ := cmd.Flags().GetBool("dry-run")
|
||||||
varFlags, _ := cmd.Flags().GetStringSlice("var")
|
varFlags, _ := cmd.Flags().GetStringSlice("var")
|
||||||
ephemeral, _ := cmd.Flags().GetBool("ephemeral")
|
wisp, _ := cmd.Flags().GetBool("wisp")
|
||||||
|
|
||||||
// Determine which store to use for spawning
|
// Determine which store to use for spawning
|
||||||
targetStore := store
|
targetStore := store
|
||||||
if ephemeral {
|
if wisp {
|
||||||
// Open ephemeral storage for wisp creation
|
// Open wisp storage for ephemeral molecule creation
|
||||||
ephStore, err := beads.NewEphemeralStorage(ctx)
|
wispStore, err := beads.NewWispStorage(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error: failed to open ephemeral storage: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Error: failed to open wisp storage: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer ephStore.Close()
|
defer wispStore.Close()
|
||||||
targetStore = ephStore
|
targetStore = wispStore
|
||||||
|
|
||||||
// Ensure ephemeral directory is gitignored
|
// Ensure wisp directory is gitignored
|
||||||
if err := beads.EnsureEphemeralGitignore(); err != nil {
|
if err := beads.EnsureWispGitignore(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Warning: could not update .gitignore: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Warning: could not update .gitignore: %v\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,16 +148,16 @@ func runMolBond(cmd *cobra.Command, args []string) {
|
|||||||
fmt.Printf(" A: %s (%s)\n", issueA.Title, operandType(aIsProto))
|
fmt.Printf(" A: %s (%s)\n", issueA.Title, operandType(aIsProto))
|
||||||
fmt.Printf(" B: %s (%s)\n", issueB.Title, operandType(bIsProto))
|
fmt.Printf(" B: %s (%s)\n", issueB.Title, operandType(bIsProto))
|
||||||
fmt.Printf(" Bond type: %s\n", bondType)
|
fmt.Printf(" Bond type: %s\n", bondType)
|
||||||
if ephemeral {
|
if wisp {
|
||||||
fmt.Printf(" Storage: ephemeral (.beads-ephemeral/)\n")
|
fmt.Printf(" Storage: wisp (.beads-wisps/)\n")
|
||||||
}
|
}
|
||||||
if aIsProto && bIsProto {
|
if aIsProto && bIsProto {
|
||||||
fmt.Printf(" Result: compound proto\n")
|
fmt.Printf(" Result: compound proto\n")
|
||||||
if customTitle != "" {
|
if customTitle != "" {
|
||||||
fmt.Printf(" Custom title: %s\n", customTitle)
|
fmt.Printf(" Custom title: %s\n", customTitle)
|
||||||
}
|
}
|
||||||
if ephemeral {
|
if wisp {
|
||||||
fmt.Printf(" Note: --ephemeral ignored for proto+proto (templates stay in permanent storage)\n")
|
fmt.Printf(" Note: --wisp ignored for proto+proto (templates stay in permanent storage)\n")
|
||||||
}
|
}
|
||||||
} else if aIsProto || bIsProto {
|
} else if aIsProto || bIsProto {
|
||||||
fmt.Printf(" Result: spawn proto, attach to molecule\n")
|
fmt.Printf(" Result: spawn proto, attach to molecule\n")
|
||||||
@@ -187,8 +187,8 @@ func runMolBond(cmd *cobra.Command, args []string) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule auto-flush (only for non-ephemeral, ephemeral doesn't sync)
|
// Schedule auto-flush (only for non-wisp, wisps don't sync)
|
||||||
if !ephemeral {
|
if !wisp {
|
||||||
markDirtyAndScheduleFlush()
|
markDirtyAndScheduleFlush()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,8 +202,8 @@ func runMolBond(cmd *cobra.Command, args []string) {
|
|||||||
if result.Spawned > 0 {
|
if result.Spawned > 0 {
|
||||||
fmt.Printf(" Spawned: %d issues\n", result.Spawned)
|
fmt.Printf(" Spawned: %d issues\n", result.Spawned)
|
||||||
}
|
}
|
||||||
if ephemeral {
|
if wisp {
|
||||||
fmt.Printf(" Storage: ephemeral (wisp)\n")
|
fmt.Printf(" Storage: wisp (.beads-wisps/)\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,7 +418,7 @@ func init() {
|
|||||||
molBondCmd.Flags().String("as", "", "Custom title for compound proto (proto+proto only)")
|
molBondCmd.Flags().String("as", "", "Custom title for compound proto (proto+proto only)")
|
||||||
molBondCmd.Flags().Bool("dry-run", false, "Preview what would be created")
|
molBondCmd.Flags().Bool("dry-run", false, "Preview what would be created")
|
||||||
molBondCmd.Flags().StringSlice("var", []string{}, "Variable substitution for spawned protos (key=value)")
|
molBondCmd.Flags().StringSlice("var", []string{}, "Variable substitution for spawned protos (key=value)")
|
||||||
molBondCmd.Flags().Bool("ephemeral", false, "Create molecule in ephemeral storage (wisp)")
|
molBondCmd.Flags().Bool("wisp", false, "Create molecule in wisp storage (.beads-wisps/)")
|
||||||
|
|
||||||
molCmd.AddCommand(molBondCmd)
|
molCmd.AddCommand(molBondCmd)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -622,49 +622,50 @@ func FindAllDatabases() []DatabaseInfo {
|
|||||||
return databases
|
return databases
|
||||||
}
|
}
|
||||||
|
|
||||||
// EphemeralDirName is the default name for the ephemeral storage directory.
|
// WispDirName is the default name for the wisp storage directory.
|
||||||
// This directory is a sibling to .beads/ and should be gitignored.
|
// This directory is a sibling to .beads/ and should be gitignored.
|
||||||
const EphemeralDirName = ".beads-ephemeral"
|
// Wisps are ephemeral molecules - the "steam" in Gas Town's engine metaphor.
|
||||||
|
const WispDirName = ".beads-wisps"
|
||||||
|
|
||||||
// FindEphemeralDir locates or determines the ephemeral storage directory.
|
// FindWispDir locates or determines the wisp storage directory.
|
||||||
// The ephemeral directory is a sibling to the .beads directory.
|
// The wisp directory is a sibling to the .beads directory.
|
||||||
//
|
//
|
||||||
// Returns the path to the ephemeral directory (which may not exist yet).
|
// Returns the path to the wisp directory (which may not exist yet).
|
||||||
// Returns empty string if no .beads directory can be found.
|
// Returns empty string if no .beads directory can be found.
|
||||||
func FindEphemeralDir() string {
|
func FindWispDir() string {
|
||||||
beadsDir := FindBeadsDir()
|
beadsDir := FindBeadsDir()
|
||||||
if beadsDir == "" {
|
if beadsDir == "" {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ephemeral dir is a sibling to .beads
|
// Wisp dir is a sibling to .beads
|
||||||
// e.g., /project/.beads -> /project/.beads-ephemeral
|
// e.g., /project/.beads -> /project/.beads-wisps
|
||||||
projectRoot := filepath.Dir(beadsDir)
|
projectRoot := filepath.Dir(beadsDir)
|
||||||
return filepath.Join(projectRoot, EphemeralDirName)
|
return filepath.Join(projectRoot, WispDirName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindEphemeralDatabasePath returns the path to the ephemeral database file.
|
// FindWispDatabasePath returns the path to the wisp database file.
|
||||||
// Creates the ephemeral directory if it doesn't exist.
|
// Creates the wisp directory if it doesn't exist.
|
||||||
// Returns empty string if no .beads directory can be found.
|
// Returns empty string if no .beads directory can be found.
|
||||||
func FindEphemeralDatabasePath() (string, error) {
|
func FindWispDatabasePath() (string, error) {
|
||||||
ephemeralDir := FindEphemeralDir()
|
wispDir := FindWispDir()
|
||||||
if ephemeralDir == "" {
|
if wispDir == "" {
|
||||||
return "", fmt.Errorf("no .beads directory found")
|
return "", fmt.Errorf("no .beads directory found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create ephemeral directory if it doesn't exist
|
// Create wisp directory if it doesn't exist
|
||||||
if err := os.MkdirAll(ephemeralDir, 0755); err != nil {
|
if err := os.MkdirAll(wispDir, 0755); err != nil {
|
||||||
return "", fmt.Errorf("creating ephemeral directory: %w", err)
|
return "", fmt.Errorf("creating wisp directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return filepath.Join(ephemeralDir, CanonicalDatabaseName), nil
|
return filepath.Join(wispDir, CanonicalDatabaseName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEphemeralStorage opens the ephemeral database for wisp storage.
|
// NewWispStorage opens the wisp database for ephemeral molecule storage.
|
||||||
// Creates the database and directory if they don't exist.
|
// Creates the database and directory if they don't exist.
|
||||||
// The ephemeral database uses the same schema as the main database.
|
// The wisp database uses the same schema as the main database.
|
||||||
func NewEphemeralStorage(ctx context.Context) (Storage, error) {
|
func NewWispStorage(ctx context.Context) (Storage, error) {
|
||||||
dbPath, err := FindEphemeralDatabasePath()
|
dbPath, err := FindWispDatabasePath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -672,9 +673,9 @@ func NewEphemeralStorage(ctx context.Context) (Storage, error) {
|
|||||||
return sqlite.New(ctx, dbPath)
|
return sqlite.New(ctx, dbPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureEphemeralGitignore ensures the ephemeral directory is gitignored.
|
// EnsureWispGitignore ensures the wisp directory is gitignored.
|
||||||
// This should be called after creating the ephemeral directory.
|
// This should be called after creating the wisp directory.
|
||||||
func EnsureEphemeralGitignore() error {
|
func EnsureWispGitignore() error {
|
||||||
beadsDir := FindBeadsDir()
|
beadsDir := FindBeadsDir()
|
||||||
if beadsDir == "" {
|
if beadsDir == "" {
|
||||||
return fmt.Errorf("no .beads directory found")
|
return fmt.Errorf("no .beads directory found")
|
||||||
@@ -683,14 +684,14 @@ func EnsureEphemeralGitignore() error {
|
|||||||
projectRoot := filepath.Dir(beadsDir)
|
projectRoot := filepath.Dir(beadsDir)
|
||||||
gitignorePath := filepath.Join(projectRoot, ".gitignore")
|
gitignorePath := filepath.Join(projectRoot, ".gitignore")
|
||||||
|
|
||||||
// Check if .gitignore exists and already contains the ephemeral dir
|
// Check if .gitignore exists and already contains the wisp dir
|
||||||
content, err := os.ReadFile(gitignorePath)
|
content, err := os.ReadFile(gitignorePath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// File exists, check if already gitignored
|
// File exists, check if already gitignored
|
||||||
lines := strings.Split(string(content), "\n")
|
lines := strings.Split(string(content), "\n")
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
if line == EphemeralDirName || line == EphemeralDirName+"/" {
|
if line == WispDirName || line == WispDirName+"/" {
|
||||||
return nil // Already gitignored
|
return nil // Already gitignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -710,20 +711,20 @@ func EnsureEphemeralGitignore() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the ephemeral directory
|
// Add the wisp directory
|
||||||
if _, err := f.WriteString(EphemeralDirName + "/\n"); err != nil {
|
if _, err := f.WriteString(WispDirName + "/\n"); err != nil {
|
||||||
return fmt.Errorf("writing to .gitignore: %w", err)
|
return fmt.Errorf("writing to .gitignore: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEphemeralDatabase checks if a database path is an ephemeral database.
|
// IsWispDatabase checks if a database path is a wisp database.
|
||||||
// Returns true if the database is in a .beads-ephemeral directory.
|
// Returns true if the database is in a .beads-wisps directory.
|
||||||
func IsEphemeralDatabase(dbPath string) bool {
|
func IsWispDatabase(dbPath string) bool {
|
||||||
if dbPath == "" {
|
if dbPath == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
dir := filepath.Dir(dbPath)
|
dir := filepath.Dir(dbPath)
|
||||||
return filepath.Base(dir) == EphemeralDirName
|
return filepath.Base(dir) == WispDirName
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1255,8 +1255,8 @@ func TestFindDatabasePath_WorktreeNoLocalDB(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFindEphemeralDir tests that FindEphemeralDir returns the correct path
|
// TestFindWispDir tests that FindWispDir returns the correct path
|
||||||
func TestFindEphemeralDir(t *testing.T) {
|
func TestFindWispDir(t *testing.T) {
|
||||||
// Save original state
|
// Save original state
|
||||||
originalEnv := os.Getenv("BEADS_DIR")
|
originalEnv := os.Getenv("BEADS_DIR")
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -1268,7 +1268,7 @@ func TestFindEphemeralDir(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Create temporary directory with .beads
|
// Create temporary directory with .beads
|
||||||
tmpDir, err := os.MkdirTemp("", "beads-ephemeral-test-*")
|
tmpDir, err := os.MkdirTemp("", "beads-wisp-test-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -1286,22 +1286,22 @@ func TestFindEphemeralDir(t *testing.T) {
|
|||||||
// Set BEADS_DIR
|
// Set BEADS_DIR
|
||||||
os.Setenv("BEADS_DIR", beadsDir)
|
os.Setenv("BEADS_DIR", beadsDir)
|
||||||
|
|
||||||
// FindEphemeralDir should return sibling directory
|
// FindWispDir should return sibling directory
|
||||||
result := FindEphemeralDir()
|
result := FindWispDir()
|
||||||
expected := filepath.Join(tmpDir, EphemeralDirName)
|
expected := filepath.Join(tmpDir, WispDirName)
|
||||||
|
|
||||||
// Resolve symlinks for comparison
|
// Resolve symlinks for comparison
|
||||||
resultResolved, _ := filepath.EvalSymlinks(result)
|
resultResolved, _ := filepath.EvalSymlinks(result)
|
||||||
expectedResolved, _ := filepath.EvalSymlinks(expected)
|
expectedResolved, _ := filepath.EvalSymlinks(expected)
|
||||||
|
|
||||||
if resultResolved != expectedResolved {
|
if resultResolved != expectedResolved {
|
||||||
t.Errorf("FindEphemeralDir() = %q, want %q", result, expected)
|
t.Errorf("FindWispDir() = %q, want %q", result, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFindEphemeralDir_NoBeadsDir tests that FindEphemeralDir returns empty string
|
// TestFindWispDir_NoBeadsDir tests that FindWispDir returns empty string
|
||||||
// when no .beads directory exists
|
// when no .beads directory exists
|
||||||
func TestFindEphemeralDir_NoBeadsDir(t *testing.T) {
|
func TestFindWispDir_NoBeadsDir(t *testing.T) {
|
||||||
// Save original state
|
// Save original state
|
||||||
originalEnv := os.Getenv("BEADS_DIR")
|
originalEnv := os.Getenv("BEADS_DIR")
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -1314,7 +1314,7 @@ func TestFindEphemeralDir_NoBeadsDir(t *testing.T) {
|
|||||||
os.Unsetenv("BEADS_DIR")
|
os.Unsetenv("BEADS_DIR")
|
||||||
|
|
||||||
// Create temporary directory without .beads
|
// Create temporary directory without .beads
|
||||||
tmpDir, err := os.MkdirTemp("", "beads-no-ephemeral-test-*")
|
tmpDir, err := os.MkdirTemp("", "beads-no-wisp-test-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -1322,16 +1322,16 @@ func TestFindEphemeralDir_NoBeadsDir(t *testing.T) {
|
|||||||
|
|
||||||
t.Chdir(tmpDir)
|
t.Chdir(tmpDir)
|
||||||
|
|
||||||
// FindEphemeralDir should return empty string
|
// FindWispDir should return empty string
|
||||||
result := FindEphemeralDir()
|
result := FindWispDir()
|
||||||
if result != "" {
|
if result != "" {
|
||||||
t.Errorf("FindEphemeralDir() = %q, want empty string", result)
|
t.Errorf("FindWispDir() = %q, want empty string", result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFindEphemeralDatabasePath tests that FindEphemeralDatabasePath creates
|
// TestFindWispDatabasePath tests that FindWispDatabasePath creates
|
||||||
// the ephemeral directory and returns the correct database path
|
// the wisp directory and returns the correct database path
|
||||||
func TestFindEphemeralDatabasePath(t *testing.T) {
|
func TestFindWispDatabasePath(t *testing.T) {
|
||||||
// Save original state
|
// Save original state
|
||||||
originalEnv := os.Getenv("BEADS_DIR")
|
originalEnv := os.Getenv("BEADS_DIR")
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -1343,7 +1343,7 @@ func TestFindEphemeralDatabasePath(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Create temporary directory with .beads
|
// Create temporary directory with .beads
|
||||||
tmpDir, err := os.MkdirTemp("", "beads-ephdb-test-*")
|
tmpDir, err := os.MkdirTemp("", "beads-wispdb-test-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -1359,32 +1359,32 @@ func TestFindEphemeralDatabasePath(t *testing.T) {
|
|||||||
|
|
||||||
os.Setenv("BEADS_DIR", beadsDir)
|
os.Setenv("BEADS_DIR", beadsDir)
|
||||||
|
|
||||||
// FindEphemeralDatabasePath should create directory and return path
|
// FindWispDatabasePath should create directory and return path
|
||||||
result, err := FindEphemeralDatabasePath()
|
result, err := FindWispDatabasePath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("FindEphemeralDatabasePath() error = %v", err)
|
t.Fatalf("FindWispDatabasePath() error = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := filepath.Join(tmpDir, EphemeralDirName, CanonicalDatabaseName)
|
expected := filepath.Join(tmpDir, WispDirName, CanonicalDatabaseName)
|
||||||
|
|
||||||
// Resolve symlinks for comparison
|
// Resolve symlinks for comparison
|
||||||
resultResolved, _ := filepath.EvalSymlinks(result)
|
resultResolved, _ := filepath.EvalSymlinks(result)
|
||||||
expectedResolved, _ := filepath.EvalSymlinks(expected)
|
expectedResolved, _ := filepath.EvalSymlinks(expected)
|
||||||
|
|
||||||
if resultResolved != expectedResolved {
|
if resultResolved != expectedResolved {
|
||||||
t.Errorf("FindEphemeralDatabasePath() = %q, want %q", result, expected)
|
t.Errorf("FindWispDatabasePath() = %q, want %q", result, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the directory was created
|
// Verify the directory was created
|
||||||
ephemeralDir := filepath.Join(tmpDir, EphemeralDirName)
|
wispDir := filepath.Join(tmpDir, WispDirName)
|
||||||
if _, err := os.Stat(ephemeralDir); os.IsNotExist(err) {
|
if _, err := os.Stat(wispDir); os.IsNotExist(err) {
|
||||||
t.Errorf("Ephemeral directory was not created: %q", ephemeralDir)
|
t.Errorf("Wisp directory was not created: %q", wispDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestIsEphemeralDatabase tests that IsEphemeralDatabase correctly identifies
|
// TestIsWispDatabase tests that IsWispDatabase correctly identifies
|
||||||
// ephemeral database paths
|
// wisp database paths
|
||||||
func TestIsEphemeralDatabase(t *testing.T) {
|
func TestIsWispDatabase(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
dbPath string
|
dbPath string
|
||||||
@@ -1401,35 +1401,35 @@ func TestIsEphemeralDatabase(t *testing.T) {
|
|||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ephemeral database",
|
name: "wisp database",
|
||||||
dbPath: "/project/.beads-ephemeral/beads.db",
|
dbPath: "/project/.beads-wisps/beads.db",
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nested ephemeral",
|
name: "nested wisp",
|
||||||
dbPath: "/some/deep/path/.beads-ephemeral/beads.db",
|
dbPath: "/some/deep/path/.beads-wisps/beads.db",
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "similar but not ephemeral",
|
name: "similar but not wisp",
|
||||||
dbPath: "/project/.beads-ephemeral-backup/beads.db",
|
dbPath: "/project/.beads-wisps-backup/beads.db",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
result := IsEphemeralDatabase(tt.dbPath)
|
result := IsWispDatabase(tt.dbPath)
|
||||||
if result != tt.expected {
|
if result != tt.expected {
|
||||||
t.Errorf("IsEphemeralDatabase(%q) = %v, want %v", tt.dbPath, result, tt.expected)
|
t.Errorf("IsWispDatabase(%q) = %v, want %v", tt.dbPath, result, tt.expected)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestEnsureEphemeralGitignore tests that EnsureEphemeralGitignore correctly
|
// TestEnsureWispGitignore tests that EnsureWispGitignore correctly
|
||||||
// adds the ephemeral directory to .gitignore
|
// adds the wisp directory to .gitignore
|
||||||
func TestEnsureEphemeralGitignore(t *testing.T) {
|
func TestEnsureWispGitignore(t *testing.T) {
|
||||||
// Save original state
|
// Save original state
|
||||||
originalEnv := os.Getenv("BEADS_DIR")
|
originalEnv := os.Getenv("BEADS_DIR")
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -1452,12 +1452,12 @@ func TestEnsureEphemeralGitignore(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "already gitignored",
|
name: "already gitignored",
|
||||||
existingContent: ".beads-ephemeral/\n",
|
existingContent: ".beads-wisps/\n",
|
||||||
expectAppend: false,
|
expectAppend: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "already gitignored without slash",
|
name: "already gitignored without slash",
|
||||||
existingContent: ".beads-ephemeral\n",
|
existingContent: ".beads-wisps\n",
|
||||||
expectAppend: false,
|
expectAppend: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1499,9 +1499,9 @@ func TestEnsureEphemeralGitignore(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call EnsureEphemeralGitignore
|
// Call EnsureWispGitignore
|
||||||
if err := EnsureEphemeralGitignore(); err != nil {
|
if err := EnsureWispGitignore(); err != nil {
|
||||||
t.Fatalf("EnsureEphemeralGitignore() error = %v", err)
|
t.Fatalf("EnsureWispGitignore() error = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read result
|
// Read result
|
||||||
@@ -1510,30 +1510,30 @@ func TestEnsureEphemeralGitignore(t *testing.T) {
|
|||||||
t.Fatalf("Failed to read .gitignore: %v", err)
|
t.Fatalf("Failed to read .gitignore: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if ephemeral dir is in gitignore
|
// Check if wisp dir is in gitignore
|
||||||
hasEntry := false
|
hasEntry := false
|
||||||
lines := strings.Split(string(content), "\n")
|
lines := strings.Split(string(content), "\n")
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
if line == EphemeralDirName || line == EphemeralDirName+"/" {
|
if line == WispDirName || line == WispDirName+"/" {
|
||||||
hasEntry = true
|
hasEntry = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasEntry {
|
if !hasEntry {
|
||||||
t.Errorf("EnsureEphemeralGitignore() did not add %s to .gitignore", EphemeralDirName)
|
t.Errorf("EnsureWispGitignore() did not add %s to .gitignore", WispDirName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify idempotent: calling again should not duplicate
|
// Verify idempotent: calling again should not duplicate
|
||||||
if err := EnsureEphemeralGitignore(); err != nil {
|
if err := EnsureWispGitignore(); err != nil {
|
||||||
t.Fatalf("EnsureEphemeralGitignore() second call error = %v", err)
|
t.Fatalf("EnsureWispGitignore() second call error = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
content2, _ := os.ReadFile(gitignorePath)
|
content2, _ := os.ReadFile(gitignorePath)
|
||||||
count := strings.Count(string(content2), EphemeralDirName)
|
count := strings.Count(string(content2), WispDirName)
|
||||||
if count > 1 {
|
if count > 1 {
|
||||||
t.Errorf("EnsureEphemeralGitignore() added duplicate entry (count=%d)", count)
|
t.Errorf("EnsureWispGitignore() added duplicate entry (count=%d)", count)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user