How to apply changes in a framework to a versioned copy of it

2006-11-14 11:53:04 UTC

In Adium 1.0, we’ll have a number of external frameworks:

So whenever any of these frameworks changes — especially if it fixes a bug that we’ve been suffering from — we build the framework in our copy of their source code, and then we drop the new built framework into our source repo and commit it.

But I often see it done this way:

  1. svn rm Foo.framework
  2. svn ci Foo.framework
  3. cp -R ../../Foo/build/Release/Foo.framework Foo.framework
  4. svn add Foo.framework
  5. svn ci Foo.framework

This is wrong, for three reasons:

  • Commit history for the framework is lost. svn doesn’t relate the new framework to the old framework that previously occupied the same path.
  • Much space and bandwidth is wasted as all of the files in the framework (including nibs, images, plists) are copied yet again, even those that were not changed.
  • It takes two commits to do one job.

Here’s a better way.

  1. pushd ../../Foo/build/Release
  2. tar cf Foo-framework.tar Foo.framework
  3. mv Foo-framework.tar $OLDPWD
  4. popd
  5. tar xf Foo-framework.tar && rm Foo-framework.tar
  6. svn ci Foo.framework

tar will overwrite every file in the framework, and of course any new ones will be created. A quick svn st will show you which files are new (unversioned) or modified; if there are any unversioned files, you should of course svn add them before committing. And then when you commit, the commit history of all the files is preserved, so you can do svn log (or the equivalent operation in Trac) later, and svn will apply its own smarts about exactly what should be copied.

The only downside to this approach is that any files that no longer exist in the old framework won’t be removed. If you have reason to believe that any files were deleted, you should perform ls -R on both directories, diff -u the two results, and look for “-” lines. But most of the time, this isn’t necessary; how often does anything ever get removed from a framework?

So, anyway, please use tar, for the sake of the commit history. ☺

UPDATE 11:55: If you want an example, here’s Adium changeset number 18243, in which I did this to the LMX framework. See how small that changeset is?

UPDATE 14:08: Fixed SparklePlus link.

5 Responses to “How to apply changes in a framework to a versioned copy of it”

  1. Tom Harrington Says:

    The link to SparklePlus is incorrect, the Google Code page is actually just a set of links back to the actual project home. SparklePlus is hosted by ironcoder.org and its home is at http://macsb.ironcoder.org/wiki/index.php?title=SparklePlus.

  2. ken Says:

    Bill Bumgarner has written about the use of tar with version control a whole bunch.

    http://svn.haxx.se/dev/archive-2003-02/1485.shtml
    http://www.friday.com/bbum/2006/08/14/tar-wrappers-in-subversion/

    Synopsis: Danger, danger!

  3. Peter Hosey Says:

    Ken: That’s talking about versioning the tar archive, which is not what I’m doing here.

  4. ken Says:

    Ah, so. ditto’d probably do the trick too.

  5. Daryle Walker Says:

    There’s no kewl UN*X command that can sync two directories? I think there are GUI-level programs that can do this, but I can’t recall them right now. For the CLI side, could rsync do it? Looking around with Google, there’s “rsync –archive –verbose /path/to/source /path/to/destination”, with an optional “–delete” to propagate removals.

Leave a Reply

Do not delete the second sentence.