Integrating xxdiff with scripts

Author: Martin Blais <blais@furius.ca>
Date: 2004-01-21

Abstract

A summary of some of the features and techniques that can be used to integrate xxdiff with your own homegrown programs.

Table of Contents

Introduction

xxdiff is built with integration in mind since the first version. It does not include builtin support for specific source control systems, such as CVS or ClearCase. Instead, its command-line interface is built so that it can easily be called in various ways within a workflow of file comparison, policing and review, and interactive merging of changes.

This approach has been used with success by the author in a variety of environments, with various revision control systems (CVS, ClearCase, others). This document aims at introducing these features and explaining how they are meant to be used.

Features and Techniques

Automatic Maximizing

Often xxdiff is used in a policing context, where the reviewer/"merge cop" will have to visualize a series of files one-by-one and make comments on each. Many people like to maximize their xxdiff to perform this arduous task. You can set the Geometry resource to special value Maximize for that purpose. (Note that you can also specify arbitraty resource strings on the command-line with the --resource option).

Reading Files from Stdin

Sometimes it can be convenient to use the output of a process directly as input for comparison, for example, something like this:

cat foo.c | sed -e 's/get_instance/getInstance/g' | xxdiff foo.c -

You can specify - in lieu of a filename on the xxdiff command-line to let it know to read standard input for that file position. (Internally, xxdiff will have to create a temporary file by itself to spawn GNU diff on it but you don't really need to know that.)

Note that xxdiff currently cannot read different files from different file descriptors, i.e. it can only read from stdin or files.

Adding Arbitraty Information to Filenames

In the xxdiff interface, the filename is shown over the corresponding file.

Often when calling xxdiff from a wrapper script, you will run xxdiff on a temporary file, or accepting input from stdin. It can also be that there is a special semantic associated with a particular file (e.g. "old" or "new" file), or that the file has been somehow manipulated automatically before being compared, or that it represents a specific revision. It is only natural that you would want to show this information in the graphical comparison program.

To that extent, xxdiff allows you to specify what information you want displayed over the file. Use the --title1, --title2 or --title3 options to have xxdiff display what you want it to.

Setting the Output Filename

Sometimes you may be invoking xxdiff with the intent of maybe getting a merged output file as a result. In order to specify where this result should lie, xxdiff provides the concept of "merged filename", which is the default location where it will save the results of user selections, the merged file. You can provide this filename on the command-line with the --merged-filename option.

Note that when a merged filename is specific on the command-line, xxdiff will not warn when overwriting that file. We assume that since you specify a particular file to be used for merged output, you expect it to be potentially overwritten.

Requesting Accept/Merge/Reject Decision

Sometimes you may want to force the user to produce a merged file as the result of file comparison. For this purpose, we provide the Decision or Accept/Merge/Reject mode in xxdiff, triggered with the --decision option.

In this mode, xxdiff will not let you exit normally. Instead:

  • if you press 'A', the file on the right will be saved as the merged file and ACCEPT will be printed on stdout;
  • if you press 'R', the file on the left will be saved as the merged file and REJECT will be printed on stdout;
  • if you press 'M', the results of user selections will be saved as the merged file and MERGED will be printed on stdout;

In all three cases, the merged file will be saved with the appropriate contents. Note that if xxdiff gets terminated otherwise (e.g. by the window manager), it will print out the string NODECISION.

The calling script can invoke xxdiff (specifying --merged-filename) and read its stdout to find out the result of the decision, and then pick up the merged file and do whatever is desired with it.

If you prefer to work with the mouse, three distinct buttons will appear on the toolbar for that purpose.

Indication of Input Processing Completion

In some circumstances, a calling script will generate temporary files for a short time, just to pass them on to xxdiff as input. If you want to delete those files as soon as possible, you may use the --indicate-input-processed option to xxdiff which will make it print the string 'INPUT-PROCESSED` as soon as it does not need its inputs anymore.

Thus you would do something like this:

  1. invoke xxdiff asynchrously (e.g. in a child process);
  2. read from its output (from a pipe), until the INPUT-PROCESSED string is seen;
  3. delete the input files;
  4. wait for xxdiff to complete.

Return Value

By default, xxdiff returns the same return value that GNU diff does (see diff(1)).

This behaviour is altered if you use the --exit-with-merge-status option: if all diff hunks are selected and no unsaved selections exist, only then xxdiff will exit with code of 0.

Conditional Display

If --exit-on-same is selected xxdiff does not show its UI and exits if the files are have no differences (according to GNU diff).

If --exit-if-no-conflicts is selected xxdiff does not show its UI and exits if automatic merging would result in no conflicts.

Examples

You can look at the various scripts available in the distribution in the bin directory or the tools directory. They are working examples of integration between xxdiff and Bourne-shell and Python scripts.