git-gui: convert git_read*, git_write to be non-variadic
We are going to treat command arguments and redirections differently to avoid passing arguments that look like redirections to the command accidentally. To do so, it will be necessary to know which arguments are intentional redirections. As a preparation, convert git_read, git_read_nice, and git_write to take just a single argument that is the command in a list. Adjust all call sites accordingly. In the future, this argument will be the regular command arguments and a second argument will be the redirection operations. Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Taylor Blau <me@ttaylorr.com>
Johannes Sixt committed
May 3, 2025 at 13:24 UTC
dc9ecb1aab1a3438fceeb44db67ddf8e8d938324
16 files changed
+62
-62
git-gui.sh
+24
-24
@@ -621,7 +621,7 @@ proc _lappend_nice {cmd_var} {
621
}
622
623
proc git {args} {
624
- set fd [eval [list git_read] $args]
624
+ set fd [git_read $args]
625
fconfigure $fd -translation binary -encoding utf-8
626
set result [string trimright [read $fd] "\n"]
627
close $fd
@@ -642,34 +642,34 @@ proc _open_stdout_stderr {cmd} {
642
return $fd
643
}
644
645
-proc git_read {args} {
646
- set cmdp [_git_cmd [lindex $args 0]]
647
- set args [lrange $args 1 end]
645
+proc git_read {cmd} {
646
+ set cmdp [_git_cmd [lindex $cmd 0]]
647
+ set cmd [lrange $cmd 1 end]
648
649
- return [_open_stdout_stderr [concat $cmdp $args]]
649
+ return [_open_stdout_stderr [concat $cmdp $cmd]]
650
}
651
652
-proc git_read_nice {args} {
652
+proc git_read_nice {cmd} {
653
set opt [list]
654
655
_lappend_nice opt
656
657
- set cmdp [_git_cmd [lindex $args 0]]
658
- set args [lrange $args 1 end]
657
+ set cmdp [_git_cmd [lindex $cmd 0]]
658
+ set cmd [lrange $cmd 1 end]
659
660
- return [_open_stdout_stderr [concat $opt $cmdp $args]]
660
+ return [_open_stdout_stderr [concat $opt $cmdp $cmd]]
661
}
662
663
-proc git_write {args} {
664
- set cmdp [_git_cmd [lindex $args 0]]
665
- set args [lrange $args 1 end]
663
+proc git_write {cmd} {
664
+ set cmdp [_git_cmd [lindex $cmd 0]]
665
+ set cmd [lrange $cmd 1 end]
666
667
- _trace_exec [concat $cmdp $args]
668
- return [open [concat [list | ] $cmdp $args] w]
667
+ _trace_exec [concat $cmdp $cmd]
668
+ return [open [concat [list | ] $cmdp $cmd] w]
669
}
670
671
proc githook_read {hook_name args} {
672
- git_read hook run --ignore-missing $hook_name -- $args 2>@1
672
+ git_read [concat [list hook run --ignore-missing $hook_name --] $args 2>@1]
673
}
674
675
proc kill_file_process {fd} {
@@ -1110,10 +1110,10 @@ proc _parse_config {arr_name args} {
1110
array unset arr
1111
set buf {}
1112
catch {
1113
- set fd_rc [eval \
1114
- [list git_read config] \
1113
+ set fd_rc [git_read \
1114
+ [concat config \
1115
$args \
1116
- [list --null --list]]
1116
+ --null --list]]
1117
fconfigure $fd_rc -translation binary -encoding utf-8
1118
set buf [read $fd_rc]
1119
close $fd_rc
@@ -1482,12 +1482,12 @@ proc rescan {after {honor_trustmtime 1}} {
1482
} else {
1483
set rescan_active 1
1484
ui_status [mc "Refreshing file status..."]
1485
- set fd_rf [git_read update-index \
1485
+ set fd_rf [git_read [list update-index \
1486
-q \
1487
--unmerged \
1488
--ignore-missing \
1489
--refresh \
1490
- ]
1490
+ ]]
1491
fconfigure $fd_rf -blocking 0 -translation binary
1492
fileevent $fd_rf readable \
1493
[list rescan_stage2 $fd_rf $after]
@@ -1527,11 +1527,11 @@ proc rescan_stage2 {fd after} {
1527
set rescan_active 2
1528
ui_status [mc "Scanning for modified files ..."]
1529
if {[git-version >= "1.7.2"]} {
1530
- set fd_di [git_read diff-index --cached --ignore-submodules=dirty -z [PARENT]]
1530
+ set fd_di [git_read [list diff-index --cached --ignore-submodules=dirty -z [PARENT]]]
1531
} else {
1532
- set fd_di [git_read diff-index --cached -z [PARENT]]
1532
+ set fd_di [git_read [list diff-index --cached -z [PARENT]]]
1533
}
1534
- set fd_df [git_read diff-files -z]
1534
+ set fd_df [git_read [list diff-files -z]]
1535
1536
fconfigure $fd_di -blocking 0 -translation binary -encoding binary
1537
fconfigure $fd_df -blocking 0 -translation binary -encoding binary
@@ -1540,7 +1540,7 @@ proc rescan_stage2 {fd after} {
1540
fileevent $fd_df readable [list read_diff_files $fd_df $after]
1541
1542
if {[is_config_true gui.displayuntracked]} {
1543
- set fd_lo [eval git_read ls-files --others -z $ls_others]
1543
+ set fd_lo [git_read [concat ls-files --others -z $ls_others]]
1544
fconfigure $fd_lo -blocking 0 -translation binary -encoding binary
1545
fileevent $fd_lo readable [list read_ls_others $fd_lo $after]
1546
incr rescan_active
lib/blame.tcl
+5
-5
@@ -486,9 +486,9 @@ method _load {jump} {
486
fconfigure $fd -eofchar {}
487
} else {
488
if {$do_textconv ne 0} {
489
- set fd [git_read cat-file --textconv "$commit:$path"]
489
+ set fd [git_read [list cat-file --textconv "$commit:$path"]]
490
} else {
491
- set fd [git_read cat-file blob "$commit:$path"]
491
+ set fd [git_read [list cat-file blob "$commit:$path"]]
492
}
493
}
494
fconfigure $fd \
@@ -617,7 +617,7 @@ method _exec_blame {cur_w cur_d options cur_s} {
617
}
618
619
lappend options -- $path
620
- set fd [eval git_read_nice blame $options]
620
+ set fd [git_read_nice [concat blame $options]]
621
fconfigure $fd -blocking 0 -translation lf -encoding utf-8
622
fileevent $fd readable [cb _read_blame $fd $cur_w $cur_d]
623
set current_fd $fd
@@ -986,7 +986,7 @@ method _showcommit {cur_w lno} {
986
if {[catch {set msg $header($cmit,message)}]} {
987
set msg {}
988
catch {
989
- set fd [git_read cat-file commit $cmit]
989
+ set fd [git_read [list cat-file commit $cmit]]
990
fconfigure $fd -encoding binary -translation lf
991
# By default commits are assumed to be in utf-8
992
set enc utf-8
@@ -1134,7 +1134,7 @@ method _blameparent {} {
1134
} else {
1135
set diffcmd [list diff-tree --unified=0 $cparent $cmit -- $new_path]
1136
}
1137
- if {[catch {set fd [eval git_read $diffcmd]} err]} {
1137
+ if {[catch {set fd [git_read $diffcmd]} err]} {
1138
$status_operation stop [mc "Unable to display parent"]
1139
error_popup [strcat [mc "Error loading diff:"] "\n\n$err"]
1140
return
lib/branch.tcl
+3
-3
@@ -7,7 +7,7 @@ proc load_all_heads {} {
7
set rh refs/heads
8
set rh_len [expr {[string length $rh] + 1}]
9
set all_heads [list]
10
- set fd [git_read for-each-ref --format=%(refname) $rh]
10
+ set fd [git_read [list for-each-ref --format=%(refname) $rh]]
11
fconfigure $fd -translation binary -encoding utf-8
12
while {[gets $fd line] > 0} {
13
if {!$some_heads_tracking || ![is_tracking_branch $line]} {
@@ -21,10 +21,10 @@ proc load_all_heads {} {
21
22
proc load_all_tags {} {
23
set all_tags [list]
24
- set fd [git_read for-each-ref \
24
+ set fd [git_read [list for-each-ref \
25
--sort=-taggerdate \
26
--format=%(refname) \
27
- refs/tags]
27
+ refs/tags]]
28
fconfigure $fd -translation binary -encoding utf-8
29
while {[gets $fd line] > 0} {
30
if {![regsub ^refs/tags/ $line {} name]} continue
lib/browser.tcl
+1
-1
@@ -196,7 +196,7 @@ method _ls {tree_id {name {}}} {
196
lappend browser_stack [list $tree_id $name]
197
$w conf -state disabled
198
199
- set fd [git_read ls-tree -z $tree_id]
199
+ set fd [git_read [list ls-tree -z $tree_id]]
200
fconfigure $fd -blocking 0 -translation binary -encoding utf-8
201
fileevent $fd readable [cb _read $fd]
202
}
lib/checkout_op.tcl
+5
-5
@@ -304,12 +304,12 @@ The rescan will be automatically started now.
304
_readtree $this
305
} else {
306
ui_status [mc "Refreshing file status..."]
307
- set fd [git_read update-index \
307
+ set fd [git_read [list update-index \
308
-q \
309
--unmerged \
310
--ignore-missing \
311
--refresh \
312
- ]
312
+ ]]
313
fconfigure $fd -blocking 0 -translation binary
314
fileevent $fd readable [cb _refresh_wait $fd]
315
}
@@ -345,7 +345,7 @@ method _readtree {} {
345
[mc "Updating working directory to '%s'..." [_name $this]] \
346
[mc "files checked out"]]
347
348
- set fd [git_read read-tree \
348
+ set fd [git_read [list read-tree \
349
-m \
350
-u \
351
-v \
@@ -353,7 +353,7 @@ method _readtree {} {
353
$HEAD \
354
$new_hash \
355
2>@1 \
356
- ]
356
+ ]]
357
fconfigure $fd -blocking 0 -translation binary
358
fileevent $fd readable [cb _readtree_wait $fd $status_bar_operation]
359
}
@@ -573,7 +573,7 @@ method _confirm_reset {cur} {
573
pack $w.buttons.cancel -side right -padx 5
574
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
575
576
- set fd [git_read rev-list --pretty=oneline $cur ^$new_hash]
576
+ set fd [git_read [list rev-list --pretty=oneline $cur ^$new_hash]]
577
while {[gets $fd line] > 0} {
578
set abbr [string range $line 0 7]
579
set subj [string range $line 41 end]
lib/choose_repository.tcl
+4
-4
@@ -818,9 +818,9 @@ method _clone_refs {} {
818
error_popup [mc "Not a Git repository: %s" [file tail $origin_url]]
819
return 0
820
}
821
- set fd_in [git_read for-each-ref \
821
+ set fd_in [git_read [list for-each-ref \
822
--tcl \
823
- {--format=list %(refname) %(objectname) %(*objectname)}]
823
+ {--format=list %(refname) %(objectname) %(*objectname)}]]
824
cd $pwd
825
826
set fd [safe_open_file [gitdir packed-refs] w]
@@ -953,14 +953,14 @@ method _do_clone_checkout {HEAD} {
953
[mc "files"]]
954
955
set readtree_err {}
956
- set fd [git_read read-tree \
956
+ set fd [git_read [list read-tree \
957
-m \
958
-u \
959
-v \
960
HEAD \
961
HEAD \
962
2>@1 \
963
- ]
963
+ ]]
964
fconfigure $fd -blocking 0 -translation binary
965
fileevent $fd readable [cb _readtree_wait $fd]
966
}
lib/choose_rev.tcl
+3
-3
@@ -146,14 +146,14 @@ constructor _new {path unmerged_only title} {
146
append fmt { %(*subject)}
147
append fmt {]}
148
set all_refn [list]
149
- set fr_fd [git_read for-each-ref \
149
+ set fr_fd [git_read [list for-each-ref \
150
--tcl \
151
--sort=-taggerdate \
152
--format=$fmt \
153
refs/heads \
154
refs/remotes \
155
refs/tags \
156
- ]
156
+ ]]
157
fconfigure $fr_fd -translation lf -encoding utf-8
158
while {[gets $fr_fd line] > 0} {
159
set line [eval $line]
@@ -176,7 +176,7 @@ constructor _new {path unmerged_only title} {
176
close $fr_fd
177
178
if {$unmerged_only} {
179
- set fr_fd [git_read rev-list --all ^$::HEAD]
179
+ set fr_fd [git_read [list rev-list --all ^$::HEAD]]
180
while {[gets $fr_fd sha1] > 0} {
181
if {[catch {set rlst $cmt_refn($sha1)}]} continue
182
foreach refn $rlst {
lib/commit.tcl
+3
-3
@@ -27,7 +27,7 @@ You are currently in the middle of a merge that has not been fully completed. Y
27
if {[catch {
28
set name ""
29
set email ""
30
- set fd [git_read cat-file commit $curHEAD]
30
+ set fd [git_read [list cat-file commit $curHEAD]]
31
fconfigure $fd -encoding binary -translation lf
32
# By default commits are assumed to be in utf-8
33
set enc utf-8
@@ -325,7 +325,7 @@ proc commit_commitmsg_wait {fd_ph curHEAD msg_p} {
325
326
proc commit_writetree {curHEAD msg_p} {
327
ui_status [mc "Committing changes..."]
328
- set fd_wt [git_read write-tree]
328
+ set fd_wt [git_read [list write-tree]]
329
fileevent $fd_wt readable \
330
[list commit_committree $fd_wt $curHEAD $msg_p]
331
}
@@ -350,7 +350,7 @@ proc commit_committree {fd_wt curHEAD msg_p} {
350
# -- Verify this wasn't an empty change.
351
#
352
if {$commit_type eq {normal}} {
353
- set fd_ot [git_read cat-file commit $PARENT]
353
+ set fd_ot [git_read [list cat-file commit $PARENT]]
354
fconfigure $fd_ot -encoding binary -translation lf
355
set old_tree [gets $fd_ot]
356
close $fd_ot
lib/console.tcl
+1
-1
@@ -93,7 +93,7 @@ method _init {} {
93
method exec {cmd {after {}}} {
94
lappend cmd 2>@1
95
if {[lindex $cmd 0] eq {git}} {
96
- set fd_f [eval git_read [lrange $cmd 1 end]]
96
+ set fd_f [git_read [lrange $cmd 1 end]]
97
} else {
98
set fd_f [_open_stdout_stderr $cmd]
99
}
lib/database.tcl
+1
-1
@@ -3,7 +3,7 @@
3
4
proc do_stats {} {
5
global use_ttk NS
6
- set fd [git_read count-objects -v]
6
+ set fd [git_read [list count-objects -v]]
7
while {[gets $fd line] > 0} {
8
if {[regexp {^([^:]+): (\d+)$} $line _ name value]} {
9
set stats($name) $value
lib/diff.tcl
+4
-4
@@ -338,7 +338,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
338
}
339
}
340
341
- if {[catch {set fd [eval git_read_nice $cmd]} err]} {
341
+ if {[catch {set fd [git_read_nice $cmd]} err]} {
342
set diff_active 0
343
unlock_index
344
ui_status [mc "Unable to display %s" [escape_path $path]]
@@ -617,7 +617,7 @@ proc apply_or_revert_hunk {x y revert} {
617
618
if {[catch {
619
set enc [get_path_encoding $current_diff_path]
620
- set p [eval git_write $apply_cmd]
620
+ set p [git_write $apply_cmd]
621
fconfigure $p -translation binary -encoding $enc
622
puts -nonewline $p $wholepatch
623
close $p} err]} {
@@ -853,7 +853,7 @@ proc apply_or_revert_range_or_line {x y revert} {
853
854
if {[catch {
855
set enc [get_path_encoding $current_diff_path]
856
- set p [eval git_write $apply_cmd]
856
+ set p [git_write $apply_cmd]
857
fconfigure $p -translation binary -encoding $enc
858
puts -nonewline $p $current_diff_header
859
puts -nonewline $p $wholepatch
@@ -890,7 +890,7 @@ proc undo_last_revert {} {
890
891
if {[catch {
892
set enc $last_revert_enc
893
- set p [eval git_write $apply_cmd]
893
+ set p [git_write $apply_cmd]
894
fconfigure $p -translation binary -encoding $enc
895
puts -nonewline $p $last_revert
896
close $p} err]} {
lib/index.tcl
+4
-4
@@ -75,7 +75,7 @@ proc update_indexinfo {msg path_list after} {
75
if {$batch > 25} {set batch 25}
76
77
set status_bar_operation [$::main_status start $msg [mc "files"]]
78
- set fd [git_write update-index -z --index-info]
78
+ set fd [git_write [list update-index -z --index-info]]
79
fconfigure $fd \
80
-blocking 0 \
81
-buffering full \
@@ -144,7 +144,7 @@ proc update_index {msg path_list after} {
144
if {$batch > 25} {set batch 25}
145
146
set status_bar_operation [$::main_status start $msg [mc "files"]]
147
- set fd [git_write update-index --add --remove -z --stdin]
147
+ set fd [git_write [list update-index --add --remove -z --stdin]]
148
fconfigure $fd \
149
-blocking 0 \
150
-buffering full \
@@ -218,13 +218,13 @@ proc checkout_index {msg path_list after capture_error} {
218
if {$batch > 25} {set batch 25}
219
220
set status_bar_operation [$::main_status start $msg [mc "files"]]
221
- set fd [git_write checkout-index \
221
+ set fd [git_write [list checkout-index \
222
--index \
223
--quiet \
224
--force \
225
-z \
226
--stdin \
227
- ]
227
+ ]]
228
fconfigure $fd \
229
-blocking 0 \
230
-buffering full \
lib/merge.tcl
+1
-1
@@ -239,7 +239,7 @@ Continue with resetting the current changes?"]
239
}
240
241
if {[ask_popup $op_question] eq {yes}} {
242
- set fd [git_read read-tree --reset -u -v HEAD 2>@1]
242
+ set fd [git_read [list read-tree --reset -u -v HEAD 2>@1]]
243
fconfigure $fd -blocking 0 -translation binary
244
set status_bar_operation [$::main_status \
245
start \
lib/mergetool.tcl
+1
-1
@@ -88,7 +88,7 @@ proc merge_load_stages {path cont} {
88
set merge_stages(3) {}
89
set merge_stages_buf {}
90
91
- set merge_stages_fd [eval git_read ls-files -u -z -- {$path}]
91
+ set merge_stages_fd [git_read [list ls-files -u -z -- $path]]
92
93
fconfigure $merge_stages_fd -blocking 0 -translation binary -encoding binary
94
fileevent $merge_stages_fd readable [list read_merge_stages $merge_stages_fd $cont]
lib/remote.tcl
+1
-1
@@ -32,7 +32,7 @@ proc all_tracking_branches {} {
32
}
33
34
if {$pat ne {}} {
35
- set fd [eval git_read for-each-ref --format=%(refname) $cmd]
35
+ set fd [git_read [concat for-each-ref --format=%(refname) $cmd]]
36
while {[gets $fd n] > 0} {
37
foreach spec $pat {
38
set dst [string range [lindex $spec 0] 0 end-2]
lib/remote_branch_delete.tcl
+1
-1
@@ -308,7 +308,7 @@ method _load {cache uri} {
308
set full_list [list]
309
set head_cache($cache) [list]
310
set full_cache($cache) [list]
311
- set active_ls [git_read ls-remote $uri]
311
+ set active_ls [git_read [list ls-remote $uri]]
312
fconfigure $active_ls \
313
-blocking 0 \
314
-translation lf \