Skip to content
A scene from Ireland

vpatch design notes

In my Linux kernel development work, I often apply patches to files that have changed since the patch was created. Sometimes these patches fail to apply for trivial reasons.

About a year ago I wrote a program called to help apply these patches, and it has been very useful. However the solution isn't perfect. The problem is that I cannot see what is going on.

When I apply a patch that fails, I would like to be able to see exactly why it failed, and what wiggle would do to fix it. But to do that I currently have to grovel around in various files. I would be nice if this was more automatic.

What I am envisaging is a new patch application tool. Let's call it vpatch.

VPATCH

Vpatch would be given a patch file and would allow it's effect, both successful and not, to be visualised. There would be some limited editing capability to be able to pick up the pieces when a patch application goes awry.

When you run vpatch (in visualising mode) it finds all the files to be patches, attempts to apply the patches, and records the result. It then displays an initial screen that lists the files, and brief statistics about application. This would include the number of successful chunks, the number of successfully wiggled chunks, and the number of chunks with unresolvable conflicts.

A file can be selected, and then the display will change to list the chunks in that file. This can be limited to only display chunks that failed in some way. Each chunk will be listed with line numbers, function name (similar to --show-c-function in diff), and status.

When a chunk is selected, the actual file content is displayed. This is the tricky bit, so this will need to be the clever bit.

difference display

There are four different pieces of text that might need to be displayed: The text in the original file, the text in the 'before' part of the patch, the text in the 'after' part of the patch, and the text in the resulting file.

When a perfect match is found for the 'before' part, then showing the 'before' in the 'original' is trivial - the "rest" is highlighted somehow. In this case, the 'after' part of the result is similarly trivial to display. All the text can be displayed in one pane using three different styles, one for common text, one for deleted text, and one for added text. In some cases it might be better to display in two separate panes, one for before and one for after, but with the same highlighting. This is a common approach for displaying differences.

But what do we do when there is not a perfect match? I find that in this case I usually want to see exactly the patch, and to have a similar view of the result. This would seem to suggest there be two pains, one showing the patch as a merged, highlighted diff, and one showing the original and the result as a merged highlighted diff. It would probably be good to have a fourth highlight. They would be:

  • text that is common in call 4
  • text that is changed by the diff
  • text that is the result of the diff
  • text that is unchanged by the diff, but is not matched by the diff

Given this display, we need to know how to help resolve unresolved differences, and how to correct incorrectly resolved differences.

editting the diff

When an unresolved difference is found, it can sometimes be very hard for wiggle to find where the difference is meant to be applied. In this case, the "I found this but" section is much bigger than the "I wanted to change this" and the "to this" sections. In this case, it would be good to be able to refine the target section. This might involve a keystroke which moves either the start or the end of that secion to the current point. When this happens, the difference should be re-wiggled into the new section to see if it matches any better. Note that it should be possible to move the range to a completely different part of the file.

This should deal with a common problem where the precise place of an insertion cannot be determined. Once the position has been localised, the insertion becomes trivial.

Another sort of editting that might be useful is to edit either the "I found this but" bit or the "I wanted to change this" bit until they match better. When this is done (using simple insertions or deletions) it should be possible to request a reapplication of the difference.

Finally it might be necessary just to edit the "I found this but" bit and discard the other two bits.

General commands

I probably want to be emacs compatable and vi compatable.

Maybe I should just write this as a mode in one or both editors, but I'm not convinced that is a good idea.

vim has "vimdiff" which does a lot of the work, but I really want something more than that. Emacs does have a patch mode that is quite useful, but much as I like emacs, I hate programming in EMACS lisp, and I would need to do that to get the features that I want.

I would rather program in C (or maybe python...) so I think I'll just use ncurses and make it a simple command-line tool.

Anyway, I do want it to be reasonably compatable with both command sets as far as that is possible. But first let's focus on the commands.

In the lists of files and of chunks, we need to be able to move up and down, scroll, refresh, hide various types of entries, select a particular entry, and (in the case of a list of chunks) move to the next (unhidden) file.

In the display of a chunk we need to switch between different views (single view, before and after, or original and revised patch), switch between different windowing (horizontal or vertical). We need to be able to move char, line or word, and to scroll and refresh. We need to be able to move the match range of the current chunk, retry matching, and just edit the content.

Editting is simple insert and delete.

I need a more organised list of these.

Data structures

We do not try to store the whole patch in memory and certainly not all files. When vpatch starts, it reads the patch one file at a time, remembers its location in the file, and applies the patch producing a ".new" file. We keep the file names, number of chunks, and successfullness of the chunks in a list for displaying.

When a file is selected, the original file is loaded and the patch is reapplied yielding a list of chunks.

We first process a file into a sequence of lines and convert the patch into line based information, and look for matches. Remaining sections between successful matches are broken into words and the match is attempted again. These matches are stored as lists of indexes into the word list.