
Often if you see a block diagram like this, what comes to mind is a
compatability layer in between a program and several operating systems.
Generally something that's general-purpose like java, or a web browser, or
a widget toolkit.
-------------
-------------
-------------
-------------
(Generally it's drawn up all purty, but I'm lame.)
But lately I've seen and written a lot of code where the diagram is more
complex:
-------------
program
-------------
V C S
-------------
OS
-------------
Sometimes the program code is littered with multiple switch statements, as
in
debcheckout,
debcommit, and
etckeeper.
case "$vcs" in
git)
svn)
hg)
esac
Sometimes it pushes the VCS-specific code into modules.
use IkiWiki::Rcs::$rcs;
rcs_commit();
But if it does, these modules are specific to that one program. This isn't
a general-purpose library.
dpkg source v3
doesn't need to use the VCS is the same way as
ikiwiki, and even
ikiwiki's
rcs_commit is very specific to ikiwiki, in its error handling,
conflict resolution, locking, etc.
pristine-tar injects and extracts data directly from git, using
low-level git plumbing, in a way that probably can't be done at all with
other VCSes. But even as I was adding that low-level, very git-specific
code into pristine-tar, I found myself writing it with future portability
in mind.
if ($vcs eq 'git')
# git write-tree, git update-index, and other fun
else
die "unsupported vcs $vcs";
When Avery Pennarun talks about
git being the next unix,
he's talking about programs like these, that build on top of a VCS.
But if git is the next unix, then so is mercurial, so is darcs,
so is bzr, so too even svn (unless it's Windows?). In other words,
we're back to the days when every program had to be ported to a bunch of
incompatible and not-quite-compatible operating systems. Back to the
unix wars.
In Elija's discussion of the
"limbo" VCS state
he gives several great examples of how multiple VCSes that each seem on the
surface to offer similar commands like "$vcs add" and "$vcs commit" can
behave very differently.
echo 1 > foo
$vcs add foo
echo 2 > foo
$vcs commit
What was committed, "1" or "2"? Depends on which
$vcs you use.
Compare with unix where
open(2) always opens a file, perhaps with
different options, or different handling of large files, but portably
enough that you generally don't need to worry about it. Even if you're
porting to Windows, you can probably get away with a compatability layer to
call whatever baroque monstrosity Windows uses to open a file, and emulate
open(2) close enough to not have to worry about it most of the time.
A thin compatability layer that calls "$vcs add" isn't very useful
for a program that builds on top of multiple VCSes.
mr is
essentially such a thin compatability layer; it manages to be useful only
by being an interface for
humans, who can deal with different limbo
implementations and other quirks.
The VCSes are to some degree converging, but so far it's mostly a surface
convergence, with commands that only look the same. Where will things go
from here?
- Maybe there will be a standardisation effort like POSIX for VCSes.
Though it seems harder; VCSes have a wider interface than just syscalls
and filesystems, so there's more scope for incompatibility.
- Or will complicated compatability code like cygwin be developed,
to let a program that was written for git use bzr instead, carefully
hiding all the differences?
- Another option would be that one VCS wins. So far I'm seeing some
consolidation, but little indication that one VCS will emerge as the
choice for everyone.
- Maybe the VCSes might begin to support each other's repositories. If
a program only supports git, and you use svn, that's fine, if
git can transparently access the svn repo.
- Or will we go on for decades spending a lot of time on portability
code?