@@ -340,11 +340,14 @@ pub fn diff_paths(
340
340
}
341
341
342
342
pub fn overlay (
343
- repo : & git2 :: Repository ,
343
+ transaction : & cache :: Transaction ,
344
344
input1 : git2:: Oid ,
345
345
input2 : git2:: Oid ,
346
346
) -> 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 ( ) ;
348
351
if input1 == input2 {
349
352
return Ok ( input1) ;
350
353
}
@@ -356,29 +359,35 @@ pub fn overlay(
356
359
}
357
360
358
361
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) ) ?;
360
367
368
+ let mut i = 0 ;
361
369
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 ( ) )
370
375
} 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
+ ) ? ;
379
384
}
380
385
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) ;
382
391
}
383
392
384
393
Ok ( input1)
@@ -837,7 +846,7 @@ pub fn invert_paths<'a>(
837
846
& format ! ( "{}{}{}" , root, if root. is_empty( ) { "" } else { "/" } , name) ,
838
847
repo. find_tree ( entry. id ( ) ) ?,
839
848
) ?;
840
- result = repo. find_tree ( overlay ( repo , result. id ( ) , s. id ( ) ) ?) ?;
849
+ result = repo. find_tree ( overlay ( transaction , result. id ( ) , s. id ( ) ) ?) ?;
841
850
}
842
851
}
843
852
@@ -897,7 +906,7 @@ fn populate(
897
906
for entry in content. iter ( ) {
898
907
if let Some ( e) = paths. get_name ( entry. name ( ) . ok_or_else ( || josh_error ( "no name" ) ) ?) {
899
908
result_tree = overlay (
900
- repo ,
909
+ transaction ,
901
910
result_tree,
902
911
populate ( transaction, e. id ( ) , entry. id ( ) ) ?,
903
912
) ?;
@@ -918,7 +927,7 @@ pub fn compose_fast(
918
927
let repo = transaction. repo ( ) ;
919
928
let mut result = empty_id ( ) ;
920
929
for tree in trees {
921
- result = overlay ( repo , tree, result) ?;
930
+ result = overlay ( transaction , tree, result) ?;
922
931
}
923
932
924
933
Ok ( repo. find_tree ( result) ?)
@@ -950,8 +959,8 @@ pub fn compose<'a>(
950
959
apply ( transaction, invert ( * f) ?, applied) ?. id ( )
951
960
} ;
952
961
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 ( ) ) ?) ?;
955
964
}
956
965
957
966
Ok ( result)
0 commit comments