Smokes your problems, coughs fresh air.

Tag: svn (Page 2 of 2)

Using diff and patch to upgrade web application installations

Update (July 30, 2008): I added information about making sure that the patch was successful.

When you install a big-ass web application such as WordPress or MediaWiki, you usually end with a bunch of configuration files and customizations (skins/themes, extension/plugins, uploads, etc.). This makes upgrading the files that come with the application a bit tricky. There’s a simple solution, however, which work regardless of whether you use a revision control system or not.

First of all, you do, of course, always need a revision control system. I personally recommend Git or Subversion, which are both excellent tools. But, that’s not what this post is about. I’m going to use two simple tools which are uniformly available on all (Unixy) platforms: diff and patch.

The procedure is simple:

  1. Download the version of the application which you’re currently running. For our example, we pretend that this version is extracted into the directory webapp-1.4.3.

  2. Then, download the version to which you’d like to upgrade. (We’re assuming that this version is extracted into the webapp-1.6.2 directory.)

  3. Compare the two versions to create a patch file:

    $ diff --unified --recursive --new-file webapp-1.4.3 webapp-1.6.2 > webapp-upgrade.diff
    
  4. Apply the patch to the installation of said web app:

    $ cd webapp-installed
    $ patch --strip=1 --remove-empty-files < ../webapp-upgrade.diff || echo "Some failures!"
    

Check if everything was patched perfectly

Now, if the patch command returned a non-zero status (printing Some failures! in the above example), it's time to check which chunks of which files failed. Get a summary by searching all files with an .rej or a .orig suffix:

$ find . -name "*.rej"

After manually applying any failed hunks, what's left is to compare your directory containing the patched application to the directory with the contents of the new application archive which you've used to create the patch:

$ cd ..
$ diff --unified --recursive --new-file webapp-1.6.2 webapp-installed

Version management

Your upgrade is done. Now, if your using a revision control system, you just need to check in new files and check out deleted files. In Subversion, I do this quickly using the following command sequence:

$ svn status|sed -e '/^\?/!d; s/^\?//'|xargs svn add
$ svn status|sed -e '/^\!/!d; s/^\!//'|xargs svn del

If you'd been using Git, you could do this all a little bit more sophisticatedly, but my Git skills are not advanced enough to go around giving others advice. Also, it's nice to learn a generic method before learning more specific tools.

Upgraded WordPress from 2.1 to 2.3.1

I’m now on WordPress 2.3.1. It was about time too; I was still on 2.1.

Importing the tags from Ultimate Tag Warrior worked fine. Before upgrading and importing, I quickly patched my local version of WP with a little help from Subversion:

$ svn diff http://svn.automattic.com/wordpress/tags/2.1/ http://svn.automattic.com/wordpress/tags/2.3.1/ > wp.diff
$ blog.bigsmoke.us
$ patch --remove-empty-files -p0 < ../wp.diff
$ svn revert wp-config.php
$ svn add `svn status|grep '^?'|sed -e 's/\?//'`
$ svn rm `svn status|grep '^!'|sed -e 's/!//'`

Then, after a few changes to my template files to play nice with WP’s new built-in tagging system, everything was running again.

Replacing the trunk of a Subversion repository with a feature branch

For the Sicirec website, I use Subversion to track all changes. When working on big changes which take more than a day to implement, I follow the Feature Branches branching pattern. This pattern means that the trunk remains relatively stable and usable for everyday updates while I can climb in a feature branch whenever I want to work on the big new feature(s).

Subversion’s merge tracking is non-existent. This means that, when I climb from branch to trunk and back again a lot, I have to manually keep track of all the changes in trunk/ that I merged into the branch. Every one such change, once merged, loses much of its meaningful history unless I painstakingly merge all the commit messages of the patch into the message of the commit that I do after the merge.

Today, after having maintained a branch for months to keep it somewhat in sync with an every-changing trunk, I’m at the point of having to merge the branch back into trunk. This is rather nightmarish because there are bound to be the many merge conflicts that I already suffered whenever merging changes from the trunk into the branch and then multiplied some.

To avoid torture, I decided I’d rather just replace the trunk with my feature branch. This is especially attractive because I then retain the history of the branch which is a little more useful to me than the history of the trunk.

I googled around a bit and could find one thread discussing a similar problem. The solution proposed there seemed to involve a few too many steps for my taste, so I did the following:

# From the working copy of my branch:
$ svn del file:///repos/trunk -m "Temporarily deleted trunk."
$ svn mv file:///repos/branches/my_branch file:///repos/trunk -m "Moved /branches/my_branch to /trunk"
$ svn switch file:///repos/trunk 

That worked perfectly fine. (Except that I still want automatic merge tracking, dammit!)

Newer posts »

© 2024 BigSmoke

Theme by Anders NorenUp ↑