@@ -340,11 +340,14 @@ pub fn diff_paths(
340340}
341341
342342pub fn overlay (
343- repo : & git2 :: Repository ,
343+ transaction : & cache :: Transaction ,
344344 input1 : git2:: Oid ,
345345 input2 : git2:: Oid ,
346346) -> JoshResult < git2:: Oid > {
347- rs_tracing:: trace_scoped!( "overlay" ) ;
347+ if let Some ( cached) = transaction. get_overlay ( ( input1, input2) ) {
348+ return Ok ( cached) ;
349+ }
350+ let repo = transaction. repo ( ) ;
348351 if input1 == input2 {
349352 return Ok ( input1) ;
350353 }
@@ -356,29 +359,35 @@ pub fn overlay(
356359 }
357360
358361 if let ( Ok ( tree1) , Ok ( tree2) ) = ( repo. find_tree ( input1) , repo. find_tree ( input2) ) {
359- let mut result_tree = tree1. clone ( ) ;
362+ rs_tracing:: trace_begin!( "overlay" ,
363+ "overlay_a" : format!( "{}" , input1) ,
364+ "overlay_b" : format!( "{}" , input2) ,
365+ "overlay_ab" : format!( "{} - {}" , input1, input2) ) ;
366+ let mut builder = repo. treebuilder ( Some ( & tree1) ) ?;
360367
368+ let mut i = 0 ;
361369 for entry in tree2. iter ( ) {
362- if let Some ( e) = tree1. get_name ( entry. name ( ) . ok_or_else ( || josh_error ( "no name" ) ) ?) {
363- result_tree = replace_child (
364- repo,
365- Path :: new ( entry. name ( ) . ok_or_else ( || josh_error ( "no name" ) ) ?) ,
366- overlay ( repo, e. id ( ) , entry. id ( ) ) ?,
367- e. filemode ( ) ,
368- & result_tree,
369- ) ?;
370+ i += 1 ;
371+ let ( id, mode) = if let Some ( e) =
372+ tree1. get_name ( entry. name ( ) . ok_or_else ( || josh_error ( "no name" ) ) ?)
373+ {
374+ ( overlay ( transaction, e. id ( ) , entry. id ( ) ) ?, e. filemode ( ) )
370375 } else {
371- result_tree = replace_child (
372- repo ,
373- Path :: new ( entry . name ( ) . ok_or_else ( || josh_error ( "no name" ) ) ? ) ,
374- entry . id ( ) ,
375- entry. filemode ( ) ,
376- & result_tree ,
377- ) ? ;
378- }
376+ ( entry . id ( ) , entry . filemode ( ) )
377+ } ;
378+
379+ builder . insert (
380+ Path :: new ( entry. name ( ) . ok_or_else ( || josh_error ( "no name" ) ) ? ) ,
381+ id ,
382+ mode ,
383+ ) ? ;
379384 }
380385
381- return Ok ( result_tree. id ( ) ) ;
386+ let rid = builder. write ( ) ?;
387+ rs_tracing:: trace_end!( "overlay" , "count" : i) ;
388+
389+ transaction. insert_overlay ( ( input1, input2) , rid) ;
390+ return Ok ( rid) ;
382391 }
383392
384393 Ok ( input1)
@@ -837,7 +846,7 @@ pub fn invert_paths<'a>(
837846 & format ! ( "{}{}{}" , root, if root. is_empty( ) { "" } else { "/" } , name) ,
838847 repo. find_tree ( entry. id ( ) ) ?,
839848 ) ?;
840- result = repo. find_tree ( overlay ( repo , result. id ( ) , s. id ( ) ) ?) ?;
849+ result = repo. find_tree ( overlay ( transaction , result. id ( ) , s. id ( ) ) ?) ?;
841850 }
842851 }
843852
@@ -897,7 +906,7 @@ fn populate(
897906 for entry in content. iter ( ) {
898907 if let Some ( e) = paths. get_name ( entry. name ( ) . ok_or_else ( || josh_error ( "no name" ) ) ?) {
899908 result_tree = overlay (
900- repo ,
909+ transaction ,
901910 result_tree,
902911 populate ( transaction, e. id ( ) , entry. id ( ) ) ?,
903912 ) ?;
@@ -918,7 +927,7 @@ pub fn compose_fast(
918927 let repo = transaction. repo ( ) ;
919928 let mut result = empty_id ( ) ;
920929 for tree in trees {
921- result = overlay ( repo , tree, result) ?;
930+ result = overlay ( transaction , tree, result) ?;
922931 }
923932
924933 Ok ( repo. find_tree ( result) ?)
@@ -950,8 +959,8 @@ pub fn compose<'a>(
950959 apply ( transaction, invert ( * f) ?, applied) ?. id ( )
951960 } ;
952961 transaction. insert_unapply ( * f, aid, unapplied) ;
953- taken = repo. find_tree ( overlay ( repo , taken. id ( ) , unapplied) ?) ?;
954- result = repo. find_tree ( overlay ( repo , subtracted. id ( ) , result. id ( ) ) ?) ?;
962+ taken = repo. find_tree ( overlay ( transaction , taken. id ( ) , unapplied) ?) ?;
963+ result = repo. find_tree ( overlay ( transaction , subtracted. id ( ) , result. id ( ) ) ?) ?;
955964 }
956965
957966 Ok ( result)
0 commit comments