Emacs/Perforce integration: back from the dead


p4.el, the Emacs/Perforce Integration, provides an interface to the Perforce software version management system from the Emacs text editor. Written originally by Eric Promislow, with important contributions from Rajesh Vaidheeswarran, Peter Österlund, and many others, it’s a piece of software that I have used more or less every day for the last thirteen years.

However, the SourceForge repository hasn’t seen any development since 20051, and it has been looking a bit ragged around the edges for a few years now. Perforce has acquired many useful new features in the last eight years: annotate -i in 2005.2, move in 2009.1, shelve and unshelve in 2009.2, grep in 2010.1, annotate -I and copy in 2010.2, sync -s and streams in 2011.1, and status, reconcile and populate in 2012.1. But more importantly, we’re now making much more serious use of the Internet for software development than we were ten years ago. When p4.el was first written back in 1996 or so, it was reasonable to assume that the Perforce server was on a local network, and therefore that it would be fine to perform frequent operations, like checking to see if a visited file is under the control of Perforce, synchronously with respect to the Emacs user interface. Sure, Emacs will hang if the Perforce server is unavailable (at least until the network connection times out after thirty seconds or so), but how often does that happen? The Perforce server is very reliable, and hardly ever goes down.

But nowadays, your Perforce server is on the other side of the world, and you’re accessing it via a VPN from your laptop on the train over a mobile data connection that drops every time the train goes into a tunnel. Even though these circumstances are admittedly somewhat trying for networking applications, it’s still completely unacceptable for Emacs to hang for thirty seconds every time you open a file.2

So finally I lost patience with this state of affairs, and I’ve forked p4.el on github, and I’m gradually fixing it. At this stage I think it’s too unstable to recommend for everyone, but if you’re a p4.el user who’s frustrated with the hangs and missing features, and you’re expert enough to cope with it being a bit buggy, then I’d be grateful if you could download a copy, try it out, and report problems (or better still, fork the repository and send me pull requests for your bug fixes). I use GNU Emacs 24.3 on OS X, Windows 7, FreeBSD and Ubuntu, but I don’t propose to put any work into ensuring that p4.el runs on any other versions of Emacs or any other operating systems. In particular, I’m likely to break XEmacs compatibility unless someone keeps me honest.

I’ve made many improvements to the code, but the most important are as follows:

  1. You no longer lose unsaved changes in a buffer when you run the p4-edit command. Instead, you are prompted as to whether you want to revert the buffer. A warning about this bug was right there near the top of p4.el for at least the last ten years:

    ;; WARNING:
    ;; --------
    ;;    % p4 edit foo.c
    ;;    ... make changes to foo.c in emacs
    ;;    % p4 submit
    ;;     ... keep the writable copy of foo.c in emacs.  Start making changes
    ;;     to it.  Discover that you can't save it.  If you do M-x:p4-edit,
    ;;     you'll lose your changes.  You need to do a 'p4 edit' at the
    ;;     command-line.

    This was a horrible misfeature, because in situations where you have the “writable on client” flag turned on your Perforce client workspace, it’s completely natural to start editing the file, and only later remember that you should have opened it for edit. If you forgot to save before running p4-edit, then you lost your work.

  2. If you are logged out of Perforce, then nearly all3 Emacs commands that run a Perforce command will prompt you to log in, and then automatically re-run the Perforce command that failed.

  3. The “mode check”—that is, the check, when you open a file, to see whether that file is under control of Perforce, so that the mode line can be updated, and menu options can be enabled or disabled—now runs quietly (that is, it never bothers you, even if there are errors) and asynchronously with respect to the Emacs user interface. This means that if you are offline, or the Perforce server is otherwise unavailable, then Emacs no longer hangs each time you open a file, waiting for a network timeout to the Perforce server. And if you are logged out, then p4.el does not bother you for your Perforce password just for opening a file.

    (There is a user option, p4-do-find-file, that disables the mode check. I’ve left this user option in place because if you don’t use the menu, or don’t care about the mode line and the menu options being correctly updated, then you can avoid these queries to the Perforce server by disabling the option.)

  4. Many more user commands now run Perforce in the background.4

  5. When you revert a file with changes, you get shown the diffs that you are about to revert. (I got this excellent idea from the vc-revert command.)

  6. When you submit a changelist that includes a file that is open for edit but with no changes, p4.el prompts you “File with empty diff opened for edit. Submit anyway?” The file or files in question are now shown to you in a buffer, to avoid the awkward pause where you have to go away and try to figure out which file or files is being complained about. (This feature also now uses p4 diff -sr instead of plain p4 diff, so the check for empty diffs is much faster in situations when you have made many changes.)

  7. Errors from Perforce commands are shown to the user more reliably. There should be no need any more to switch to the *P4* buffer to try to figure out why your command didn’t work.

  8. The p4-blame command now uses p4 annotate -i -c if the server supports this, instead of working out the annotations by starting with the base revision, and patching it with each diff. It also caches the annotation strings instead of rebuilding them for each line. This makes it much faster on files with many revisions. For users on older servers the annotate-by-patching code still works, and now there are now progress messages to reassure you that the operation has not hung.

  1.  Fujii Hironori worked on it in 2009, adding major modes for the output buffers and modernizing the syntax highlighting and menus.

  2.  Sure, you can turn off the user option p4-do-find-file when you’re on the train and turn it back on again when you get back to the office. Or you can type C-g to abort the operation and then revisit the file. But life would be so much better if things like this worked smoothly out of the box without you having to nurse them along like this.

  3.  At the time of writing, p4-resolve was an exception, but I fixed this in commit 77904937.

  4.  Caveat: I’m not entirely certain if it’s wise for all user operations to run in the background. Initially I thought it was nice to be able to issue a big p4-describe or whatever and then immediately get on with some other work while the server chugged away processing my query. But then I found myself worrying about whether in fact it had succeeded, and going off to check the relevant buffer to see if it had failed for some reason. This despite having programmed it to always show me error messages, if there are any. So if you try out the new code, let me know what you think about this. Maybe there needs to be some kind of dashboard, if only to reassure you that nothing’s gone wrong?5

  5.  I later made the set of commands that run synchronously configurable (see commit fb87c2d4). Customize the variable p4-synchronous-commands accordingly.