@matheusbsbs / matheus-bagliano / commits / fb0ca475c6
Fork 0

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>

Shawn O. Pearce committed Jan 20, 2008 at 14:11 UTC fb0ca475c6ab02eeeb8ca7f2c0558d64301a8800
1 file changed +83 -31
lib/commit.tcl
+83 -31
@@ -192,6 +192,24 @@ A good commit message has the following format:
192 return
193 }
194
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 +
213 # -- Run the pre-commit hook.
214 #
215 set pchook [gitdir hooks pre-commit]
@@ -207,7 +225,7 @@ A good commit message has the following format:
225 } elseif {[file executable $pchook]} {
226 set pchook [list $pchook |& cat]
227 } else {
210 - commit_writetree $curHEAD $msg
228 + commit_commitmsg $curHEAD $msg_p
229 return
230 }
231
@@ -216,21 +234,22 @@ A good commit message has the following format:
234 set fd_ph [open "| $pchook" r]
235 fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
236 fileevent $fd_ph readable \
219 - [list commit_prehook_wait $fd_ph $curHEAD $msg]
237 + [list commit_prehook_wait $fd_ph $curHEAD $msg_p]
238 }
239
222 -proc commit_prehook_wait {fd_ph curHEAD msg} {
240 +proc commit_prehook_wait {fd_ph curHEAD msg_p} {
241 global pch_error
242
243 append pch_error [read $fd_ph]
244 fconfigure $fd_ph -blocking 1
245 if {[eof $fd_ph]} {
246 if {[catch {close $fd_ph}]} {
247 + catch {file delete $msg_p}
248 ui_status {Commit declined by pre-commit hook.}
249 hook_failed_popup pre-commit $pch_error
250 unlock_index
251 } else {
233 - commit_writetree $curHEAD $msg
252 + commit_commitmsg $curHEAD $msg_p
253 }
254 set pch_error {}
255 return
@@ -238,14 +257,64 @@ proc commit_prehook_wait {fd_ph curHEAD msg} {
257 fconfigure $fd_ph -blocking 0
258 }
259
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} {
311 ui_status {Committing changes...}
312 set fd_wt [git_read write-tree]
313 fileevent $fd_wt readable \
245 - [list commit_committree $fd_wt $curHEAD $msg]
314 + [list commit_committree $fd_wt $curHEAD $msg_p]
315 }
316
248 -proc commit_committree {fd_wt curHEAD msg} {
317 +proc commit_committree {fd_wt curHEAD msg_p} {
318 global HEAD PARENT MERGE_HEAD commit_type
319 global current_branch
320 global ui_comm selected_commit_type
@@ -254,6 +323,7 @@ proc commit_committree {fd_wt curHEAD msg} {
323
324 gets $fd_wt tree_id
325 if {[catch {close $fd_wt} err]} {
326 + catch {file delete $msg_p}
327 error_popup [strcat [mc "write-tree failed:"] "\n\n$err"]
328 ui_status {Commit failed.}
329 unlock_index
@@ -276,6 +346,7 @@ proc commit_committree {fd_wt curHEAD msg} {
346 }
347
348 if {$tree_id eq $old_tree} {
349 + catch {file delete $msg_p}
350 info_popup [mc "No changes to commit.
351
352 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.
359 }
360 }
361
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 -
362 # -- Create the commit.
363 #
364 set cmd [list commit-tree $tree_id]
@@ -314,6 +367,7 @@ A rescan will be automatically started now.
367 }
368 lappend cmd <$msg_p
369 if {[catch {set cmt_id [eval git $cmd]} err]} {
370 + catch {file delete $msg_p}
371 error_popup [strcat [mc "commit-tree failed:"] "\n\n$err"]
372 ui_status {Commit failed.}
373 unlock_index
@@ -326,16 +380,14 @@ A rescan will be automatically started now.
380 if {$commit_type ne {normal}} {
381 append reflogm " ($commit_type)"
382 }
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
386 append reflogm {: } $subject
387 if {[catch {
388 git update-ref -m $reflogm HEAD $cmt_id $curHEAD
389 } err]} {
390 + catch {file delete $msg_p}
391 error_popup [strcat [mc "update-ref failed:"] "\n\n$err"]
392 ui_status {Commit failed.}
393 unlock_index