AW: [PATCH v5] gitk: add external diff file rename detection

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Hannes,

please ignore the V5 patch.
I totally missed to check for the file of interest when checking for renames.
I'll correct that and send an update.

Best wishes
Tobias

> -----Ursprüngliche Nachricht-----
> Von: ToBoMi via GitGitGadget <gitgitgadget@xxxxxxxxx>
> Gesendet: Dienstag, 10. Juni 2025 10:30
> An: git@xxxxxxxxxxxxxxx
> Cc: Johannes Sixt <j6t@xxxxxxxx>; Boesch, Tobias
> <tobias.boesch@xxxxxxxxx>; Boesch, Tobias <tobias.boesch@xxxxxxxxx>;
> Boesch, Tobias <tobias.boesch@xxxxxxxxx>
> Betreff: [PATCH v5] gitk: add external diff file rename detection
>
> From: Tobias Boesch <tobias.boesch@xxxxxxxxx>
>
> If a file is renamed between commits and an external diff is started through
> gitk on the original or the renamed file name, gitk is unable to open the
> renamed file in the external diff editor.
> It fails to fetch the renamed file from git, because it fetches it using its original
> path in contrast to using the renamed path of the file.
> Detect the rename and open the external diff with the original and the
> renamed file instead of no file (fetch the renamed file path and name from git)
> no matter if the original or the renamed file is selected in gitk.
> Since moved or renamed file are handled the same way do this also for moved
> files.
>
> Signed-off-by: Tobias Boesch <tobias.boesch@xxxxxxxxx>
> ---
>     gitk: add external diff file rename detection
>
>     Changes since v1:
>
>      * Commit message ident
>      * Commit message line length
>
>     Changes since v2:
>
>      * Removed option for rename detection (Adding GUI options seems to be
>        not desired - which is understandable)
>      * Rebased on current master of git-for-windows
>      * Renamed variables for a better understanding
>      * Made rename detection also work when the renamed file is selected in
>        gitk
>
>     Changes since v3:
>
>      * Changed message to use present tense, removed bullet points and
>        described changes in imperative mood
>
>     Changes sine v4:
>
>      * Use a git command to gather the changed file paths rather than
>        parsing the text from the diff window panel for efficiency and to
>        avoid regex containing the filename as a variable.
>      * Change != to ne in string comparison
>      * removed extra set of parentheses around &&
>      * shorter variable names
>
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-
> 1774%2FToBoMi%2Fdetect_renamed_files_when_opening_diff-v5
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-
> 1774/ToBoMi/detect_renamed_files_when_opening_diff-v5
> Pull-Request: https://github.com/gitgitgadget/git/pull/1774
>
> Range-diff vs v4:
>
>  1:  948b94bef5c ! 1:  0d28f189dc3 gitk: add external diff file rename
> detection
>      @@ gitk-git/gitk: proc external_diff_get_one_file {diffid filename diffdir} {
>                       "revision $diffid"]
>        }
>
>      -+proc check_for_renames_in_diff {filepath} {
>      -+    global ctext
>      ++proc check_for_renames_in_diff {diffidfrom diffidto filepath} {
>      ++    global nullid nullid2
>       +
>      -+    set renamed_filenames [list {}]
>      -+    set filename [file tail $filepath]
>      -+    set rename_from_text_identifier_length 12
>      -+    set rename_to_text_identifier_length 10
>      -+    set reg_expr_rename_from {^rename from (.*$filename)}
>      -+    set reg_expr_rename_from [subst -nobackslashes -nocommands
> $reg_expr_rename_from]
>      -+    set rename_from_text_index [$ctext search -elide -regexp --
> $reg_expr_rename_from 0.0]
>      -+    if { ($rename_from_text_index != {})} {
>      -+        set reg_expr_rename_to {^rename to (.*)}
>      -+        set rename_to_text_index [$ctext search -elide -regexp --
> $reg_expr_rename_to $rename_from_text_index]
>      -+        if { ($rename_from_text_index != {}) && ($rename_to_text_index !=
> {}) } {
>      -+            lappend renamed_filenames [$ctext get
> "$rename_from_text_index + $rename_from_text_identifier_length chars"
> "$rename_from_text_index lineend"]
>      -+            lappend renamed_filenames [$ctext get "$rename_to_text_index +
> $rename_to_text_identifier_length chars" "$rename_to_text_index lineend"]
>      -+        }
>      -+        return $renamed_filenames
>      ++    if {$diffidfrom eq $nullid} {
>      ++        set rev [list $diffidto -R]
>      ++    } elseif {$diffidfrom eq $nullid2} {
>      ++        set rev [list $diffidto --cached -R]
>      ++    } elseif {$diffidto eq $nullid} {
>      ++        set rev [list $diffidfrom]
>      ++    } elseif {$diffidto eq $nullid2} {
>      ++        set rev [list $diffidfrom --cached]
>      ++    } else {
>      ++        set rev [list $diffidfrom..$diffidto]
>       +    }
>      -+    set reg_expr_rename_to {^rename to (.*$filename)}
>      -+    set reg_expr_rename_to [subst -nobackslashes -nocommands
> $reg_expr_rename_to]
>      -+    set rename_to_text_index [$ctext search -elide -regexp --
> $reg_expr_rename_to 0.0]
>      -+    if { ($rename_to_text_index != {})} {
>      -+        set reg_expr_rename_from {^rename from (.*)}
>      -+        set rename_from_text_index [$ctext search -backwards -elide -regexp
> -- $reg_expr_rename_from $rename_to_text_index]
>      -+        if { ($rename_to_text_index != {}) && ($rename_from_text_index !=
> {}) } {
>      -+            lappend renamed_filenames [$ctext get
> "$rename_from_text_index + $rename_from_text_identifier_length chars"
> "$rename_from_text_index lineend"]
>      -+            lappend renamed_filenames [$ctext get "$rename_to_text_index +
> $rename_to_text_identifier_length chars" "$rename_to_text_index lineend"]
>      ++
>      ++    set renames [list {}]
>      ++    if {[catch {eval exec git diff $rev --find-renames --stat --raw --diff-
> filter=R} cmd_result]} {
>      ++        error_popup "[mc "Error getting file rename info for file \"%s\" from
> commit %s to %s." \
>      ++                            $filepath $diffidfrom $diffidto] $cmd_result.\n\n"
>      ++    }
>      ++    set filename [file tail $filepath]
>      ++    set regex_ren {\d+\s\d+\s\S+\s\S+\s\S+\s+(\S+)\s+(\S+)}
>      ++    set regex_ren [subst -nobackslashes -nocommands $regex_ren]
>      ++    if {[regexp -line -- $regex_ren $cmd_result whole_match ren_from
> ren_to]} {
>      ++        if {$ren_from ne {} && $ren_to ne {}} {
>      ++            lappend renames $ren_from
>      ++            lappend renames $ren_to
>       +        }
>      -+        return $renamed_filenames
>       +    }
>      ++    return $renames
>       +}
>       +
>        proc external_diff {} {
>      @@ gitk-git/gitk: proc external_diff {} {
>            # gather files to diff
>       -    set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file
> $diffdir]
>       -    set difftofile [external_diff_get_one_file $diffidto $flist_menu_file
> $diffdir]
>      -+    set renamed_filenames [check_for_renames_in_diff $flist_menu_file]
>      ++    set renamed_filenames [check_for_renames_in_diff $diffidfrom
> $diffidto $flist_menu_file]
>       +    set rename_from_filename [lindex $renamed_filenames 1]
>       +    set rename_to_filename [lindex $renamed_filenames 2]
>       +    if { ($rename_from_filename != {}) && ($rename_to_filename != {}) } {
>
>
>  gitk-git/gitk | 44 ++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 42 insertions(+), 2 deletions(-)
>
> diff --git a/gitk-git/gitk b/gitk-git/gitk index 19689765cde..f97904f5fa2
> 100755
> --- a/gitk-git/gitk
> +++ b/gitk-git/gitk
> @@ -3775,6 +3775,38 @@ proc external_diff_get_one_file {diffid filename
> diffdir} {
>                 "revision $diffid"]
>  }
>
> +proc check_for_renames_in_diff {diffidfrom diffidto filepath} {
> +    global nullid nullid2
> +
> +    if {$diffidfrom eq $nullid} {
> +        set rev [list $diffidto -R]
> +    } elseif {$diffidfrom eq $nullid2} {
> +        set rev [list $diffidto --cached -R]
> +    } elseif {$diffidto eq $nullid} {
> +        set rev [list $diffidfrom]
> +    } elseif {$diffidto eq $nullid2} {
> +        set rev [list $diffidfrom --cached]
> +    } else {
> +        set rev [list $diffidfrom..$diffidto]
> +    }
> +
> +    set renames [list {}]
> +    if {[catch {eval exec git diff $rev --find-renames --stat --raw --diff-filter=R}
> cmd_result]} {
> +        error_popup "[mc "Error getting file rename info for file \"%s\" from
> commit %s to %s." \
> +                            $filepath $diffidfrom $diffidto] $cmd_result.\n\n"
> +    }
> +    set filename [file tail $filepath]
> +    set regex_ren {\d+\s\d+\s\S+\s\S+\s\S+\s+(\S+)\s+(\S+)}
> +    set regex_ren [subst -nobackslashes -nocommands $regex_ren]
> +    if {[regexp -line -- $regex_ren $cmd_result whole_match ren_from ren_to]}
> {
> +        if {$ren_from ne {} && $ren_to ne {}} {
> +            lappend renames $ren_from
> +            lappend renames $ren_to
> +        }
> +    }
> +    return $renames
> +}
> +
>  proc external_diff {} {
>      global nullid nullid2
>      global flist_menu_file
> @@ -3805,8 +3837,16 @@ proc external_diff {} {
>      if {$diffdir eq {}} return
>
>      # gather files to diff
> -    set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file
> $diffdir]
> -    set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
> +    set renamed_filenames [check_for_renames_in_diff $diffidfrom $diffidto
> $flist_menu_file]
> +    set rename_from_filename [lindex $renamed_filenames 1]
> +    set rename_to_filename [lindex $renamed_filenames 2]
> +    if { ($rename_from_filename != {}) && ($rename_to_filename != {}) } {
> +        set difffromfile [external_diff_get_one_file $diffidfrom
> $rename_from_filename $diffdir]
> +        set difftofile [external_diff_get_one_file $diffidto $rename_to_filename
> $diffdir]
> +    } else {
> +        set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file
> $diffdir]
> +        set difftofile [external_diff_get_one_file $diffidto $flist_menu_file
> $diffdir]
> +    }
>
>      if {$difffromfile ne {} && $difftofile ne {}} {
>          set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
>
> base-commit: 14de3eb34435db79c6e7edc8082c302a26a8330a
> --
> gitgitgadget


-------------------------------------------------------------------------------------------------
imperial-Werke oHG, Sitz Bünde, Registergericht Bad Oeynhausen - HRA 4825




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux