@@ -1106,6 +1106,104 @@ exit 1
11061106 } ) ;
11071107}
11081108
1109+ #[ test]
1110+ fn sync_removes_local_parent_branch_after_repair_when_parent_was_merged_upstream ( ) {
1111+ with_temp_repo ( "dig-sync-cli" , |repo| {
1112+ initialize_main_repo ( repo) ;
1113+ initialize_origin_remote ( repo) ;
1114+ dig_ok ( repo, & [ "init" ] ) ;
1115+ dig_ok ( repo, & [ "branch" , "feat/root" ] ) ;
1116+ commit_file ( repo, "root.txt" , "root\n " , "feat: root" ) ;
1117+ git_ok ( repo, & [ "push" , "-u" , "origin" , "feat/root" ] ) ;
1118+ track_pull_request_number ( repo, "feat/root" , 101 ) ;
1119+ dig_ok ( repo, & [ "branch" , "feat/auth" ] ) ;
1120+ commit_file ( repo, "auth.txt" , "auth\n " , "feat: auth" ) ;
1121+ git_ok ( repo, & [ "push" , "-u" , "origin" , "feat/auth" ] ) ;
1122+ track_pull_request_number ( repo, "feat/auth" , 102 ) ;
1123+ dig_ok ( repo, & [ "branch" , "feat/auth-ui" ] ) ;
1124+ commit_file ( repo, "ui.txt" , "ui\n " , "feat: ui" ) ;
1125+ git_ok ( repo, & [ "push" , "-u" , "origin" , "feat/auth-ui" ] ) ;
1126+ track_pull_request_number ( repo, "feat/auth-ui" , 103 ) ;
1127+
1128+ let parent_head_oid = git_stdout ( repo, & [ "rev-parse" , "feat/auth" ] ) ;
1129+ let remote_repo = clone_origin ( repo, "origin-worktree-local-parent" ) ;
1130+ git_ok ( & remote_repo, & [ "checkout" , "main" ] ) ;
1131+ git_ok ( & remote_repo, & [ "merge" , "--squash" , "origin/feat/root" ] ) ;
1132+ git_ok (
1133+ & remote_repo,
1134+ & [ "commit" , "--quiet" , "-m" , "feat: merge root" ] ,
1135+ ) ;
1136+ git_ok ( & remote_repo, & [ "push" , "origin" , "main" ] ) ;
1137+ git_ok ( & remote_repo, & [ "push" , "origin" , "--delete" , "feat/root" ] ) ;
1138+ git_ok ( & remote_repo, & [ "push" , "origin" , "--delete" , "feat/auth" ] ) ;
1139+
1140+ git_ok ( repo, & [ "checkout" , "main" ] ) ;
1141+ git_ok ( repo, & [ "branch" , "-D" , "feat/root" ] ) ;
1142+ set_branch_archived ( repo, "feat/root" , true ) ;
1143+
1144+ let remote_update_log = install_remote_update_logger ( repo) ;
1145+ let ( path, gh_log_path) = install_fake_gh (
1146+ repo,
1147+ & format ! (
1148+ r#"#!/bin/sh
1149+ set -eu
1150+ printf '%s\n' "$*" >> "$DIG_TEST_GH_LOG"
1151+ if [ "$1" = "pr" ] && [ "$2" = "view" ] && [ "$3" = "102" ]; then
1152+ printf '{{"number":102,"state":"MERGED","mergedAt":"2026-03-26T12:00:00Z","baseRefName":"feat/root","headRefName":"feat/auth","headRefOid":"{parent_head_oid}","isDraft":false,"url":"https://github.com/acme/dig/pull/102"}}\n'
1153+ exit 0
1154+ fi
1155+ if [ "$1" = "pr" ] && [ "$2" = "view" ] && [ "$3" = "103" ]; then
1156+ printf '{{"number":103,"state":"CLOSED","mergedAt":null,"baseRefName":"feat/auth","headRefName":"feat/auth-ui","isDraft":false,"url":"https://github.com/acme/dig/pull/103"}}\n'
1157+ exit 0
1158+ fi
1159+ if [ "$1" = "pr" ] && [ "$2" = "reopen" ] && [ "$3" = "103" ]; then
1160+ exit 0
1161+ fi
1162+ if [ "$1" = "pr" ] && [ "$2" = "ready" ] && [ "$3" = "103" ] && [ "$4" = "--undo" ]; then
1163+ exit 0
1164+ fi
1165+ if [ "$1" = "pr" ] && [ "$2" = "edit" ] && [ "$3" = "103" ] && [ "$4" = "--base" ] && [ "$5" = "main" ]; then
1166+ exit 0
1167+ fi
1168+ echo "unexpected gh args: $*" >&2
1169+ exit 1
1170+ "#
1171+ ) ,
1172+ ) ;
1173+
1174+ let output = dig_with_input_and_env (
1175+ repo,
1176+ & [ "sync" ] ,
1177+ "n\n " ,
1178+ & [
1179+ ( "PATH" , path. as_str ( ) ) ,
1180+ ( "DIG_TEST_GH_LOG" , gh_log_path. as_str ( ) ) ,
1181+ ] ,
1182+ ) ;
1183+ let stdout = strip_ansi ( & String :: from_utf8 ( output. stdout ) . unwrap ( ) ) ;
1184+ let stderr = String :: from_utf8 ( output. stderr ) . unwrap ( ) ;
1185+
1186+ assert ! (
1187+ output. status. success( ) ,
1188+ "stdout:\n {stdout}\n stderr:\n {stderr}"
1189+ ) ;
1190+ assert ! ( stdout. contains( "Recovered pull requests:" ) ) ;
1191+ assert ! ( stdout. contains( "Deleted locally and no longer tracked by dig:" ) ) ;
1192+ assert ! ( stdout. contains( "- feat/auth" ) ) ;
1193+ assert_eq ! ( git_stdout( repo, & [ "branch" , "--list" , "feat/auth" ] ) , "" ) ;
1194+
1195+ let state = load_state_json ( repo) ;
1196+ let child = find_node ( & state, "feat/auth-ui" ) . unwrap ( ) ;
1197+ assert_eq ! ( child[ "base_ref" ] , "main" ) ;
1198+ assert_eq ! ( child[ "parent" ] [ "kind" ] , "trunk" ) ;
1199+ assert ! ( find_archived_node( & state, "feat/auth" ) . is_some( ) ) ;
1200+ assert_eq ! (
1201+ count_remote_ref_updates( & remote_update_log, "refs/heads/feat/auth" ) ,
1202+ 2
1203+ ) ;
1204+ } ) ;
1205+ }
1206+
11091207#[ test]
11101208fn sync_aborts_before_local_cleanup_when_pull_request_repair_fails ( ) {
11111209 with_temp_repo ( "dig-sync-cli" , |repo| {
0 commit comments