From 15196c30e37aa937b121abcd7d95d35e0b3350d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Pit--Claudel?= Date: Mon, 11 Jul 2016 01:47:01 +0200 Subject: [PATCH] Add notes about using `git bisect' to pinpoint Emacs bugs * admin/notes/bisecting: New file. * admin/notes/repo: Add pointer to admin/notes/bisecting. --- admin/notes/bisecting | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++ admin/notes/repo | 3 +- 2 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 admin/notes/bisecting diff --git a/admin/notes/bisecting b/admin/notes/bisecting new file mode 100644 index 0000000..4efb5cc --- /dev/null +++ b/admin/notes/bisecting @@ -0,0 +1,105 @@ +HOW TO USE GIT BISECT TO PINPOINT EMACS BUGS -*- outline -*- + +This documents explains how to use git bisect to find the commit that +introduced an Emacs bug. Bisecting works best if the bug is easy and +relatively quick to reproduce in a clean ‘emacs -Q’ instance. + +For general information about bisecting, use ‘M-x man git-bisect’. +This document contains quick-start instructions and Emacs-specific +tips. + +* Bisecting Emacs bugs + +First, find a recipe that reproduces the bug in emacs -Q. Then use +this recipe to locate a revision in which the bug doesn't happen. If +it's a new bug, a not-too-recent revision could do; otherwise, +checking for the bug previous releases of Emacs works well. + +Then, run the following command to start bisecting + + git bisect start + + is usually HEAD in practice. + +Git will then check out revisions between these two bounds,; at each +step, you need to run ‘git bisect good’ or ‘git bisect bad’ to inform +git of the status of the current revision: ‘bad’ if it has the bug; +good if it doesn't. + +If Emacs' build is broken in the current revision, use ‘git bisect +skip’ to move to a neighboring revision. + +** Automating ‘git bisect’ + +You can also write ‘git bisect run ’ to automate +the process. ‘’ should build Emacs, run your bug +reproduction test, and return 0 if the current revision is good, and 1 +otherwise. Returning 125 is equivalent to doing ‘git bisect skip’. + +Concretely, ‘’ usually looks like this: + + #!/usr/bin/env bash + + # Remove leftovers from previous runs + git clean -xfd > /dev/null + # Build Emacs and skip commit if build fails + (./autogen.sh && ./configure --cache-file=/tmp/emacs.config.cache && make -j4) || exit 125 + + # Reproduce the bug, writing output somewhere + src/emacs -Q -l "../reproduce-the-bug.el" || exit 125 + # Remove leftovers again + git clean -xfd > /dev/null + # Analyze output and produce exit code + cmp ../reference-output current-output + +Some caveats: + +- This script cleans Emacs' source directory with ‘git clean -xfd’, so + make sure your uncommitted changes are saved somewhere else. + +- You should produce the ‘../reproduce-your-bug.el’ script on your own + (it should check if the bug exists, and save a different output to a + file named ‘current-output’ based on the result of that check), as + well as a file ‘../reference-output’ containing the expected output + in the good case. + +** Using ‘git bisect’ to find display-related bugs + +Most bugs that manifest graphically can be checked for by +programmatically inspecting text properties, but some are only +apparent through visual inspection. Since building Emacs takes a long +time, it can be a pain to debug these manually. + +Fortunately, it's relatively easy to bisect such bugs automatically. +Use the following template for ‘../reproduce-the-bug.el’: + + (defun take-screenshot-and-exit (fname x y w h) + "Save a screenshot of Emacs as FNAME, then exit. + X and Y are the coordinates of the top-left point of the area of interest. + W, and H are its dimensions." + (let ((window-id (frame-parameter nil 'outer-window-id))) + (call-process "xwd" nil nil nil "-silent" "-id" window-id "-out" fname)) + (call-process "mogrify" nil nil nil fname "-crop" (format "%dx%d+%d+%d" w h x y)) + (kill-emacs)) + + (defun main () + ;; Reproduce your bug here + … + ;; Force a redisplay + (redisplay t) + ;; Insert rough X, Y, W, H values below + (run-with-timer 0 nil #'take-screenshot-and-exit "screenshot.xwd" … … … …)) + + (main) + +This script makes a screenshot of Emacs after reproducing your bug (if +‘xwd’ isn't available, you can use ImageMagick's ‘import’ tool, +passing it a ‘-window’ argument where ‘xwd’ wants ‘id’). Cropping the +image is useful to weed out unrelated display changes; try to include +only a small portion of the screen containing your bug. + +Then to produce the right exit code use ImageMagick's ‘identify’ tool: + + cmp <(identify -quiet -format "%#" "../screenshot.xwd") <(identify -quiet -format "%#" "../good.xwd") + +‘good.xwd’ should be the image produced by your script in the good state. diff --git a/admin/notes/repo b/admin/notes/repo index 3ab3da7..60373bd 100644 --- a/admin/notes/repo +++ b/admin/notes/repo @@ -114,8 +114,7 @@ again. * Bisecting -This is a semi-automated way to find the revision that introduced a bug. -Browse 'git help bisect' for technical instructions. +See admin/notes/bisecting. * Maintaining ChangeLog history -- 2.9.0