@@ -40,6 +40,7 @@ func snapshotBootstrapEnv(t *testing.T) func() {
4040
4141func TestDetectBootstrapAction_NoneWhenDatabaseExists (t * testing.T ) {
4242 t .Setenv ("BEADS_DOLT_DATA_DIR" , "" )
43+ t .Setenv ("BEADS_DOLT_SHARED_SERVER" , "" )
4344 t .Setenv ("BEADS_DOLT_SERVER_DATABASE" , "" )
4445 t .Setenv ("BEADS_DOLT_SERVER_HOST" , "" )
4546 t .Setenv ("BEADS_DOLT_SERVER_PORT" , "" )
@@ -214,6 +215,7 @@ func TestDetectBootstrapAction_ServerModeMissingConfiguredDBDoesNotReturnNone(t
214215
215216func TestDetectBootstrapAction_ServerModeProbeErrorStopsWithReason (t * testing.T ) {
216217 t .Setenv ("BEADS_DOLT_DATA_DIR" , "" )
218+ t .Setenv ("BEADS_DOLT_SHARED_SERVER" , "" )
217219 t .Setenv ("BEADS_DOLT_SERVER_DATABASE" , "" )
218220 t .Setenv ("BEADS_DOLT_SERVER_HOST" , "" )
219221 t .Setenv ("BEADS_DOLT_SERVER_PORT" , "" )
@@ -971,6 +973,143 @@ func TestDetectBootstrapAction_SharedServerEnvUsesSharedPath(t *testing.T) {
971973 }
972974}
973975
976+ // TestDetectBootstrapAction_WorktreeSynthesizedDirPrefersSyncOverDefaultSharedDB
977+ // verifies that when bootstrap is running from a worktree whose fallback
978+ // .beads path lives under a bare/common git directory, remote recovery via
979+ // refs/dolt/data wins over an unrelated default "beads" database already
980+ // present on the shared server.
981+ func TestDetectBootstrapAction_WorktreeSynthesizedDirPrefersSyncOverDefaultSharedDB (t * testing.T ) {
982+ t .Setenv ("BEADS_DOLT_DATA_DIR" , "" )
983+ t .Setenv ("BEADS_DOLT_SERVER_DATABASE" , "" )
984+ t .Setenv ("BEADS_DOLT_SERVER_HOST" , "" )
985+ t .Setenv ("BEADS_DOLT_SERVER_PORT" , "" )
986+ t .Setenv ("BEADS_DOLT_SERVER_MODE" , "" )
987+ t .Setenv ("BEADS_DOLT_SHARED_SERVER" , "1" )
988+
989+ homeDir := t .TempDir ()
990+ t .Setenv ("HOME" , homeDir )
991+
992+ originBare := filepath .Join (t .TempDir (), "origin.git" )
993+ runGitForBootstrapTest (t , "" , "init" , "--bare" , "--initial-branch=main" , originBare )
994+
995+ sourceDir := t .TempDir ()
996+ runGitForBootstrapTest (t , sourceDir , "init" , "-b" , "main" )
997+ runGitForBootstrapTest (t , sourceDir , "config" , "user.email" , "test@test.com" )
998+ runGitForBootstrapTest (t , sourceDir , "config" , "user.name" , "Test User" )
999+ runGitForBootstrapTest (t , sourceDir , "commit" , "--allow-empty" , "-m" , "init" )
1000+ runGitForBootstrapTest (t , sourceDir , "remote" , "add" , "origin" , originBare )
1001+ runGitForBootstrapTest (t , sourceDir , "push" , "origin" , "main" )
1002+ runGitForBootstrapTest (t , sourceDir , "push" , "origin" , "HEAD:refs/dolt/data" )
1003+
1004+ localBare := filepath .Join (t .TempDir (), "local-bare.git" )
1005+ runGitForBootstrapTest (t , "" , "clone" , "--bare" , originBare , localBare )
1006+
1007+ worktreeDir := filepath .Join (t .TempDir (), "worktree" )
1008+ runGitForBootstrapTest (t , "" , "--git-dir=" + localBare , "worktree" , "add" , worktreeDir , "main" )
1009+
1010+ sharedDoltDir := filepath .Join (homeDir , ".beads" , "shared-server" , "dolt" )
1011+ if err := os .MkdirAll (filepath .Join (sharedDoltDir , "beads" ), 0o750 ); err != nil {
1012+ t .Fatal (err )
1013+ }
1014+
1015+ oldWd , err := os .Getwd ()
1016+ if err != nil {
1017+ t .Fatal (err )
1018+ }
1019+ defer func () { _ = os .Chdir (oldWd ) }()
1020+ if err := os .Chdir (worktreeDir ); err != nil {
1021+ t .Fatal (err )
1022+ }
1023+
1024+ synthesizedDir := filepath .Join (localBare , ".beads" )
1025+ cfg , cfgErr := configfile .Load (synthesizedDir )
1026+ if cfgErr != nil || cfg == nil {
1027+ cfg = findParentConfig (synthesizedDir )
1028+ }
1029+ if cfg == nil {
1030+ cfg = configfile .DefaultConfig ()
1031+ }
1032+
1033+ if got := cfg .GetDoltDatabase (); got != "beads" {
1034+ t .Fatalf ("GetDoltDatabase() = %q, want %q (default expected without local metadata)" , got , "beads" )
1035+ }
1036+
1037+ origCheck := checkBootstrapServerDB
1038+ checkBootstrapServerDB = func (probeCfg bootstrapServerProbeConfig ) bootstrapServerDBCheck {
1039+ if probeCfg .database != "beads" {
1040+ t .Fatalf ("probeCfg.database = %q, want %q" , probeCfg .database , "beads" )
1041+ }
1042+ return bootstrapServerDBCheck {Exists : true , Reachable : true }
1043+ }
1044+ defer func () { checkBootstrapServerDB = origCheck }()
1045+
1046+ plan := detectBootstrapAction (synthesizedDir , cfg )
1047+
1048+ if plan .Action != "sync" {
1049+ t .Fatalf ("expected action=%q, got %q: %s" , "sync" , plan .Action , plan .Reason )
1050+ }
1051+ if plan .SyncRemote == "" {
1052+ t .Fatal ("expected SyncRemote to be populated from origin refs/dolt/data detection" )
1053+ }
1054+ if plan .Database != "beads" {
1055+ t .Errorf ("plan.Database = %q, want %q (default metadata-free value should still recover via sync)" , plan .Database , "beads" )
1056+ }
1057+ }
1058+
1059+ func TestDetectBootstrapAction_SynthesizedDirWithoutRecoveryStillUsesExistingSharedDB (t * testing.T ) {
1060+ t .Setenv ("BEADS_DOLT_DATA_DIR" , "" )
1061+ t .Setenv ("BEADS_DOLT_SERVER_DATABASE" , "" )
1062+ t .Setenv ("BEADS_DOLT_SERVER_HOST" , "" )
1063+ t .Setenv ("BEADS_DOLT_SERVER_PORT" , "" )
1064+ t .Setenv ("BEADS_DOLT_SERVER_MODE" , "" )
1065+ t .Setenv ("BEADS_DOLT_SHARED_SERVER" , "1" )
1066+
1067+ homeDir := t .TempDir ()
1068+ t .Setenv ("HOME" , homeDir )
1069+
1070+ worktreeDir := filepath .Join (t .TempDir (), "worktree" )
1071+ if err := os .MkdirAll (worktreeDir , 0o750 ); err != nil {
1072+ t .Fatal (err )
1073+ }
1074+
1075+ oldWd , err := os .Getwd ()
1076+ if err != nil {
1077+ t .Fatal (err )
1078+ }
1079+ defer func () { _ = os .Chdir (oldWd ) }()
1080+ if err := os .Chdir (worktreeDir ); err != nil {
1081+ t .Fatal (err )
1082+ }
1083+
1084+ sharedDoltDir := filepath .Join (homeDir , ".beads" , "shared-server" , "dolt" )
1085+ if err := os .MkdirAll (filepath .Join (sharedDoltDir , "project_existing" ), 0o750 ); err != nil {
1086+ t .Fatal (err )
1087+ }
1088+
1089+ synthesizedDir := filepath .Join (worktreeDir , ".beads" )
1090+ cfg := configfile .DefaultConfig ()
1091+ cfg .DoltMode = configfile .DoltModeServer
1092+ cfg .DoltDatabase = "project_existing"
1093+
1094+ origCheck := checkBootstrapServerDB
1095+ checkBootstrapServerDB = func (probeCfg bootstrapServerProbeConfig ) bootstrapServerDBCheck {
1096+ if probeCfg .database != "project_existing" {
1097+ t .Fatalf ("probeCfg.database = %q, want %q" , probeCfg .database , "project_existing" )
1098+ }
1099+ return bootstrapServerDBCheck {Exists : true , Reachable : true }
1100+ }
1101+ defer func () { checkBootstrapServerDB = origCheck }()
1102+
1103+ plan := detectBootstrapAction (synthesizedDir , cfg )
1104+
1105+ if plan .Action != "none" {
1106+ t .Fatalf ("expected action=%q, got %q: %s" , "none" , plan .Action , plan .Reason )
1107+ }
1108+ if ! plan .HasExisting {
1109+ t .Fatal ("expected HasExisting to be true when configured shared-server DB already exists" )
1110+ }
1111+ }
1112+
9741113// TestFinalizeSyncedBootstrapWritesConfigFiles verifies that after a sync
9751114// clone, finalizeSyncedBootstrap writes the metadata.json and config.yaml
9761115// files bd needs to reopen the cloned database. This is the regression
0 commit comments