twitcode #4: reverse diff — using the right tool for the job
Mercurial’s hg diff command supports a --reverse option which shows the regular diff output except it reverses the sense of the comparison — i.e., it goes from the “destination” to the “source” (git diff supports this action too, but as the flag “-R”). Most of the time you want the ordinary “forward” sense, but occasionally the reverse sense comes in handy, and that’s why that option’s there. On rare occasion, I’ll even want to do this to files not under version control, but the regular system diff
doesn’t support this feature.
So, after hitting this deficiency again recently, I decided to write up my own reverse-diff command which would swap its last two arguments and call diff. I started with the shell, as dealing with command arguments and calling programs is its forte. But it turned out to be surprisingly difficult to do stuff like copy the argument list or mess around with the end and near-end of the argument list, which I thought would be dead-simple operations. After futzing around with shell variables and parameters and the various options for variable/parameter expansion for something like 25 minutes, I came to my senses and did it in something like two minutes using C, where nothing’s going to interpret any kind of data as anything unless you explicitly request it to, and array manipulation is built in with clean syntax. All I had to do was swap argv[argc-1]
and argv[argc-2]
then execvp("diff", argv)
, easy peasy.
And if I golf argc
and argv
into c
and v
, then it fits in 130 chars [source]:
#include <unistd.h>
int main(int c, char**v) {
if (c>2) { char*t=v[c-2]; v[c-2]=v[c-1]; v[c-1]=t; }
return execvp("diff", v);
}
I could probably omit the check for ≥2 arguments, as the system diff doesn’t support the convention that a missing file argument means to use stdin
(instead, it treats a filename of -
(single hyphen) as representing stdin
), but perhaps it’ll be used by somebody who’s installed an enhanced diff program.
I’m also amused that each of my “twitcodes” has been in a different language: shell, perl, python, and now C.