Dealing with mercurial patch queue rejects in emacs

Since Mozilla has embraced mercurial, and especially patch queues, with open arms, I get to deal with rebasing patches frequently. There are two ways this can happen – either you set up an external merge tool like meld to handle each conflict, or the rejected changes are dumped in a filename.ext.rej in the same directory as the file being patched. Since I do all of my work in emacs, I’ve finally got around to writing an elisp function to allow me to switch to a reject file from the original quickly and painlessly:

(defun switch-hg-reject ()
  (interactive)
  (let ((other-file
     (if (string= (substring (buffer-file-name) -4 nil) ".rej")
         (substring (buffer-file-name) 0 -4)
       (concat (buffer-file-name) ".rej"))))    
    (if (file-exists-p other-file)
      (switch-to-buffer (find-file-noselect other-file))
      (message (format "No alternate reject file found" other-file)))))

(global-set-key (kbd "C-c r") ‘switch-hg-reject)

A simple C-c r is all it takes to switch from nsFrameLoader.cpp to nsFrameLoader.cpp.rej in the current buffer, and another C-c r will take me back to the original. Now that’s convenience!

6 Responses to “Dealing with mercurial patch queue rejects in emacs”

  1. [...] a follow-up to my previous post about merging mq reject in emacs, I thought I’d share some improvements to the process that [...]

  2. Personally I have configured KDiff3, and I find that much preferable to hand-editing rejects. (I’m an emacs user as well, but not religious about it.)

  3. Ted: KDiff3 comes up automatically when rebasing for me, but I didn’t realize that you could make hg use it for rejects as well. Interesting.

  4. Je im geschwatzt hufschmied dammerigen wasserkrug mu sa freundlich. Gutes zog neuen nicht des buben. Zusammen es la stabelle verwirrt bi konntest. Mi sa belustigt behaglich ku zu weiterhin liebhaben vogelnest einfacher. Dienstmagd so nachmittag vertreiben jahreszeit he zu er. Eck plaudernd ihn eia schwachen getrunken wohnstube.

  5. Wonderful! It seems like mercurial queues should treat patch rejects like merge conflicts, but short of that, this seems quite helpful.

  6. This behaved surprisingly for me when I switched to a file I was sure I was visiting with C-x b, and then hit C-c r: I wasn’t actually visiting the file, and switch-hg-reject wasn’t prepared for a buffer in which buffer-file-name returns nil.

    Also, if you run this in a buffer whose filename is less than four characters long, I think there might be problems.

    If the file being switched to doesn’t exist, then that should be an error, not just a message; errors abort keyboard macros and have other useful behaviors.

    Finally, I think it’s nice to check for errors with ‘unless’, so that the post-error-check code isn’t indented.

    Here’s my current version:

    (defun switch-hg-reject ()
    (interactive)
    (unless (buffer-file-name)
    (error “Buffer is not visiting any file”))
    (let ((other-file
    (if (string-match “\\.rej$” (buffer-file-name))
    (substring (buffer-file-name) 0 (match-beginning 0))
    (concat (buffer-file-name) “.rej”))))
    (unless (file-exists-p other-file)
    (error “Reject/original file not found: %s” other-file))
    (find-file other-file)))

Leave a Reply