@@ -5,12 +5,20 @@ mod mac_watcher;
55pub mod fs_watcher;
66
77use anyhow:: { anyhow, Context as _, Result } ;
8+ #[ cfg( any( test, feature = "test-support" ) ) ]
9+ use collections:: HashMap ;
10+ #[ cfg( any( test, feature = "test-support" ) ) ]
11+ use git:: status:: StatusCode ;
12+ #[ cfg( any( test, feature = "test-support" ) ) ]
13+ use git:: status:: TrackedStatus ;
814use git:: GitHostingProviderRegistry ;
915#[ cfg( any( test, feature = "test-support" ) ) ]
1016use git:: { repository:: RepoPath , status:: FileStatus } ;
1117
1218#[ cfg( any( target_os = "linux" , target_os = "freebsd" ) ) ]
1319use ashpd:: desktop:: trash;
20+ #[ cfg( any( test, feature = "test-support" ) ) ]
21+ use std:: collections:: HashSet ;
1422#[ cfg( unix) ]
1523use std:: os:: fd:: AsFd ;
1624#[ cfg( unix) ]
@@ -1292,6 +1300,105 @@ impl FakeFs {
12921300 } ) ;
12931301 }
12941302
1303+ pub fn set_git_content_for_repo (
1304+ & self ,
1305+ dot_git : & Path ,
1306+ head_state : & [ ( RepoPath , String , Option < String > ) ] ,
1307+ ) {
1308+ self . with_git_state ( dot_git, true , |state| {
1309+ state. head_contents . clear ( ) ;
1310+ state. head_contents . extend (
1311+ head_state
1312+ . iter ( )
1313+ . map ( |( path, head_content, _) | ( path. clone ( ) , head_content. clone ( ) ) ) ,
1314+ ) ;
1315+ state. index_contents . clear ( ) ;
1316+ state. index_contents . extend ( head_state. iter ( ) . map (
1317+ |( path, head_content, index_content) | {
1318+ (
1319+ path. clone ( ) ,
1320+ index_content. as_ref ( ) . unwrap_or ( head_content) . clone ( ) ,
1321+ )
1322+ } ,
1323+ ) ) ;
1324+ } ) ;
1325+ self . recalculate_git_status ( dot_git) ;
1326+ }
1327+
1328+ pub fn recalculate_git_status ( & self , dot_git : & Path ) {
1329+ let git_files: HashMap < _ , _ > = self
1330+ . files ( )
1331+ . iter ( )
1332+ . filter_map ( |path| {
1333+ let repo_path =
1334+ RepoPath :: new ( path. strip_prefix ( dot_git. parent ( ) . unwrap ( ) ) . ok ( ) ?. into ( ) ) ;
1335+ let content = self
1336+ . read_file_sync ( path)
1337+ . ok ( )
1338+ . map ( |content| String :: from_utf8 ( content) . unwrap ( ) ) ;
1339+ Some ( ( repo_path, content?) )
1340+ } )
1341+ . collect ( ) ;
1342+ self . with_git_state ( dot_git, false , |state| {
1343+ state. statuses . clear ( ) ;
1344+ let mut paths: HashSet < _ > = state. head_contents . keys ( ) . collect ( ) ;
1345+ paths. extend ( state. index_contents . keys ( ) ) ;
1346+ paths. extend ( git_files. keys ( ) ) ;
1347+ for path in paths {
1348+ let head = state. head_contents . get ( path) ;
1349+ let index = state. index_contents . get ( path) ;
1350+ let fs = git_files. get ( path) ;
1351+ let status = match ( head, index, fs) {
1352+ ( Some ( head) , Some ( index) , Some ( fs) ) => FileStatus :: Tracked ( TrackedStatus {
1353+ index_status : if head == index {
1354+ StatusCode :: Unmodified
1355+ } else {
1356+ StatusCode :: Modified
1357+ } ,
1358+ worktree_status : if fs == index {
1359+ StatusCode :: Unmodified
1360+ } else {
1361+ StatusCode :: Modified
1362+ } ,
1363+ } ) ,
1364+ ( Some ( head) , Some ( index) , None ) => FileStatus :: Tracked ( TrackedStatus {
1365+ index_status : if head == index {
1366+ StatusCode :: Unmodified
1367+ } else {
1368+ StatusCode :: Modified
1369+ } ,
1370+ worktree_status : StatusCode :: Deleted ,
1371+ } ) ,
1372+ ( Some ( _) , None , Some ( _) ) => FileStatus :: Tracked ( TrackedStatus {
1373+ index_status : StatusCode :: Deleted ,
1374+ worktree_status : StatusCode :: Added ,
1375+ } ) ,
1376+ ( Some ( _) , None , None ) => FileStatus :: Tracked ( TrackedStatus {
1377+ index_status : StatusCode :: Deleted ,
1378+ worktree_status : StatusCode :: Deleted ,
1379+ } ) ,
1380+ ( None , Some ( index) , Some ( fs) ) => FileStatus :: Tracked ( TrackedStatus {
1381+ index_status : StatusCode :: Added ,
1382+ worktree_status : if fs == index {
1383+ StatusCode :: Unmodified
1384+ } else {
1385+ StatusCode :: Modified
1386+ } ,
1387+ } ) ,
1388+ ( None , Some ( _) , None ) => FileStatus :: Tracked ( TrackedStatus {
1389+ index_status : StatusCode :: Added ,
1390+ worktree_status : StatusCode :: Deleted ,
1391+ } ) ,
1392+ ( None , None , Some ( _) ) => FileStatus :: Untracked ,
1393+ ( None , None , None ) => {
1394+ unreachable ! ( ) ;
1395+ }
1396+ } ;
1397+ state. statuses . insert ( path. clone ( ) , status) ;
1398+ }
1399+ } ) ;
1400+ }
1401+
12951402 pub fn set_blame_for_repo ( & self , dot_git : & Path , blames : Vec < ( RepoPath , git:: blame:: Blame ) > ) {
12961403 self . with_git_state ( dot_git, true , |state| {
12971404 state. blames . clear ( ) ;
0 commit comments