views:

123

answers:

1

I am not interested in any auto update solution, such as ClickOnce or the MS Updater Block. For anyone feeling the urge to ask why not: I am already using these and there is nothing wrong with them, I would just like to learn about any efficient alternatives.

I would like to publish patches = small differences that will modify existing files of the deployment with the smallest possible delta. Not only code needs to be patched, but also resource files. Patching the running code can be accomplished by maintaining two separate synchronized copies of the deployment (no on the fly changes to the running executable are required).

The application itself can be xcopy deployed (to avoid MSI auto-correcting the modified files or breaking ClickOnce signatures).

  • I would like to learn how to handle different versions of patches (e.g. there is a patch issued that fixes one error and later another patch that fixes another error (in the same file) - users may have any combination of these and there comes a third patch - in text files, this may be easy to implement, but how about executable files? (native Win32 code vs. .NET, any difference?)

  • If the first problem is too hard to solve or unsolvable for executables, I would like to at least learn if there is a solution that implements simple patching with serial revisions - in order to install revision 5, user must have all previous revisions installed to ensure validity of the deployment.

  • The patches can be issued as downloadable files from a website - no auto-patching functionality directly from a running application is required.

Are there any existing solutions to accomplish this?

NOTE: There are a few questions on SO that may seem like duplicates, but none with a good answer.

This question is about the Windows platform, preferably .NET.

So far, wyUpdate seems to fit this problem best. Still interested in alternatives.

+4  A: 

You will not be able to create one binary patch that can apply to multiple versions of the program, so the following scenario will not be possible:

      org+p1
     /      \
    + p1     +p2    <-- note, p2 is the same patch both places
   /          \
original       org+p1+p2
   \          /
    + p2     +p1    <-- ie. the p2 on this line is the same as the one above
     \      /
      org+p2

You will instead have this scenario:

      org v.2
     /      \
    +p1      +p4    <-- note, different patches now
   /          \
org v.1        org v.4
   \          /
    +p2      +p3
     \      /
      org v.3

You should easily see how complex this becomes if you want to allow your users to cherrypick the fixes they want to apply. Yes, this can be done with text files, after all, that's how branching and merging works with most source control tools, but they work on the basis that you can insert and delete stuff in files without compromising the rest of the file, and that doesn't work with an executable.

Note: A special case is fixes that replace bytes, but doesn't insert or delete anything from the file. As long as multiple such fixes doesn't overlap it would be possible to cherrypick which ones you want to apply. However, such patches are very rare.

You should, as you've hinted in your question, work with a serial timeline, possibly with single hotfixes to existing versions, so you might have this instead:

                                      +-- most up to date version
                                      |            
                                      v
org v.1         org v.3             org v.4
   \           /       \           /
    +p1       +p2       +p3       +p4
     \       /           \       /
      org v.2             org v.4
       \
        +p1.1
         \
          org v.2 hotfix 1

As for actual code, I have a diff/patch implementation, but it is probably far from optimal. It currently takes a lot of time to produce the patch files for any sizable file. The patches are fairly small, but I dare say other algorithms will produce better patches. Sample tests with bsdiff and bspatch produces smaller patches.

However, the code is here if you want to play with it. It is part of a larger class library and I can't remember how much of it (the rest of the library) you need to compile just the binary patch classes, but it's all there. The class you want to use is the Delta2 class.

Lasse V. Karlsen
Thanks for the detailed analysis and the link to your delta implementation. I will study the code and try to learn from that.
Marek