Q:

Subversion update externals to a date

I'm working on a large, established project under SVN control. Many parts of the code base are being checked out as externals, but are being actively worked on by other people.
I wanted to update my entire working copy, externals and all, so that it reflected the various repositories' HEADs at a specific point in time. My initial attempt was:
svn up -r'{20090324}'

This updates the current directory to the specified date, but updates all externals to the current date. Updating the externals one at a time works as expected.
I understand that due to the nature of externals, a single update couldn't work with a revision number, but why doesn't it work with a date?
What's the best way to achieve the point-in-time effect that I'm looking for, without having to maintain a script that hard-codes the various externals?
I'm running a Linux system.

A:

This is inefficient, in that it calls svn update more often than (usually) required.  Otherwise, it is short an sweet:
Unix:
find . -name .svn -execdir svn update -r {2010-08-30} \;

Windows:
forfiles /m .svn /s /c "cmd /c svn up -r {2010-08-30}"

A:

When using svn:externals, it is generally a bad idea to use an external without a revision number. It means that it becomes hard to correlate the version of the external with the version of the containing project; I know this the hard way, from trying to track down some history in a project that contained externals, and I would have to guess which revision corresponded to the revision in the containing project (sometimes it was earlier because someone had updated the external project and then updated the containing project, sometimes it was later because someone had edited files directly in the external checkout and then committed it).
Instead, as suggested by the tip box a couple paragraphs into the externals section in the subversion book, you should always commit externals with a revision number. That way, whenever you check out a particular revision of the containing project, the appropriate revision of the external will also be checked out. It does mean a little more work, as you have to update the revision number in the svn:externals property every time (we wrote a script to do it automatically), but in the long run it is a much better solution.
edit: Here is the skeleton of the script we used (a rake task) for conveniently updating the external and keeping everything in sync.
desc 'Update external for this project (rake update_external r=17789)'
task :update_external do |t|
  rev = ENV['r']
  rev =~ /^\d+$/ or raise "Invalid SVN revision number: r=<#{rev}>"

  # Update the project.
  sh "svn update"

  URL = 'svn+ssh://example.com/external/trunk'
  sh "svn propset svn:externals 'external -r#{rev} #{URL}' containing/directory"

  # Update again -- to put the externals back to the right revision.
  sh "svn update"
end

A:

This is the best solution to the problem I found to date (it's a tricky problem - subversions devs should fix it in the core). This example deals with mplayer in particular but you should easily see the logic.
; fetch the rev I want without including the externals
svn checkout -r "$REV" --ignore-externals \
    svn://svn.mplayerhq.hu/mplayer/trunk

; grab the date of that rev from the svn info output
DATE=`svn info trunk|sed -n '/^Last Changed Date/s/.*: \(.*\) (.*/\1/p'`

; fetch the externals using that date
svn checkout -r "{$DATE}" \
        svn://svn.mplayerhq.hu/ffmpeg/trunk/libavutil \
        svn://svn.mplayerhq.hu/ffmpeg/trunk/libavformat \
        svn://svn.mplayerhq.hu/ffmpeg/trunk/libavcodec \
        svn://svn.mplayerhq.hu/ffmpeg/trunk/libpostproc

