Skip to content

Commit fb0ca47

Browse files
committed
git-gui: Honor the standard commit-msg hook
Under core Git the git-commit tool will invoke the commit-msg hook if it exists and is executable to the user running git-commit. As a hook it has some limited value as it cannot alter the commit, but it can modify the message the user is attempting to commit. It is also able to examine the message to ensure it conforms to some local standards/conventions. Since the hook takes the name of a temporary file holding the message as its only parameter we need to move the code that creates the temp file up earlier in our commit code path, and then pass through that file name to the latest stage (where we call git-commit-tree). We let the hook alter the file as it sees fit and we don't bother to look at its content again until the commit succeeded and we need the subject for the reflog update. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
1 parent a028557 commit fb0ca47

File tree

1 file changed

+83
-31
lines changed

1 file changed

+83
-31
lines changed

lib/commit.tcl

Lines changed: 83 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,24 @@ A good commit message has the following format:
192192
return
193193
}
194194

195+
# -- Build the message file.
196+
#
197+
set msg_p [gitdir GITGUI_EDITMSG]
198+
set msg_wt [open $msg_p w]
199+
fconfigure $msg_wt -translation lf
200+
if {[catch {set enc $repo_config(i18n.commitencoding)}]} {
201+
set enc utf-8
202+
}
203+
set use_enc [tcl_encoding $enc]
204+
if {$use_enc ne {}} {
205+
fconfigure $msg_wt -encoding $use_enc
206+
} else {
207+
puts stderr [mc "warning: Tcl does not support encoding '%s'." $enc]
208+
fconfigure $msg_wt -encoding utf-8
209+
}
210+
puts $msg_wt $msg
211+
close $msg_wt
212+
195213
# -- Run the pre-commit hook.
196214
#
197215
set pchook [gitdir hooks pre-commit]
@@ -207,7 +225,7 @@ A good commit message has the following format:
207225
} elseif {[file executable $pchook]} {
208226
set pchook [list $pchook |& cat]
209227
} else {
210-
commit_writetree $curHEAD $msg
228+
commit_commitmsg $curHEAD $msg_p
211229
return
212230
}
213231

@@ -216,36 +234,87 @@ A good commit message has the following format:
216234
set fd_ph [open "| $pchook" r]
217235
fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
218236
fileevent $fd_ph readable \
219-
[list commit_prehook_wait $fd_ph $curHEAD $msg]
237+
[list commit_prehook_wait $fd_ph $curHEAD $msg_p]
220238
}
221239

222-
proc commit_prehook_wait {fd_ph curHEAD msg} {
240+
proc commit_prehook_wait {fd_ph curHEAD msg_p} {
223241
global pch_error
224242

225243
append pch_error [read $fd_ph]
226244
fconfigure $fd_ph -blocking 1
227245
if {[eof $fd_ph]} {
228246
if {[catch {close $fd_ph}]} {
247+
catch {file delete $msg_p}
229248
ui_status {Commit declined by pre-commit hook.}
230249
hook_failed_popup pre-commit $pch_error
231250
unlock_index
232251
} else {
233-
commit_writetree $curHEAD $msg
252+
commit_commitmsg $curHEAD $msg_p
234253
}
235254
set pch_error {}
236255
return
237256
}
238257
fconfigure $fd_ph -blocking 0
239258
}
240259

241-
proc commit_writetree {curHEAD msg} {
260+
proc commit_commitmsg {curHEAD msg_p} {
261+
global pch_error
262+
263+
# -- Run the commit-msg hook.
264+
#
265+
set pchook [gitdir hooks commit-msg]
266+
267+
# On Cygwin [file executable] might lie so we need to ask
268+
# the shell if the hook is executable. Yes that's annoying.
269+
#
270+
if {[is_Cygwin] && [file isfile $pchook]} {
271+
set pchook [list sh -c [concat \
272+
"if test -x \"$pchook\";" \
273+
"then exec \"$pchook\" \"$msg_p\" 2>&1;" \
274+
"fi"]]
275+
} elseif {[file executable $pchook]} {
276+
set pchook [list $pchook $msg_p |& cat]
277+
} else {
278+
commit_writetree $curHEAD $msg_p
279+
return
280+
}
281+
282+
ui_status {Calling commit-msg hook...}
283+
set pch_error {}
284+
set fd_ph [open "| $pchook" r]
285+
fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
286+
fileevent $fd_ph readable \
287+
[list commit_commitmsg_wait $fd_ph $curHEAD $msg_p]
288+
}
289+
290+
proc commit_commitmsg_wait {fd_ph curHEAD msg_p} {
291+
global pch_error
292+
293+
append pch_error [read $fd_ph]
294+
fconfigure $fd_ph -blocking 1
295+
if {[eof $fd_ph]} {
296+
if {[catch {close $fd_ph}]} {
297+
catch {file delete $msg_p}
298+
ui_status {Commit declined by commit-msg hook.}
299+
hook_failed_popup commit-msg $pch_error
300+
unlock_index
301+
} else {
302+
commit_writetree $curHEAD $msg_p
303+
}
304+
set pch_error {}
305+
return
306+
}
307+
fconfigure $fd_ph -blocking 0
308+
}
309+
310+
proc commit_writetree {curHEAD msg_p} {
242311
ui_status {Committing changes...}
243312
set fd_wt [git_read write-tree]
244313
fileevent $fd_wt readable \
245-
[list commit_committree $fd_wt $curHEAD $msg]
314+
[list commit_committree $fd_wt $curHEAD $msg_p]
246315
}
247316

248-
proc commit_committree {fd_wt curHEAD msg} {
317+
proc commit_committree {fd_wt curHEAD msg_p} {
249318
global HEAD PARENT MERGE_HEAD commit_type
250319
global current_branch
251320
global ui_comm selected_commit_type
@@ -254,6 +323,7 @@ proc commit_committree {fd_wt curHEAD msg} {
254323

255324
gets $fd_wt tree_id
256325
if {[catch {close $fd_wt} err]} {
326+
catch {file delete $msg_p}
257327
error_popup [strcat [mc "write-tree failed:"] "\n\n$err"]
258328
ui_status {Commit failed.}
259329
unlock_index
@@ -276,6 +346,7 @@ proc commit_committree {fd_wt curHEAD msg} {
276346
}
277347

278348
if {$tree_id eq $old_tree} {
349+
catch {file delete $msg_p}
279350
info_popup [mc "No changes to commit.
280351
281352
No files were modified by this commit and it was not a merge commit.
@@ -288,24 +359,6 @@ A rescan will be automatically started now.
288359
}
289360
}
290361

291-
# -- Build the message.
292-
#
293-
set msg_p [gitdir COMMIT_EDITMSG]
294-
set msg_wt [open $msg_p w]
295-
fconfigure $msg_wt -translation lf
296-
if {[catch {set enc $repo_config(i18n.commitencoding)}]} {
297-
set enc utf-8
298-
}
299-
set use_enc [tcl_encoding $enc]
300-
if {$use_enc ne {}} {
301-
fconfigure $msg_wt -encoding $use_enc
302-
} else {
303-
puts stderr [mc "warning: Tcl does not support encoding '%s'." $enc]
304-
fconfigure $msg_wt -encoding utf-8
305-
}
306-
puts $msg_wt $msg
307-
close $msg_wt
308-
309362
# -- Create the commit.
310363
#
311364
set cmd [list commit-tree $tree_id]
@@ -314,6 +367,7 @@ A rescan will be automatically started now.
314367
}
315368
lappend cmd <$msg_p
316369
if {[catch {set cmt_id [eval git $cmd]} err]} {
370+
catch {file delete $msg_p}
317371
error_popup [strcat [mc "commit-tree failed:"] "\n\n$err"]
318372
ui_status {Commit failed.}
319373
unlock_index
@@ -326,16 +380,14 @@ A rescan will be automatically started now.
326380
if {$commit_type ne {normal}} {
327381
append reflogm " ($commit_type)"
328382
}
329-
set i [string first "\n" $msg]
330-
if {$i >= 0} {
331-
set subject [string range $msg 0 [expr {$i - 1}]]
332-
} else {
333-
set subject $msg
334-
}
383+
set msg_fd [open $msg_p r]
384+
gets $msg_fd subject
385+
close $msg_fd
335386
append reflogm {: } $subject
336387
if {[catch {
337388
git update-ref -m $reflogm HEAD $cmt_id $curHEAD
338389
} err]} {
390+
catch {file delete $msg_p}
339391
error_popup [strcat [mc "update-ref failed:"] "\n\n$err"]
340392
ui_status {Commit failed.}
341393
unlock_index

0 commit comments

Comments
 (0)