NOTE: to run this test requires both `svn` and `git` to be on `$PATH`.

Updating from svn
=================

gitify provides the ``update`` command, which in effect behaves like running
``svn up`` on the local checkout, except that it also updates the git index.

IOW it performs a ``git svn rebase`` operation, except that it performs this
operation on the cache, instead of in-place, thus eliminating many possiblities
for conflicts (which the ``git svn rebase`` command is rather prone to)

Setup
*****

To test this, we create two checkouts of ``trunk``, one of which we gitify
and the other just as a plain svn checkout which we then update (to simulate
the use case of others updating the remote svn repo independently of our own
local changes.)

  >>> import os
  >>> from gitsvnhelpers.gitify import gitify
  >>> self.checkout('trunk')
  >>> gitified = self.checkoutdir
  >>> gitify(args=['init'])
  No git repository found in...
  Initiating cloning into cache.
  Analyzing svn log...
  Cloning file:///...
  Initialized empty Git repository in ...
  ...
  Git branch 'local/trunk' is now following svn branch 'trunk':
  # On branch local/trunk
  nothing to commit (working directory clean)

  >>> self.checkout('trunk', target='svnremote')
  >>> svnremote = self.checkoutdir

Requires svn
************

Running update on a directory that does not contain a .svn repository raises an error:

  >>> os.chdir(self.tempdir)
  >>> gitify(args=['update'])
  Traceback (most recent call last):
  ... 
  SystemExit: 1

The same goes for the push command

  >>> gitify(args=['push'])
  Traceback (most recent call last):
  ... 
  SystemExit: 1

  >>> os.chdir(self.checkoutdir)

Non-conflicting update
**********************

Starting easy, we simply add a new file to the svn repo:

  >>> do('echo "Change from svn" >> svn.txt')
  >>> do('svn add svn.txt')
  A         svn.txt

  >>> do('svn commit -m "Added from svn"')
  Adding         svn.txt
  Transmitting file data .
  Committed revision ...

Then we re-visit our gitified checkout:

  >>> os.chdir(gitified)

Initially, git knows nothing about the svn commit:

  >>> do('git log -n 1 --abbrev-commit')
  commit ...
  Author: ...
  Date: ...
  <BLANKLINE>
      First attempt at fooberizing
  ...

Now let's run gitify's ``update`` command:

  >>> gitify(args=['update'])
  	A	svn.txt
  r7 = ... (refs/remotes/trunk)
  First, rewinding head to replay your work on top of it...
  Fast-forwarded local/trunk to refs/remotes/trunk.

and voila!, the svn commit appears in the git log:

  >>> do('git log -n 1 --abbrev-commit')
  commit ...
  Author: ...
  Date: ...
  <BLANKLINE>
      Added from svn
  ...

Not only that, but the file has indeed been added, as well:

  >>> do('less svn.txt')
  Change from svn

Non-conflicting changes of the same file
========================================

``git svn rebase`` handled the above case beautifully and if that was the whole
story of updating from remote svn changes, gitify would be redundant. However,
``git svn rebase`` easily stumbles over changes, even if ``svn up`` would handle
them gracefully. To demonstrate this we'll 'pitch' a second svn checkout 
against two gitified checkouts, one which we manipulate via ``git svn`` and
the other via ``gitify``.

Checking out and modifiying locally
***********************************

We first create all necessary checkouts (to ensure they all have the same
revision) and create local changes to ``svn.txt`` without committing it:

  >>> self.checkout('trunk', target='svnlocal')
  >>> svnlocal = self.checkoutdir
  >>> do('echo "Changed locally" >> svn.txt')

  >>> self.checkout('trunk', target='gitsvn')
  >>> gitsvn = self.checkoutdir
  >>> do('git svn clone file://%s -s .' % self.repo)
  Initialized empty Git repository in /...
  r1 = ... (refs/remotes/trunk)
  	A	README.txt
  ...

  >>> do('git checkout -f -b local/trunk trunk')
  >>> do('git branch')
  * local/trunk
    master

  >>> do('echo "Changed locally" >> svn.txt')

  >>> os.chdir(gitified)
  >>> do('echo "Changed locally" >> svn.txt')
  >>> do('echo "From gitify." >> svn.txt')

Remote change
*************

We now modify the file via the 'remote' svn and commit that change:

  >>> os.chdir(svnremote)
  >>> do('echo "Changed locally" >> svn.txt')
  >>> do('svn commit -m "Modified from remote svn"')
  Sending        svn.txt
  Transmitting file data .
  Committed revision 8.

Now we can 'pitch' the three candidates against each other how they handle
updating the remote change.

Subversion
**********

  >>> os.chdir(svnlocal)
  >>> do("svn up")
  Updating '.':
  G    svn.txt
  Updated to revision 8.

As we can see, subversion handled this nicely. It notices, that the local
changes are mergable and goes ahead and does just that, informing us with the
``G`` status. Nicely done, svn - you've set the par for the course!

git-svn
*******

  >>> os.chdir(gitsvn)
  >>> from jarn.mkrelease.tee import popen
  >>> do('git svn rebase')
  svn.txt: needs update

``git svn`` balks at this and simply refuses to do anything :-(

If we commit our changes:

  >>> do('git commit -a -m "Modified from gitsvn"')
  [local/trunk ...] Modified from gitsvn
   1 files changed, 1 insertions(+), 0 deletions(-)

The rebase command works as expected:

  >>> do('git svn rebase')
  	M	svn.txt
  r8 = ... (refs/remotes/trunk)
  First, rewinding head to replay your work on top of it...

Now the slate is clean:

  >>> do('git status')
  # On branch local/trunk
  nothing to commit (working directory clean)

gitify
******

Gitify will stash the changes and go ahead with the rebase. To verify this,
let's first check the status:

  >>> os.chdir(gitified)
  >>> do('git status')
  # On branch local/trunk
  # Change...:
  #   (use "git add <file>..." to update what will be committed)
  #   (use "git checkout -- <file>..." to discard changes in working directory)
  #
  #	modified:   svn.txt
  #
  no changes added to commit (use "git add" and/or "git commit -a")

  >>> gitify(args=['update'])
  Stashing uncommitted local changes.
  ...

This leaves us (as desired) with the uncomitted changes we started out with,
except that git now calls them 'unmerged' instead of 'modified':

  >>> do('git status')
  # On branch local/trunk
  # Unmerged paths:
  #   (use "git reset HEAD <file>..." to unstage)
  #   (use "git add... to mark resolution)
  #
  #	both modified:      svn.txt
  #
  no changes added to commit (use "git add" and/or "git commit -a")
