[meld] Use external diff for Subversion if 'patch' failed (closes bgo#587079)



commit c4de90ce4d4a39b86599b3af90989dab76866d1f
Author: Cedric Le Dillau <ld c free fr>
Date:   Thu Dec 30 23:41:36 2010 +0100

    Use external diff for Subversion if 'patch' failed (closes bgo#587079)
    
    This commit allows to run diff+patch a second time for Subversion if
    'patch' failed (due to ASCII colors) using the external diff tool.
    If the second run also failed, then the user is notified.
    
    Signed-off-by: Cedric Le Dillau <ld c free fr>

 meld/misc.py   |    5 +++--
 meld/vc/svn.py |    9 ++++++++-
 meld/vcview.py |   49 +++++++++++++++++++++++++++++++------------------
 3 files changed, 42 insertions(+), 21 deletions(-)
---
diff --git a/meld/misc.py b/meld/misc.py
index bc0ee37..6434e38 100644
--- a/meld/misc.py
+++ b/meld/misc.py
@@ -239,10 +239,11 @@ def read_pipe_iter(command, errorstream, yield_interval=0.1, workdir=None):
         workdir = None
     return sentinel()()
 
-def write_pipe(command, text):
+def write_pipe(command, text, error=None):
     """Write 'text' into a shell command and discard its stdout output.
     """
-    proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+    proc = subprocess.Popen(command, stdin=subprocess.PIPE,
+                            stdout=subprocess.PIPE, stderr=error)
     proc.communicate(text)
     return proc.wait()
 
diff --git a/meld/vc/svn.py b/meld/vc/svn.py
index 3652f84..ad72a91 100644
--- a/meld/vc/svn.py
+++ b/meld/vc/svn.py
@@ -49,7 +49,11 @@ class Vc(_vc.Vc):
     def commit_command(self, message):
         return [self.CMD,"commit","-m",message]
     def diff_command(self):
-        return [self.CMD,"diff"]
+        if hasattr(self, "external_diff"):
+            return [self.CMD, "diff", "--diff-cmd", self.external_diff]
+        else:
+            return [self.CMD, "diff"]
+
     def update_command(self):
         return [self.CMD,"update"]
     def add_command(self, binary=0):
@@ -66,6 +70,9 @@ class Vc(_vc.Vc):
         else:
             return True
 
+    def switch_to_external_diff(self):
+        self.external_diff = "diff"
+
     def _get_matches(self, directory):
         """return a list of tuples (file_path, status_code, revision)"""
 
diff --git a/meld/vcview.py b/meld/vcview.py
index c9d66e0..e323cee 100644
--- a/meld/vcview.py
+++ b/meld/vcview.py
@@ -373,21 +373,32 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
             self.run_diff( [path] )
 
     def run_diff_iter(self, path_list, empty_patch_ok):
-        yield _("[%s] Fetching differences") % self.label_text
-        difffunc = self._command_iter(self.vc.diff_command(), path_list, 0).next
-        diff = None
-        while type(diff) != type(()):
-            diff = difffunc()
-            yield 1
-        prefix, patch = diff[0], diff[1]
-        yield _("[%s] Applying patch") % self.label_text
-        if patch:
-            self.show_patch(prefix, patch)
-        elif empty_patch_ok:
-            misc.run_dialog( _("No differences found."), parent=self, messagetype=gtk.MESSAGE_INFO)
-        else:
-            for path in path_list:
-                self.emit("create-diff", [path])
+        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
+            difffunc = self._command_iter(self.vc.diff_command(),
+                                          path_list, 0).next
+            diff = None
+            while type(diff) != type(()):
+                diff = difffunc()
+                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
+            elif empty_patch_ok:
+                misc.run_dialog(_("No differences found."), parent=self,
+                                messagetype=gtk.MESSAGE_INFO)
+            else:
+                for path in path_list:
+                    self.emit("create-diff", [path])
 
     def run_diff(self, path_list, empty_patch_ok=0):
         for path in path_list:
@@ -500,7 +511,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
     def on_button_open_clicked(self, obj):
         self._open_files(self._get_selected_files())
 
-    def show_patch(self, prefix, patch):
+    def show_patch(self, prefix, patch, silent=False):
         tmpdir = tempfile.mkdtemp("-meld")
         self.tempdirs.append(tmpdir)
 
@@ -519,10 +530,11 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
             diffs.append( (destfile, pathtofile) )
 
         patchcmd = self.vc.patch_command( tmpdir )
-        if misc.write_pipe(patchcmd, patch) == 0:
+        if misc.write_pipe(patchcmd, patch, error=misc.NULL) == 0:
             for d in diffs:
                 self.emit("create-diff", d)
-        else:
+            return True
+        elif not silent:
             import meldapp
             msg = _("""
                     Invoking 'patch' failed.
@@ -552,6 +564,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
                             " ".join(patchcmd))
             msg = '\n'.join([line.strip() for line in msg.split('\n')])
             misc.run_dialog(msg, parent=self)
+        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]