[meld] Remove old-style patch-based file retrieval, moving into CVS



commit 5be1c94c838326125a36f625ece3431c73361f52
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Sun Jun 16 08:34:08 2013 +1000

    Remove old-style patch-based file retrieval, moving into CVS
    
    The old-style patching has been removed for every VC that gives us
    direct access to files. CVS is the only hold-out, so it gets to suffer
    the missing error messages.

 meld/vc/_vc.py      |    9 ---
 meld/vc/bzr.py      |    1 -
 meld/vc/cvs.py      |   51 +++++++++++++++
 meld/vc/darcs.py    |    2 -
 meld/vc/fossil.py   |    1 -
 meld/vc/monotone.py |    1 -
 meld/vc/svk.py      |    1 -
 meld/vc/svn.py      |    9 +---
 meld/vcview.py      |  169 +++++++++++----------------------------------------
 9 files changed, 88 insertions(+), 156 deletions(-)
---
diff --git a/meld/vc/_vc.py b/meld/vc/_vc.py
index e7590af..121c593 100644
--- a/meld/vc/_vc.py
+++ b/meld/vc/_vc.py
@@ -99,8 +99,6 @@ class File(Entry):
 
 class Vc(object):
 
-    PATCH_STRIP_NUM = 0
-    PATCH_INDEX_RE = ''
     VC_DIR = None
     VC_ROOT_WALK = True
     VC_METADATA = None
@@ -144,9 +142,6 @@ class Vc(object):
     def resolved_command(self):
         raise NotImplementedError()
 
-    def patch_command(self, workdir):
-        return ["patch", "-p%i" % self.PATCH_STRIP_NUM, "-R", "-d", workdir]
-
     # Prototyping VC interface version 2
 
     def get_files_to_commit(self, paths):
@@ -230,10 +225,6 @@ class Vc(object):
         """
         pass
 
-    def get_patch_files(self, patch):
-        regex = re.compile(self.PATCH_INDEX_RE, re.M)
-        return [f.strip() for f in regex.findall(patch)]
-
     # Determine if a directory is a valid git/svn/hg/cvs/etc repository
     def valid_repo(self):
         return True
diff --git a/meld/vc/bzr.py b/meld/vc/bzr.py
index 8e83d6a..49662ac 100644
--- a/meld/vc/bzr.py
+++ b/meld/vc/bzr.py
@@ -38,7 +38,6 @@ class Vc(_vc.CachedVc):
     CMDARGS = ["--no-aliases", "--no-plugins"]
     NAME = "Bazaar"
     VC_DIR = ".bzr"
-    PATCH_INDEX_RE = "^=== modified file '(.*)'.*$"
     CONFLICT_RE = "conflict in (.*)$"
 
     commit_statuses = (
diff --git a/meld/vc/cvs.py b/meld/vc/cvs.py
index 4a9c898..7afbff1 100644
--- a/meld/vc/cvs.py
+++ b/meld/vc/cvs.py
@@ -26,12 +26,19 @@ import logging
 import os
 from gettext import gettext as _
 import re
+import shutil
+import tempfile
 import time
 
 from meld import misc
 from . import _vc
 
 
+class FakeErrorStream(object):
+    def error(self, error):
+        pass
+
+
 class Vc(_vc.Vc):
     CMD = "cvs"
     # CVSNT is a drop-in replacement for CVS; if found, it is used instead
@@ -39,6 +46,7 @@ class Vc(_vc.Vc):
     NAME = "CVS"
     VC_DIR = "CVS"
     VC_ROOT_WALK = False
+    PATCH_STRIP_NUM = 0
     PATCH_INDEX_RE = "^Index:(.*)$"
 
     VC_COLUMNS = (_vc.DATA_NAME, _vc.DATA_STATE, _vc.DATA_REVISION,
@@ -74,6 +82,49 @@ class Vc(_vc.Vc):
         else:
             return False
 
+    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:]
+
+        diffiter = misc.read_pipe_iter(self.diff_command() + [path],
+                                       FakeErrorStream(), workdir=self.root)
+        patch = None
+        while patch is None:
+            patch = next(diffiter)
+
+        tmpdir = tempfile.mkdtemp("-meld")
+        destfile = os.path.join(tmpdir, os.path.basename(path))
+
+        try:
+            shutil.copyfile(os.path.join(self.root, path), destfile)
+        except IOError:
+            # For missing files, create a new empty file
+            open(destfile, "w").close()
+
+        patchcmd = ["patch", "-R", "-d", tmpdir]
+        try:
+            with open(os.devnull, "w") as NULL:
+                result = misc.write_pipe(patchcmd, patch, error=NULL)
+                assert result == 0
+
+            with open(destfile) as patched_file:
+                with tempfile.NamedTemporaryFile(prefix='meld-tmp',
+                                                 delete=False) as temp_file:
+                    shutil.copyfileobj(patched_file, temp_file)
+
+            return temp_file.name
+        except (OSError, AssertionError):
+            return
+        finally:
+            if os.path.exists(destfile):
+                os.remove(destfile)
+            if os.path.exists(destfile):
+                os.rmdir(tmpdir)
+
     def _get_dirsandfiles(self, directory, dirs, files):
         log = logging.getLogger(__name__)
 
diff --git a/meld/vc/darcs.py b/meld/vc/darcs.py
index 0860516..a5073d8 100644
--- a/meld/vc/darcs.py
+++ b/meld/vc/darcs.py
@@ -35,8 +35,6 @@ class Vc(_vc.CachedVc):
     CMD = "darcs"
     NAME = "Darcs"
     VC_DIR = "_darcs"
-    PATCH_STRIP_NUM = 1
-    PATCH_INDEX_RE = "--- old.+?/(.+?)\\t+.*[0-9]{4}$"
     state_map = {
         "a": _vc.STATE_NONE,
         "A": _vc.STATE_NEW,
diff --git a/meld/vc/fossil.py b/meld/vc/fossil.py
index 3f08f76..344332e 100644
--- a/meld/vc/fossil.py
+++ b/meld/vc/fossil.py
@@ -38,7 +38,6 @@ class Vc(_vc.CachedVc):
     CMD = "fossil"
     NAME = "Fossil"
     VC_METADATA = [".fslckout", "_FOSSIL_", ".fos"]    # One or the other
-    PATCH_INDEX_RE = "^--- (.*)$"
 
     VC_COLUMNS = (_vc.DATA_NAME, _vc.DATA_STATE, _vc.DATA_REVISION)
 
diff --git a/meld/vc/monotone.py b/meld/vc/monotone.py
index 384f106..e2812b7 100644
--- a/meld/vc/monotone.py
+++ b/meld/vc/monotone.py
@@ -36,7 +36,6 @@ class Vc(_vc.CachedVc):
     CMD = "mtn"
     NAME = "Monotone"
     VC_DIR = "_MTN"
-    PATCH_INDEX_RE = "^[+]{3,3} ([^  ]*)\t[0-9a-f]{40,40}$"
 
     state_map_6 = {
         'added known rename_source'         : _vc.STATE_NEW,
diff --git a/meld/vc/svk.py b/meld/vc/svk.py
index 76c377c..e7b7e86 100644
--- a/meld/vc/svk.py
+++ b/meld/vc/svk.py
@@ -49,7 +49,6 @@ class Vc(svn.Vc):
 
     CMD = "svk"
     NAME = "SVK"
-    PATCH_INDEX_RE = "^=== (.*)$"
 
     def check_repo_root(self, location):
         try:
diff --git a/meld/vc/svn.py b/meld/vc/svn.py
index 8b27275..dad97d6 100644
--- a/meld/vc/svn.py
+++ b/meld/vc/svn.py
@@ -38,7 +38,6 @@ class Vc(_vc.CachedVc):
     NAME = "Subversion"
     VC_DIR = ".svn"
     VC_ROOT_WALK = False
-    PATCH_INDEX_RE = "^Index:(.*)$"
 
     VC_COLUMNS = (_vc.DATA_NAME, _vc.DATA_STATE, _vc.DATA_REVISION)
 
@@ -56,10 +55,7 @@ class Vc(_vc.CachedVc):
     def commit_command(self, message):
         return [self.CMD,"commit","-m",message]
     def diff_command(self):
-        if hasattr(self, "external_diff"):
-            return [self.CMD, "diff", "--diff-cmd", self.external_diff]
-        else:
-            return [self.CMD, "diff"]
+        return [self.CMD, "diff"]
 
     def update_command(self):
         return [self.CMD,"update"]
@@ -170,9 +166,6 @@ class Vc(_vc.CachedVc):
             content = f.readline().strip()
         return self._repo_version_support(int(content))
 
-    def switch_to_external_diff(self):
-        self.external_diff = "diff"
-
     def _update_tree_state_cache(self, path, tree_state):
         while 1:
             try:
diff --git a/meld/vcview.py b/meld/vcview.py
index 0ea58ba..12219b6 100644
--- a/meld/vcview.py
+++ b/meld/vcview.py
@@ -570,71 +570,43 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
             path = self.model.value_path(it, 0)
             self.run_diff([path])
 
-    def run_diff_iter(self, path_list):
-        silent_error = hasattr(self.vc, 'switch_to_external_diff')
-        retry_diff = True
-        while retry_diff:
-            retry_diff = False
-
-            yield _("[%s] Fetching differences") % self.label_text
-            diffiter = self._command_iter(self.vc.diff_command(), path_list, 0)
-            diff = None
-            while type(diff) != type(()):
-                diff = next(diffiter)
-                yield 1
-            prefix, patch = diff[0], diff[1]
-
-            yield _("[%s] Applying patch") % self.label_text
-            if patch:
-                applied = self.show_patch(prefix, patch, silent=silent_error)
-                if not applied and silent_error:
-                    silent_error = False
-                    self.vc.switch_to_external_diff()
-                    retry_diff = True
-            else:
-                for path in path_list:
-                    self.emit("create-diff", [path], {})
-
     def run_diff(self, path_list):
-        try:
-            for path in path_list:
-                if os.path.isdir(path):
-                    self.emit("create-diff", [path], {})
-                    continue
-
-                kwargs = {}
-                vc_file = self.vc.lookup_files(
-                    [], [(os.path.basename(path), path)])[1][0]
-                if vc_file.state == tree.STATE_CONFLICT:
-                    # We use auto merge, so we create a new temp file
-                    # for other, base and this, then set the output to
-                    # the current file.
-
-                    conflicts = (tree.CONFLICT_OTHER, tree.CONFLICT_MERGED,
-                                 tree.CONFLICT_THIS)
-                    diffs = [self.vc.get_path_for_conflict(path, conflict=c)
-                             for c in conflicts]
-                    for conflict_path, is_temp in diffs:
-                        # If this is the actual file, don't touch it.
-                        if conflict_path != path and is_temp:
-                            os.chmod(conflict_path, 0o444)
-                            _temp_files.append(conflict_path)
-                    # create-diff expects only the paths
-                    diffs = [p for p, is_temp in diffs]
-
-                    # If we want to use auto-merge or use the merged
-                    # output given by the VCS
-                    kwargs['auto_merge'] = False
-                    kwargs['merge_output'] = path
-                else:
-                    comp_path = self.vc.get_path_for_repo_file(path)
-                    os.chmod(comp_path, 0o444)
-                    _temp_files.append(comp_path)
-                    diffs = [comp_path, path]
-                self.emit("create-diff", diffs, kwargs)
-        except NotImplementedError:
-            for path in path_list:
-                self.scheduler.add_task(self.run_diff_iter([path]), atfront=1)
+        for path in path_list:
+            if os.path.isdir(path):
+                self.emit("create-diff", [path], {})
+                continue
+
+            kwargs = {}
+            vc_file = self.vc.lookup_files(
+                [], [(os.path.basename(path), path)])[1][0]
+            if vc_file.state == tree.STATE_CONFLICT and \
+                    hasattr(self.vc, 'get_path_for_conflict'):
+                # We use auto merge, so we create a new temp file
+                # for other, base and this, then set the output to
+                # the current file.
+
+                conflicts = (tree.CONFLICT_OTHER, tree.CONFLICT_MERGED,
+                             tree.CONFLICT_THIS)
+                diffs = [self.vc.get_path_for_conflict(path, conflict=c)
+                         for c in conflicts]
+                for conflict_path, is_temp in diffs:
+                    # If this is the actual file, don't touch it.
+                    if conflict_path != path and is_temp:
+                        os.chmod(conflict_path, 0o444)
+                        _temp_files.append(conflict_path)
+                # create-diff expects only the paths
+                diffs = [p for p, is_temp in diffs]
+
+                # If we want to use auto-merge or use the merged
+                # output given by the VCS
+                kwargs['auto_merge'] = False
+                kwargs['merge_output'] = path
+            else:
+                comp_path = self.vc.get_path_for_repo_file(path)
+                os.chmod(comp_path, 0o444)
+                _temp_files.append(comp_path)
+                diffs = [comp_path, path]
+            self.emit("create-diff", diffs, kwargs)
 
     def on_treeview_popup_menu(self, treeview):
         time = gtk.get_current_event_time()
@@ -828,75 +800,6 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
     def open_external(self):
         self._open_files(self._get_selected_files())
 
-    def show_patch(self, prefix, patch, silent=False):
-        if vc._vc.call(["which", "patch"]):
-            primary = _("Patch tool not found")
-            secondary = _("Meld needs the <i>patch</i> tool to be installed "
-                          "to perform comparisons in %s repositories. Please "
-                          "install <i>patch</i> and try again.") % self.vc.NAME
-
-            msgarea = self.msgarea_mgr.new_from_text_and_icon(
-                gtk.STOCK_DIALOG_ERROR, primary, secondary)
-            msgarea.add_button(_("Hi_de"), gtk.RESPONSE_CLOSE)
-            msgarea.connect("response", lambda *args: self.msgarea_mgr.clear())
-            msgarea.show_all()
-            return False
-
-        tmpdir = tempfile.mkdtemp("-meld")
-        _temp_dirs.append(tmpdir)
-
-        diffs = []
-        for fname in self.vc.get_patch_files(patch):
-            destfile = os.path.join(tmpdir, fname)
-            destdir = os.path.dirname(destfile)
-
-            if not os.path.exists(destdir):
-                os.makedirs(destdir)
-            pathtofile = os.path.join(prefix, fname)
-            try:
-                shutil.copyfile(pathtofile, destfile)
-            except IOError:
-                # it is missing, create empty file
-                open(destfile, "w").close()
-            diffs.append((destfile, pathtofile))
-
-        patchcmd = self.vc.patch_command(tmpdir)
-        try:
-            with open(os.devnull, "w") as NULL:
-                result = misc.write_pipe(patchcmd, patch, error=NULL)
-        except OSError:
-            result = 1
-
-        if result == 0:
-            for d in diffs:
-                os.chmod(d[0], 0o444)
-                self.emit("create-diff", d, {})
-            return True
-        elif not silent:
-            primary = _("Error fetching original comparison file")
-            secondary = _("Meld couldn't obtain the original version of your "
-                          "comparison file. If you are using the most recent "
-                          "version of Meld, please report a bug, including as "
-                          "many details as possible.")
-
-            msgarea = self.msgarea_mgr.new_from_text_and_icon(
-                gtk.STOCK_DIALOG_ERROR, primary, secondary)
-            msgarea.add_button(_("Hi_de"), gtk.RESPONSE_CLOSE)
-            msgarea.add_button(_("Report a bug"), gtk.RESPONSE_OK)
-
-            def patch_error_cb(msgarea, response):
-                if response == gtk.RESPONSE_OK:
-                    bug_url = "https://bugzilla.gnome.org/enter_bug.cgi?"; + \
-                              "product=meld"
-                    misc.open_uri(bug_url)
-                else:
-                    self.msgarea_mgr.clear()
-
-            msgarea.connect("response", patch_error_cb)
-            msgarea.show_all()
-
-        return False
-
     def refresh(self):
         self.set_location(self.model.value_path(self.model.get_iter_root(), 0))
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]