diff --git a/meld/melddoc.py b/meld/melddoc.py
index b1fad18..2654044 100644
--- a/meld/melddoc.py
+++ b/meld/melddoc.py
@@ -145,17 +145,8 @@ class MeldDoc(gobject.GObject):
 
     def on_delete_event(self, appquit=0):
         """Called when the docs container is about to close.
-           A doc normally returns gtk.RESPONSE_OK but may return
-           gtk.RESPONSE_CANCEL which requests the container
-           to not delete it. In the special case when the
-           app is about to quit, gtk.RESPONSE_CLOSE may be returned
-           which instructs the container to quit without any
-           more callbacks.
-        """
-        return gtk.RESPONSE_OK
 
-    def on_quit_event(self):
-        """Called when the docs container is about to close.
-           There is no way to interrupt the quit event.
+        A doc normally returns gtk.RESPONSE_OK, but may instead return
+        gtk.RESPONSE_CANCEL to request that the container not delete it.
         """
-        pass
+        return gtk.RESPONSE_OK
diff --git a/meld/meldwindow.py b/meld/meldwindow.py
index 55e3061..9b51f2b 100644
--- a/meld/meldwindow.py
+++ b/meld/meldwindow.py
@@ -396,8 +396,6 @@ class MeldWindow(gnomeglade.Component):
             response = self.try_remove_page(page, appquit=1)
             if response == gtk.RESPONSE_CANCEL:
                 return gtk.RESPONSE_CANCEL
-        for c in self.notebook.get_children():
-            c.get_data("pyobject").on_quit_event()
         gtk.main_quit()
         return gtk.RESPONSE_CLOSE
 
diff --git a/meld/vc/__init__.py b/meld/vc/__init__.py
index bca7967..a7c16b2 100644
--- a/meld/vc/__init__.py
+++ b/meld/vc/__init__.py
@@ -95,9 +95,4 @@ def get_vcs(location):
     vc_name = lambda x: x.NAME
     vcs.sort(cmp=vc_comp, key=vc_name)
 
-    # Simplistic hack so that we don't offer both 1.7 and <1.6 SVN
-    vc_names = [plugin.NAME for plugin in vcs]
-    if "Subversion" in vc_names and "Subversion 1.7" in vc_names:
-        vcs = [plugin for plugin in vcs if plugin.NAME != "Subversion 1.7"]
-
     return vcs
diff --git a/meld/vc/_vc.py b/meld/vc/_vc.py
index 09d9c6d..7f00cee 100644
--- a/meld/vc/_vc.py
+++ b/meld/vc/_vc.py
@@ -78,20 +78,20 @@ class Vc(object):
     VC_METADATA = None
 
     def __init__(self, location):
-        # Save the requested diff directory/file.  It may be a sub-directory
-        # of the repository we are diffing and can be useful in limiting meld's
-        # output to the requested location.  It can also be used to determine
-        # if the user is requesting a single-file diff or a diretcory diff.
+        # Save the requested comparison location. The location may be a
+        # sub-directory of the repository we are diffing and can be useful in
+        # limiting meld's output to the requested location.
+        #
+        # If the location requested is a file (e.g., a single-file command line
+        # comparison) then the location is set to the containing directory.
+        if not os.path.isdir(location):
+            location = os.path.dirname(location)
         self.location = location
 
-        if not os.path.isdir(location):
-            path = os.path.dirname(self.location)
-        else:
-            path = location
         if self.VC_ROOT_WALK:
-            self.root = self.find_repo_root(path)
+            self.root = self.find_repo_root(self.location)
         else:
-            self.root = self.check_repo_root(path)
+            self.root = self.check_repo_root(self.location)
 
     def commit_command(self, message):
         raise NotImplementedError()
@@ -110,6 +110,20 @@ class Vc(object):
     def patch_command(self, workdir):
         return ["patch", "-p%i" % self.PATCH_STRIP_NUM, "-R", "-d", workdir]
 
+    def get_path_for_repo_file(self, path, commit=None):
+        """Returns a file path for the repository path at commit
+
+        If *commit* is given, the path returned will point to a copy of
+        the file at *path* at the given commit, as interpreted by the
+        VCS. If *commit* is **None**, the current revision is used.
+
+        Even if the VCS maintains an on-disk copy of the given path, a
+        temp file with file-at-commit content must be created and its
+        path returned, to avoid destructive editing. The VCS plugin
+        must **not** delete temp files it creates.
+        """
+        raise NotImplementedError()
+
     def check_repo_root(self, location):
         if not os.path.isdir(os.path.join(location, self.VC_DIR)):
             raise ValueError
@@ -215,6 +229,33 @@ class CachedVc(Vc):
             self.cache_inventory(directory)
         return self._tree_cache
 
+
+class InvalidVCPath(ValueError):
+    """Raised when a VC module is passed an invalid (or not present) path."""
+
+    def __init__(self, vc, path, err):
+        self.vc = vc
+        self.path = path
+        self.error = err
+
+    def __str__(self):
+        return "%s: Path %s is invalid or not present\nError: %s\n" % \
+              (self.vc.NAME, self.path, self.error)
+
+
+class InvalidVCRevision(ValueError):
+    """Raised when a VC module is passed a revision spec it can't handle."""
+
+    def __init__(self, vc, rev, err):
+        self.vc = vc
+        self.revision = rev
+        self.error = err
+
+    def __str__(self):
+        return "%s: Doesn't understand or have revision %s\nError: %s\n" % \
+              (self.vc.NAME, self.revision, self.error)
+
+
 # Return the stdout output of a given command
 def popen(cmd, cwd=None):
     return subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE).stdout
diff --git a/meld/vc/git.py b/meld/vc/git.py
index d45d362..bdb5ab2 100644
--- a/meld/vc/git.py
+++ b/meld/vc/git.py
@@ -30,6 +30,10 @@
 import os
 import errno
 import _vc
+import re
+import shutil
+import subprocess
+import tempfile
 
 class Vc(_vc.CachedVc):
 
@@ -67,6 +71,30 @@ class Vc(_vc.CachedVc):
         return [self.CMD,"rm"]
     def revert_command(self):
         return [self.CMD,"checkout"]
+
+    def get_path_for_repo_file(self, path, commit=None):
+        if commit is None:
+            commit = "HEAD"
+        else:
+            raise NotImplementedError()
+
+        if not path.startswith(self.root + os.path.sep):
+            raise _vc.InvalidVCPath(self, path, "Path not in repository")
+        path = path[len(self.root) + 1:]
+
+        obj = commit + ":" + path
+        process = subprocess.Popen(["git", "cat-file", "blob", obj],
+                                   cwd=self.location, stdout=subprocess.PIPE,
+                                   stderr=subprocess.PIPE)
+        vc_file = process.stdout
+
+        # Error handling here involves doing nothing; in most cases, the only
+        # sane response is to return an empty temp file.
+
+        with tempfile.NamedTemporaryFile(prefix='meld-tmp', delete=False) as f:
+            shutil.copyfileobj(vc_file, f)
+        return f.name
+
     def valid_repo(self):
         if _vc.call([self.CMD, "branch"], cwd=self.root):
             return False
diff --git a/meld/vc/svn.py b/meld/vc/svn.py
index 84b1cbd..1882598 100644
--- a/meld/vc/svn.py
+++ b/meld/vc/svn.py
@@ -1,4 +1,5 @@
 ### Copyright (C) 2002-2005 Stephen Kennedy <stevek@gnome.org>
+### Copyright (C) 2011-2012 Kai Willadsen <kai.willadsen@gmail.com>
 
 ### Redistribution and use in source and binary forms, with or without
 ### modification, are permitted provided that the following conditions
@@ -25,6 +26,8 @@ import os
 import re
 import errno
 import _vc
+import shutil
+import tempfile
 import xml.etree.ElementTree as ElementTree
 
 
@@ -64,11 +67,51 @@ class Vc(_vc.CachedVc):
         return [self.CMD,"revert"]
     def resolved_command(self):
         return [self.CMD,"resolved"]
+
+    def get_path_for_repo_file(self, path, commit=None):
+        if commit is not None:
+            raise NotImplementedError()
+
+        if not path.startswith(self.root + os.path.sep):
+            raise _vc.InvalidVCPath(self, path, "Path not in repository")
+        path = path[len(self.root) + 1:]
+
+        base, fname = os.path.split(path)
+        svn_path = os.path.join(base, ".svn", "text-base", fname + ".svn-base")
+
+        with tempfile.NamedTemporaryFile(prefix='meld-tmp', delete=False) as f:
+            try:
+                with open(svn_path, 'r') as vc_file:
+                    shutil.copyfileobj(vc_file, f)
+            except IOError as err:
+                if err.errno != errno.ENOENT:
+                    raise
+                # If the repository path doesn't exist, we either have an
+                # invalid path (difficult to check) or a new file. Either way,
+                # we just return an empty file
+
+        return f.name
+
+    def _repo_version_support(self, version):
+        return version < 12
+
     def valid_repo(self):
         if _vc.call([self.CMD, "info"], cwd=self.root):
             return False
+
+        # Check for repository version, trusting format file then entries file
+        format_path = os.path.join(self.root, self.VC_DIR, "format")
+        entries_path = os.path.join(self.root, self.VC_DIR, "entries")
+        if os.path.exists(format_path):
+            version_file = format_path
+        elif os.path.exists(entries_path):
+            version_file = entries_path
         else:
-            return True
+            return False
+
+        with open(version_file) as f:
+            content = f.readline().strip()
+        return self._repo_version_support(int(content))
 
     def switch_to_external_diff(self):
         self.external_diff = "diff"
diff --git a/meld/vc/svn_17.py b/meld/vc/svn_17.py
index d8009f2..d82c9fa 100644
--- a/meld/vc/svn_17.py
+++ b/meld/vc/svn_17.py
@@ -1,9 +1,9 @@
-### Copyright (C) 2011 Kai Willadsen <kai.willadsen@gmail.com>
+### Copyright (C) 2011-2012 Kai Willadsen <kai.willadsen@gmail.com>
 
 ### Redistribution and use in source and binary forms, with or without
 ### modification, are permitted provided that the following conditions
 ### are met:
-### 
+###
 ### 1. Redistributions of source code must retain the above copyright
 ###    notice, this list of conditions and the following disclaimer.
 ### 2. Redistributions in binary form must reproduce the above copyright
@@ -21,7 +21,13 @@
 ### (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 ### THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+import os
+import shutil
+import subprocess
+import tempfile
+
 import svn
+import _vc
 
 
 class Vc(svn.Vc):
@@ -29,3 +35,28 @@ class Vc(svn.Vc):
     NAME = "Subversion 1.7"
     VC_ROOT_WALK = True
 
+    def _repo_version_support(self, version):
+        return version >= 12
+
+    def get_path_for_repo_file(self, path, commit=None):
+        if commit is None:
+            commit = "BASE"
+        else:
+            raise NotImplementedError()
+
+        if not path.startswith(self.root + os.path.sep):
+            raise _vc.InvalidVCPath(self, path, "Path not in repository")
+        path = path[len(self.root) + 1:]
+
+        process = subprocess.Popen([self.CMD, "cat", "-r", commit, path],
+                                   cwd=self.location, stdout=subprocess.PIPE,
+                                   stderr=subprocess.PIPE)
+        vc_file = process.stdout
+
+        # Error handling here involves doing nothing; in most cases, the only
+        # sane response is to return an empty temp file. The most common error
+        # is "no base revision until committed" from diffing a new file.
+
+        with tempfile.NamedTemporaryFile(prefix='meld-tmp', delete=False) as f:
+            shutil.copyfileobj(vc_file, f)
+        return f.name
diff --git a/meld/vcview.py b/meld/vcview.py
index 8caf17c..58913b2 100644
--- a/meld/vcview.py
+++ b/meld/vcview.py
@@ -15,10 +15,14 @@
 ### along with this program; if not, write to the Free Software
 ### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
+from __future__ import print_function
+
+import atexit
 import tempfile
 import shutil
 import gtk
 import os
+import sys
 from gettext import gettext as _
 
 import tree
@@ -42,6 +46,34 @@ def _commonprefix(files):
         workdir = os.path.dirname(files[0]) or "."
     return workdir
 
+
+def cleanup_temp():
+    temp_location = tempfile.gettempdir()
+    # The strings below will probably end up as debug log, and are deliberately
+    # not marked for translation.
+    for f in _temp_files:
+        try:
+            assert os.path.exists(f) and os.path.isabs(f) and \
+                   os.path.dirname(f) == temp_location
+            os.remove(f)
+        except:
+            except_str = "{0[0]}: \"{0[1]}\"".format(sys.exc_info())
+            print("File \"{0}\" not removed due to".format(f), except_str,
+                  file=sys.stderr)
+    for f in _temp_dirs:
+        try:
+            assert os.path.exists(f) and os.path.isabs(f) and \
+                   os.path.dirname(f) == temp_location
+            shutil.rmtree(f, ignore_errors=1)
+        except:
+            except_str = "{0[0]}: \"{0[1]}\"".format(sys.exc_info())
+            print("Directory \"{0}\" not removed due to".format(f), except_str,
+                  file=sys.stderr)
+
+_temp_dirs, _temp_files = [], []
+atexit.register(cleanup_temp)
+
+
 ################################################################################
 #
 # CommitDialog
@@ -156,7 +188,6 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
                        "VcShowIgnored", "VcResolved"):
             button = self.actiongroup.get_action(action)
             button.props.icon_name = button.props.stock_id
-        self.tempdirs = []
         self.model = VcTreeStore()
         self.treeview.set_model(self.model)
         self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
@@ -371,14 +402,8 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
         path = fileentry.get_full_path()
         self.set_location(path)
 
-    def on_quit_event(self):
-        self.scheduler.remove_all_tasks()
-        for f in self.tempdirs:
-            if os.path.exists(f):
-                shutil.rmtree(f, ignore_errors=1)
-
     def on_delete_event(self, appquit=0):
-        self.on_quit_event()
+        self.scheduler.remove_all_tasks()
         return gtk.RESPONSE_OK
 
     def on_row_activated(self, treeview, path, tvc):
@@ -418,8 +443,15 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
                     self.emit("create-diff", [path])
 
     def run_diff(self, path_list):
-        for path in path_list:
-            self.scheduler.add_task(self.run_diff_iter([path]).next, atfront=1)
+        try:
+            for path in path_list:
+                comp_path = self.vc.get_path_for_repo_file(path)
+                os.chmod(comp_path, 0o444)
+                _temp_files.append(comp_path)
+                self.emit("create-diff", [comp_path, path])
+        except NotImplementedError:
+            for path in path_list:
+                self.scheduler.add_task(self.run_diff_iter([path]).next, atfront=1)
 
     def on_treeview_popup_menu(self, treeview):
         time = gtk.get_current_event_time()
@@ -554,7 +586,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
 
     def show_patch(self, prefix, patch, silent=False):
         tmpdir = tempfile.mkdtemp("-meld")
-        self.tempdirs.append(tmpdir)
+        _temp_dirs.append(tmpdir)
 
         diffs = []
         for fname in self.vc.get_patch_files(patch):
