git-gui: Add support of SHA256 repo

This patch adds the basic support of SHA256 Git repositories.
Most of changes are idiomatic replacement of the hard-coded hash ID
length, but there are subtle things:

* The hash length is determined on startup, and stored in $hashlength
  global variable (either 40 or 64).
* The hard-coded "40" are replaced with $hashlength;
  for regexp patterns, the ugly string map is used.
* Some code have the fixed numbers like 39 and 45, and those are
  replaced with the $hashlength and the offset correction.
* $nullid and $nullid2 are generated for the hash length.

A caveat is that repository picker dialog is performed before
evaluating the repo type, hence $hashlength isn't set there yet.
So the code dealing with the hard-coded "40" are handled differently;
namely, the regexp range is expanded, and the null id is generated
from the HEAD id length locally.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
maint
Takashi Iwai 2025-07-16 09:32:25 +02:00 committed by Johannes Sixt
parent 532a054451
commit dab92fe42f
5 changed files with 31 additions and 12 deletions

View File

@ -1298,6 +1298,17 @@ if {[catch {
set picked 1
}

# Use object format as hash algorithm (either "sha1" or "sha256")
set hashalgorithm [git rev-parse --show-object-format]
if {$hashalgorithm eq "sha1"} {
set hashlength 40
} elseif {$hashalgorithm eq "sha256"} {
set hashlength 64
} else {
puts stderr "Unknown hash algorithm: $hashalgorithm"
exit 1
}

# we expand the _gitdir when it's just a single dot (i.e. when we're being
# run from the .git dir itself) lest the routines to find the worktree
# get confused
@ -1391,8 +1402,8 @@ set is_conflict_diff 0
set last_revert {}
set last_revert_enc {}

set nullid "0000000000000000000000000000000000000000"
set nullid2 "0000000000000000000000000000000000000001"
set nullid [string repeat 0 $hashlength]
set nullid2 "[string repeat 0 [expr $hashlength - 1]]1"

######################################################################
##
@ -3202,7 +3213,7 @@ blame {
if {$head eq {}} {
load_current_branch
} else {
if {[regexp {^[0-9a-f]{1,39}$} $head]} {
if {[regexp [string map "@@ [expr $hashlength - 1]" {^[0-9a-f]{1,@@}$}] $head]} {
if {[catch {
set head [git rev-parse --verify $head]
} err]} {

View File

@ -426,6 +426,7 @@ method _kill {} {

method _load {jump} {
variable group_colors
global hashlength

_hide_tooltip $this

@ -436,7 +437,7 @@ method _load {jump} {
$i conf -state normal
$i delete 0.0 end
foreach g [$i tag names] {
if {[regexp {^g[0-9a-f]{40}$} $g]} {
if {[regexp [string map "@@ $hashlength" {^g[0-9a-f]{@@}$}] $g]} {
$i tag delete $g
}
}
@ -500,6 +501,8 @@ method _load {jump} {
}

method _history_menu {} {
global hashlength

set m $w.backmenu
if {[winfo exists $m]} {
$m delete 0 end
@ -513,7 +516,7 @@ method _history_menu {} {
set c [lindex $e 0]
set f [lindex $e 1]

if {[regexp {^[0-9a-f]{40}$} $c]} {
if {[regexp [string map "@@ $hashlength" {^[0-9a-f]{@@}$}] $c]} {
set t [string range $c 0 8]...
} elseif {$c eq {}} {
set t {Working Directory}
@ -627,6 +630,7 @@ method _exec_blame {cur_w cur_d options cur_s} {
method _read_blame {fd cur_w cur_d} {
upvar #0 $cur_d line_data
variable group_colors
global hashlength nullid

if {$fd ne $current_fd} {
catch {close $fd}
@ -635,7 +639,7 @@ method _read_blame {fd cur_w cur_d} {

$cur_w conf -state normal
while {[gets $fd line] >= 0} {
if {[regexp {^([a-z0-9]{40}) (\d+) (\d+) (\d+)$} $line line \
if {[regexp [string map "@@ $hashlength" {^([a-z0-9]{@@}) (\d+) (\d+) (\d+)$}] $line line \
cmit original_line final_line line_count]} {
set r_commit $cmit
set r_orig_line $original_line
@ -648,7 +652,7 @@ method _read_blame {fd cur_w cur_d} {
set oln $r_orig_line
set cmit $r_commit

if {[regexp {^0{40}$} $cmit]} {
if {$cmit eq $nullid} {
set commit_abbr work
set commit_type curr_commit
} elseif {$cmit eq $commit} {

View File

@ -879,7 +879,7 @@ method _do_clone_full_end {ok} {
if {[file exists [gitdir FETCH_HEAD]]} {
set fd [safe_open_file [gitdir FETCH_HEAD] r]
while {[gets $fd line] >= 0} {
if {[regexp "^(.{40})\t\t" $line line HEAD]} {
if {[regexp "^(.{40,64})\t\t" $line line HEAD]} {
break
}
}
@ -987,8 +987,9 @@ method _readtree_wait {fd} {

# -- Run the post-checkout hook.
#
set fd_ph [githook_read post-checkout [string repeat 0 40] \
[git rev-parse HEAD] 1]
set head_id [git rev-parse HEAD]
set fd_ph [githook_read post-checkout \
[string repeat 0 [string length $head_id]] $head_id 1]
if {$fd_ph ne {}} {
global pch_error
set pch_error {}

View File

@ -346,6 +346,7 @@ proc commit_committree {fd_wt curHEAD msg_p} {
global file_states selected_paths rescan_active
global repo_config
global env
global hashlength

gets $fd_wt tree_id
if {[catch {close $fd_wt} err]} {
@ -365,7 +366,7 @@ proc commit_committree {fd_wt curHEAD msg_p} {
close $fd_ot

if {[string equal -length 5 {tree } $old_tree]
&& [string length $old_tree] == 45} {
&& [string length $old_tree] == [expr {$hashlength + 5}]} {
set old_tree [string range $old_tree 5 end]
} else {
error [mc "Commit %s appears to be corrupt" $PARENT]

View File

@ -323,6 +323,8 @@ method _load {cache uri} {
}

method _read {cache fd} {
global hashlength

if {$fd ne $active_ls} {
catch {close $fd}
return
@ -330,7 +332,7 @@ method _read {cache fd} {

while {[gets $fd line] >= 0} {
if {[string match {*^{}} $line]} continue
if {[regexp {^([0-9a-f]{40}) (.*)$} $line _junk obj ref]} {
if {[regexp [string map "@@ $hashlength" {^([0-9a-f]{@@}) (.*)$}] $line _junk obj ref]} {
if {[regsub ^refs/heads/ $ref {} abr]} {
lappend head_list $abr
lappend head_cache($cache) $abr