@@ -821,6 +821,103 @@ func TestSubmitCreatesAndTracksPR(t *testing.T) {
821821 }
822822}
823823
824+ func TestCreateRejectsDetachedHEAD (t * testing.T ) {
825+ repo := testutil .SetupGitRepo (t )
826+ testutil .Run (t , repo , "git" , "checkout" , "--detach" )
827+
828+ runtime := newTestRuntime (repo )
829+ state := store.RepoState {
830+ Version : 1 ,
831+ Repo : "hack-dance/stack" ,
832+ DefaultRemote : "origin" ,
833+ Trunk : "main" ,
834+ Branches : map [string ]store.BranchRecord {},
835+ }
836+ if err := runtime .Store .WriteState (runtime .Context , state ); err != nil {
837+ t .Fatalf ("write state: %v" , err )
838+ }
839+
840+ err := executeCommandExpectError (runtime , "create" , "feature/a" )
841+ if err == nil || ! strings .Contains (err .Error (), "detached HEAD" ) {
842+ t .Fatalf ("expected detached HEAD error, got %v" , err )
843+ }
844+
845+ state , err = runtime .Store .ReadState (runtime .Context )
846+ if err != nil {
847+ t .Fatalf ("read state: %v" , err )
848+ }
849+ if len (state .Branches ) != 0 {
850+ t .Fatalf ("expected no tracked branches, got %+v" , state .Branches )
851+ }
852+ if runtime .Git .BranchExists (runtime .Context , "feature/a" ) {
853+ t .Fatalf ("expected feature/a branch to not be created" )
854+ }
855+ }
856+
857+ func TestCreateRejectsUntrackedCurrentParent (t * testing.T ) {
858+ repo := testutil .SetupGitRepo (t )
859+ testutil .Run (t , repo , "git" , "switch" , "-c" , "feature/base" )
860+
861+ runtime := newTestRuntime (repo )
862+ state := store.RepoState {
863+ Version : 1 ,
864+ Repo : "hack-dance/stack" ,
865+ DefaultRemote : "origin" ,
866+ Trunk : "main" ,
867+ Branches : map [string ]store.BranchRecord {},
868+ }
869+ if err := runtime .Store .WriteState (runtime .Context , state ); err != nil {
870+ t .Fatalf ("write state: %v" , err )
871+ }
872+
873+ err := executeCommandExpectError (runtime , "create" , "feature/child" )
874+ if err == nil || ! strings .Contains (err .Error (), "not tracked in local metadata" ) {
875+ t .Fatalf ("expected untracked parent error, got %v" , err )
876+ }
877+
878+ state , err = runtime .Store .ReadState (runtime .Context )
879+ if err != nil {
880+ t .Fatalf ("read state: %v" , err )
881+ }
882+ if len (state .Branches ) != 0 {
883+ t .Fatalf ("expected no tracked branches, got %+v" , state .Branches )
884+ }
885+ if runtime .Git .BranchExists (runtime .Context , "feature/child" ) {
886+ t .Fatalf ("expected feature/child branch to not be created" )
887+ }
888+ }
889+
890+ func TestTrackRejectsUntrackedParent (t * testing.T ) {
891+ repo := testutil .SetupGitRepo (t )
892+ testutil .Run (t , repo , "git" , "switch" , "-c" , "feature/base" )
893+ testutil .Run (t , repo , "git" , "switch" , "-c" , "feature/child" )
894+
895+ runtime := newTestRuntime (repo )
896+ state := store.RepoState {
897+ Version : 1 ,
898+ Repo : "hack-dance/stack" ,
899+ DefaultRemote : "origin" ,
900+ Trunk : "main" ,
901+ Branches : map [string ]store.BranchRecord {},
902+ }
903+ if err := runtime .Store .WriteState (runtime .Context , state ); err != nil {
904+ t .Fatalf ("write state: %v" , err )
905+ }
906+
907+ err := executeCommandExpectError (runtime , "track" , "feature/child" , "--parent" , "feature/base" )
908+ if err == nil || ! strings .Contains (err .Error (), "parent branch \" feature/base\" is not tracked in local metadata" ) {
909+ t .Fatalf ("expected untracked parent error, got %v" , err )
910+ }
911+
912+ state , err = runtime .Store .ReadState (runtime .Context )
913+ if err != nil {
914+ t .Fatalf ("read state: %v" , err )
915+ }
916+ if len (state .Branches ) != 0 {
917+ t .Fatalf ("expected no tracked branches, got %+v" , state .Branches )
918+ }
919+ }
920+
824921func TestVersionCommandPrintsBuildInfo (t * testing.T ) {
825922 repo := testutil .SetupGitRepo (t )
826923 runtime := newTestRuntime (repo )
0 commit comments