[meld] Add new VC file request interface and SVN support
- From: Kai Willadsen <kaiw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [meld] Add new VC file request interface and SVN support
- Date: Sun, 2 Dec 2012 21:25:11 +0000 (UTC)
commit 24798fb11d13f68bb83f4d1e8344b668ea1ffa00
Author: Kai Willadsen <kai willadsen gmail com>
Date: Sun Sep 4 13:26:54 2011 +1000
Add new VC file request interface and SVN support
Currently, all VC plugins are asked for a diff between the on-disk
contents and the repository head, which VCView then reverse applies
with patch to get a temporary copy of the repository contents. This
works surprisingly well, but has several issues, most notable of which
is that it's borderline impossible to figure out what's happening when
it breaks. In addition, some VCSs (e.g., subversion) give out patches
that won't actually reverse-apply because of other magic that's been
performed on the checkout, but isn't reflected in the diff.
This patch adds a simple 'give me the file' API to the Vc class, and
adds support for it to the svn plugin. While it has a slot for a
commit argument to retrieve non-HEAD commits, this currently doesn't
work and has no UI anyway.
meld/vc/_vc.py | 19 +++++++++++++++++++
meld/vc/svn.py | 20 ++++++++++++++++++++
meld/vcview.py | 14 ++++++++++++--
3 files changed, 51 insertions(+), 2 deletions(-)
---
diff --git a/meld/vc/_vc.py b/meld/vc/_vc.py
index 3efc0d0..61a583e 100644
--- a/meld/vc/_vc.py
+++ b/meld/vc/_vc.py
@@ -110,6 +110,25 @@ class Vc(object):
def patch_command(self, workdir):
return ["patch", "-p%i" % self.PATCH_STRIP_NUM, "-R", "-d", workdir]
+ def get_repo_file_path(self, path, commit=None):
+ """Requests a file path for the repository copy of the given path.
+
+ Regardless of whether the VCS in question maintains an on-disk copy of
+ the given path, to avoid destructive editing, a temp file with the
+ given content must be created and its path returned. The VCS plugin
+ must **not** delete temp files it creates.
+
+ If *commit* is given, then the path returned will point to a copy of
+ the file at path at the given commit, as interpreted by the VCS in
+ question. If *commit* is **None**, then the current tip is used.
+ """
+
+ # TODO: This method is required to return a path because of how
+ # FileDiff currently operates. In the future, allowing for blob
+ # returns would be desirable.
+
+ raise NotImplementedError()
+
def check_repo_root(self, location):
if not os.path.isdir(os.path.join(location, self.VC_DIR)):
raise ValueError
diff --git a/meld/vc/svn.py b/meld/vc/svn.py
index 24de407..440e778 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 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
@@ -24,6 +25,8 @@
import errno
import os
import re
+import shutil
+import tempfile
import xml.etree.ElementTree as ElementTree
from . import _vc
@@ -65,6 +68,23 @@ class Vc(_vc.CachedVc):
return [self.CMD,"revert"]
def resolved_command(self):
return [self.CMD,"resolved"]
+
+ def get_repo_file_path(self, path, commit=None):
+ if commit is not None:
+ raise NotImplementedError()
+
+ base, fname = os.path.split(path)
+ svn_path = os.path.join(base, ".svn", "text-base", fname + ".svn-base")
+
+ # TODO: In Python 2.6+, this could be done with NamedTemporaryFile
+ tmp_handle, tmp_path = tempfile.mkstemp(prefix='meld-tmp', text=True)
+ with open(svn_path, 'r') as vc_file:
+ tmp_file = os.fdopen(tmp_handle, 'w')
+ shutil.copyfileobj(vc_file, tmp_file)
+ tmp_file.close()
+
+ return tmp_path
+
def valid_repo(self):
if _vc.call([self.CMD, "info"], cwd=self.root):
return False
diff --git a/meld/vcview.py b/meld/vcview.py
index 486ee99..27bae2e 100644
--- a/meld/vcview.py
+++ b/meld/vcview.py
@@ -156,6 +156,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
button = self.actiongroup.get_action(action)
button.props.icon_name = button.props.stock_id
self.tempdirs = []
+ self.temp_files = set()
self.model = VcTreeStore()
self.widget.connect("style-set", self.model.on_style_set)
self.treeview.set_model(self.model)
@@ -381,6 +382,9 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
for f in self.tempdirs:
if os.path.exists(f):
shutil.rmtree(f, ignore_errors=1)
+ for f in self.temp_files:
+ if os.path.exists(f):
+ os.remove(f)
def on_delete_event(self, appquit=0):
self.on_quit_event()
@@ -428,8 +432,14 @@ 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]), atfront=1)
+ try:
+ for path in path_list:
+ comp_path = self.vc.get_repo_file_path(path)
+ self.temp_files.add(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]), atfront=1)
def on_treeview_popup_menu(self, treeview):
time = gtk.get_current_event_time()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]