From bb565a03c35103c5ec60dd42582eafdbdc21b725 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, 107 insertions(+), 1 deletion(-)
create mode 100644 admin/notes/bisecting
diff --git a/admin/notes/bisecting b/admin/notes/bisecting
new file mode 100644
index 0000000..3a335a4
--- /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 automate git bisect to find the commit
+that introduced an Emacs bug. Bisecting automatically works best if
+the bug is easy and quick to reproduce in a clean âemacs -Qâ instance.
+
+For an Emacs-independent tutorial on bisecting, run âgit help bisectâ.
+
+* Automating âgit bisectâ
+
+Use âgit bisect run â to automate the bisecting
+process. ââ should build Emacs, run your bug
+reproduction test, and return 0 if the current revision is good, 1 if
+it's bad, and 125 to skip the current revision.
+
+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
+
+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 return the right error code
+ using â(kill-emacs EXIT-CODE)â).
+
+* Using âgit bisectâ to find display-related bugs
+
+** Ways to programmatically detect display bugs
+
+Most bugs that manifest graphically can be checked for by
+programmatically inspecting the following elements:
+
+- text properties
+- window-start and window-end
+- posn-at-point
+- pos-visible-in-window-p
+- frame-geometry
+- window--dump-frame
+- frame--size-history
+- display-monitor-attributes-list
+- C-u C-x =
+- trace-redisplay and trace-to-stderr
+- dump-glyph-matrix and dump-frame-glyph-matrix
+
+** When the above fails
+
+Some bugs are only apparent through visual inspection. Since building
+Emacs takes a long time, it can be a pain to debug these manually.
+
+If your display bug has a clear manifestation in a screenshot of a
+particular portion of Emacs display, and you have a program, like
+'xwd', that can capture the content of the Emacs frame, and also have
+ImageMagick installed, you can automate the comparison of the
+redisplay results to make the bisection process fully automatic.
+
+Use the following template for â../reproduce-the-bug.elâ: it requires
+ImageMagick (mogrify and identify) and xwd (if âxwdâ isn't available,
+you can use ImageMagick's âimportâ tool, passing it a â-windowâ
+argument where âxwdâ wants âidâ).
+
+ (defun image-checksum (img-fname)
+ "Compute a checksum of IMG-FNAME's image data."
+ (car (process-lines "identify" "-quiet" "-format" "%#" img-fname)))
+
+ (defun take-screenshot-and-exit (fname x y w h reference-fname)
+ "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. This function sets
+ Emacs' return code to 0 if the resulting screenshot matches
+ REFERENCE-FNAME, and 1 otherwise."
+ (let ((wid (frame-parameter nil 'outer-window-id))
+ (crop-spec (format "%dx%d+%d+%d" w h x y)))
+ (call-process "xwd" nil nil nil "-silent" "-id" wid "-out" fname)
+ (call-process "mogrify" nil nil nil fname "-crop" crop-spec))
+ (let ((same-picture (equal (image-checksum fname)
+ (image-checksum reference-fname))))
+ (kill-emacs (if same-picture 0 1))))
+
+ (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" ⦠⦠⦠⦠"reference-screenshot.xwd"))
+
+ (main)
+
+This script takes and crops a screenshot of Emacs after reproducing
+your bug, then compares the result to a reference (cropped)
+screenshot, and returns 0 if they match, and 1 otherwise. Cropping is
+useful to weed out unrelated display changes; try to include only a
+small portion of the screen containing your bug.
diff --git a/admin/notes/repo b/admin/notes/repo
index 3ab3da7..f169468 100644
--- a/admin/notes/repo
+++ b/admin/notes/repo
@@ -115,7 +115,8 @@ again.
* Bisecting
This is a semi-automated way to find the revision that introduced a bug.
-Browse 'git help bisect' for technical instructions.
+Browse 'git help bisect' and admin/notes/bisecting for technical
+instructions.
* Maintaining ChangeLog history
--
2.7.4