@@ -737,6 +737,38 @@ static struct line_log_data *lookup_line_range(struct rev_info *revs,
737
737
return ret ;
738
738
}
739
739
740
+ static int same_paths_in_pathspec_and_range (struct pathspec * pathspec ,
741
+ struct line_log_data * range )
742
+ {
743
+ int i ;
744
+ struct line_log_data * r ;
745
+
746
+ for (i = 0 , r = range ; i < pathspec -> nr && r ; i ++ , r = r -> next )
747
+ if (strcmp (pathspec -> items [i ].match , r -> path ))
748
+ return 0 ;
749
+ if (i < pathspec -> nr || r )
750
+ /* different number of pathspec items and ranges */
751
+ return 0 ;
752
+
753
+ return 1 ;
754
+ }
755
+
756
+ static void parse_pathspec_from_ranges (struct pathspec * pathspec ,
757
+ struct line_log_data * range )
758
+ {
759
+ struct line_log_data * r ;
760
+ struct argv_array array = ARGV_ARRAY_INIT ;
761
+ const char * * paths ;
762
+
763
+ for (r = range ; r ; r = r -> next )
764
+ argv_array_push (& array , r -> path );
765
+ paths = argv_array_detach (& array );
766
+
767
+ parse_pathspec (pathspec , 0 , PATHSPEC_PREFER_FULL , "" , paths );
768
+ /* strings are now owned by pathspec */
769
+ free (paths );
770
+ }
771
+
740
772
void line_log_init (struct rev_info * rev , const char * prefix , struct string_list * args )
741
773
{
742
774
struct commit * commit = NULL ;
@@ -746,20 +778,7 @@ void line_log_init(struct rev_info *rev, const char *prefix, struct string_list
746
778
range = parse_lines (rev -> diffopt .repo , commit , prefix , args );
747
779
add_line_range (rev , commit , range );
748
780
749
- if (!rev -> diffopt .detect_rename ) {
750
- struct line_log_data * r ;
751
- struct argv_array array = ARGV_ARRAY_INIT ;
752
- const char * * paths ;
753
-
754
- for (r = range ; r ; r = r -> next )
755
- argv_array_push (& array , r -> path );
756
- paths = argv_array_detach (& array );
757
-
758
- parse_pathspec (& rev -> diffopt .pathspec , 0 ,
759
- PATHSPEC_PREFER_FULL , "" , paths );
760
- /* strings are now owned by pathspec */
761
- free (paths );
762
- }
781
+ parse_pathspec_from_ranges (& rev -> diffopt .pathspec , range );
763
782
}
764
783
765
784
static void move_diff_queue (struct diff_queue_struct * dst ,
@@ -817,15 +836,29 @@ static void queue_diffs(struct line_log_data *range,
817
836
struct diff_queue_struct * queue ,
818
837
struct commit * commit , struct commit * parent )
819
838
{
839
+ struct object_id * tree_oid , * parent_tree_oid ;
840
+
820
841
assert (commit );
821
842
843
+ tree_oid = get_commit_tree_oid (commit );
844
+ parent_tree_oid = parent ? get_commit_tree_oid (parent ) : NULL ;
845
+
846
+ if (opt -> detect_rename &&
847
+ !same_paths_in_pathspec_and_range (& opt -> pathspec , range )) {
848
+ clear_pathspec (& opt -> pathspec );
849
+ parse_pathspec_from_ranges (& opt -> pathspec , range );
850
+ }
822
851
DIFF_QUEUE_CLEAR (& diff_queued_diff );
823
- diff_tree_oid (parent ? get_commit_tree_oid (parent ) : NULL ,
824
- get_commit_tree_oid (commit ), "" , opt );
825
- if (opt -> detect_rename ) {
852
+ diff_tree_oid (parent_tree_oid , tree_oid , "" , opt );
853
+ if (opt -> detect_rename && diff_might_be_rename ()) {
854
+ /* must look at the full tree diff to detect renames */
855
+ clear_pathspec (& opt -> pathspec );
856
+ DIFF_QUEUE_CLEAR (& diff_queued_diff );
857
+
858
+ diff_tree_oid (parent_tree_oid , tree_oid , "" , opt );
859
+
826
860
filter_diffs_for_paths (range , 1 );
827
- if (diff_might_be_rename ())
828
- diffcore_std (opt );
861
+ diffcore_std (opt );
829
862
filter_diffs_for_paths (range , 0 );
830
863
}
831
864
move_diff_queue (queue , & diff_queued_diff );
0 commit comments