@@ -737,6 +737,38 @@ static struct line_log_data *lookup_line_range(struct rev_info *revs,
737737 return ret ;
738738}
739739
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+
740772void line_log_init (struct rev_info * rev , const char * prefix , struct string_list * args )
741773{
742774 struct commit * commit = NULL ;
@@ -746,20 +778,7 @@ void line_log_init(struct rev_info *rev, const char *prefix, struct string_list
746778 range = parse_lines (rev -> diffopt .repo , commit , prefix , args );
747779 add_line_range (rev , commit , range );
748780
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 );
763782}
764783
765784static void move_diff_queue (struct diff_queue_struct * dst ,
@@ -817,15 +836,29 @@ static void queue_diffs(struct line_log_data *range,
817836 struct diff_queue_struct * queue ,
818837 struct commit * commit , struct commit * parent )
819838{
839+ struct object_id * tree_oid , * parent_tree_oid ;
840+
820841 assert (commit );
821842
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+ }
822851 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+
826860 filter_diffs_for_paths (range , 1 );
827- if (diff_might_be_rename ())
828- diffcore_std (opt );
861+ diffcore_std (opt );
829862 filter_diffs_for_paths (range , 0 );
830863 }
831864 move_diff_queue (queue , & diff_queued_diff );
0 commit comments