Permalink
Browse files

Cambios para utilizar las diferencias detectadas por rsync (y evitar una

comparación lenta en remoto) y para usar el algoritmo patience de bazaar

(Deberían ser dos ramas diferentes)
  • Loading branch information...
1 parent 38e3a16 commit d65f554d9ba7aed8efcb9ebe2332b9837b3a9c02 nenopera committed Sep 2, 2011
View
1 README
@@ -0,0 +1 @@
+Meld diff tool using patience algorithm
View
@@ -20,6 +20,7 @@
import gobject
from matchers import MyersSequenceMatcher
+from bzrlib.patiencediff import PatienceSequenceMatcher
################################################################################
#
@@ -76,10 +77,13 @@ class Differ(gobject.GObject):
'diffs-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()),
}
- _matcher = MyersSequenceMatcher
-
- def __init__(self):
+ def __init__(self, algorithm="unified"):
# Internally, diffs are stored from text1 -> text0 and text1 -> text2.
+ self.algorithm = algorithm
+ if (self.algorithm == "unified"):
+ self._matcher = MyersSequenceMatcher
+ else:
+ self._matcher = PatienceSequenceMatcher
gobject.GObject.__init__(self)
self.num_sequences = 0
self.seqlength = [0, 0, 0]
@@ -437,10 +441,14 @@ def set_sequences_iter(self, sequences):
for i in range(self.num_sequences - 1):
matcher = self._matcher(None, sequences[1], sequences[i*2])
- work = matcher.initialise()
- while work.next() is None:
- yield None
- self.diffs[i] = matcher.get_difference_opcodes()
+
+ if (self.algorithm == "unified"):
+ work = matcher.initialise()
+ while work.next() is None:
+ yield None
+ self.diffs[i] = matcher.get_difference_opcodes()
+ else:
+ self.diffs[i] = filter(lambda x: x[0] != "equal", matcher.get_opcodes())
self._initialised = True
self._update_merge_cache(sequences)
yield 1
View
@@ -33,6 +33,7 @@
import re
import stat
import time
+import mtree #Trasladar al modelo
import ui.emblemcellrenderer
@@ -71,7 +72,7 @@ def all_same(lst):
return not lst or lst.count(lst[0]) == len(lst)
-def _files_same(files, regexes):
+def _files_same(files, regexes, model=None):
"""Determine whether a list of files are the same.
Possible results are:
@@ -82,6 +83,12 @@ def _files_same(files, regexes):
FileError: There was a problem reading one or more of the files
"""
+ if model != None:
+ if all([model.rsync_tree.contains_path(re.sub("^"+model.locations[i]+"/?","",files[i])) for i in range(min(len(files),len(model.locations)))]):
+ return Different
+ else:
+ return Same
+
# One file is the same as itself
if len(files) < 2:
return Same
@@ -219,7 +226,7 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
tree.STATE_MISSING: "delete",
}
- def __init__(self, prefs, num_panes):
+ def __init__(self, prefs, num_panes, rsync_file=None):
melddoc.MeldDoc.__init__(self, prefs)
gnomeglade.Component.__init__(self, paths.ui_dir("dirdiff.ui"), "dirdiff")
@@ -259,7 +266,7 @@ def __init__(self, prefs, num_panes):
self.map_widgets_into_lists(["treeview", "fileentry", "scrolledwindow",
"diffmap", "linkmap", "msgarea_mgr",
"vbox"])
- self.set_num_panes(num_panes)
+ self.set_num_panes(num_panes, rsync_file)
self.focus_in_events = []
self.focus_out_events = []
for treeview in self.treeview:
@@ -434,6 +441,7 @@ def on_fileentry_activate(self, entry):
def set_locations(self, locations):
self.set_num_panes(len(locations))
locations = [os.path.abspath(l or ".") for l in locations]
+ self.model.locations = locations
self.model.clear()
for pane, loc in enumerate(locations):
self.fileentry[pane].set_filename(loc)
@@ -564,6 +572,7 @@ def _search_recursively_iter(self, rootpath):
differences |= self._update_item_state(child)
else: # directory is empty, add a placeholder
self.model.add_empty(it)
+
if differences:
expanded.add(path)
@@ -874,7 +883,7 @@ def _filter_on_state(self, roots, fileslist):
is_present = [ os.path.exists( f ) for f in curfiles ]
all_present = 0 not in is_present
if all_present:
- if _files_same(curfiles, regexes) in (Same, SameFiltered):
+ if _files_same(curfiles, regexes,self.model) in (Same, SameFiltered):
state = tree.STATE_NORMAL
else:
state = tree.STATE_MODIFIED
@@ -895,22 +904,28 @@ def mtime(f):
return os.stat(f).st_mtime
except OSError:
return 0
+
# find the newest file, checking also that they differ
mod_times = [ mtime(f) for f in files[:self.num_panes] ]
newest_index = mod_times.index( max(mod_times) )
if mod_times.count( max(mod_times) ) == len(mod_times):
newest_index = -1 # all same
all_present = 0 not in mod_times
+
+ # En este punto compara si los dos directorios o archivos existen.
+ # Ver lo que hace cuando es igual y utilizarlo con la lista pasada de
+ # diferencias, (asi no entrara en la mayoria de directorios) (ojo a ver si no los rellena tampoco)
+
if all_present:
- all_same = _files_same(files, regexes)
+ all_same = _files_same(files, regexes, self.model)
all_present_same = all_same
else:
lof = []
for j in range(len(mod_times)):
if mod_times[j]:
lof.append( files[j] )
all_same = Different
- all_present_same = _files_same(lof, regexes)
+ all_present_same = _files_same(lof, regexes, self.model)
different = 1
one_isdir = [None for i in range(self.model.ntree)]
for j in range(self.model.ntree):
@@ -999,9 +1014,11 @@ def recurse_tree_states(rowiter):
chunkstart, laststate = index, state
return tree_state_iter
- def set_num_panes(self, n):
+ def set_num_panes(self, n, rsync_file=None):
if n != self.num_panes and n in (1,2,3):
self.model = DirDiffTreeStore(n)
+ self.model.rsync_tree = mtree.parse_rsync_file(rsync_file)
+
for i in range(n):
self.treeview[i].set_model(self.model)
View
@@ -53,15 +53,20 @@ class CachedSequenceMatcher(object):
eviction is overly simplistic, but is okay for our usage pattern.
"""
- def __init__(self):
+ def __init__(self, algorithm="unified"):
self.cache = {}
+ self.algorithm = algorithm
def __call__(self, text1, textn):
try:
self.cache[(text1, textn)][1] = time.time()
return self.cache[(text1, textn)][0]
except KeyError:
- matcher = matchers.MyersSequenceMatcher(None, text1, textn)
+ from bzrlib.patiencediff import PatienceSequenceMatcher
+ if (self.algorithm == "patience"):
+ matcher = PatienceSequenceMatcher(None, text1, textn)
+ else:
+ matcher = matchers.MyersSequenceMatcher(None, text1, textn)
opcodes = matcher.get_opcodes()
self.cache[(text1, textn)] = [opcodes, time.time()]
return opcodes
@@ -209,9 +214,10 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
'action-mode-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (int,)),
}
- def __init__(self, prefs, num_panes):
+ def __init__(self, prefs, num_panes, algorithm="unified"):
"""Start up an filediff with num_panes empty contents.
"""
+ self.algorithm=algorithm
melddoc.MeldDoc.__init__(self, prefs)
gnomeglade.Component.__init__(self, paths.ui_dir("filediff.ui"), "filediff")
self.map_widgets_into_lists(["textview", "fileentry", "diffmap", "scrolledwindow", "linkmap", "statusimage", "msgarea_mgr", "vbox"])
@@ -250,7 +256,7 @@ def __init__(self, prefs, num_panes):
self._sync_vscroll_lock = False
self._sync_hscroll_lock = False
self._scroll_lock = False
- self.linediffer = self.differ()
+ self.linediffer = self.differ(self.algorithm)
self.linediffer.ignore_blanks = self.prefs.ignore_blank_lines
self.in_nested_action = False
self.in_nested_textview_gutter_expose = False
@@ -539,7 +545,7 @@ def pull_all_non_conflicting_changes(self, direction):
dst = self._get_focused_pane()
src = dst + direction
assert src in range(self.num_panes)
- merger = merge.Merger()
+ merger = merge.Merger(self.algorithm)
merger.differ = self.linediffer
merger.texts = self.buffer_texts
for mergedfile in merger.merge_2_files(src, dst):
@@ -555,7 +561,7 @@ def resync():
def merge_all_non_conflicting_changes(self):
dst = 1
- merger = merge.Merger()
+ merger = merge.Merger(self.algorithm)
merger.differ = self.linediffer
merger.texts = self.buffer_texts
for mergedfile in merger.merge_3_files(False):
View
@@ -26,8 +26,8 @@ class FileMerge(filediff.FileDiff):
differ = merge.AutoMergeDiffer
- def __init__(self, prefs, num_panes):
- filediff.FileDiff.__init__(self, prefs, num_panes)
+ def __init__(self, prefs, num_panes, algorithm="unified"):
+ filediff.FileDiff.__init__(self, prefs, num_panes, algorithm)
self.hidden_textbuffer = gtk.TextBuffer()
def _connect_buffer_handlers(self):
@@ -75,7 +75,7 @@ def _merge_files(self):
lines = [x.split("\n") for x in panetext]
filteredpanetext = [self._filter_text(p) for p in panetext]
filteredlines = [x.split("\n") for x in filteredpanetext]
- merger = merge.Merger()
+ merger = merge.Merger(self.algorithm)
step = merger.initialize(filteredlines, lines)
while step.next() == None:
yield 1
View
@@ -15,7 +15,7 @@
### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import difflib
-
+from bzrlib.patiencediff import PatienceSequenceMatcher
def find_common_prefix(a, b):
if not a or not b:
View
@@ -160,20 +160,14 @@ def parse_args(self, rawargs):
parser = optparse.OptionParser(
usage=usage,
- description=_("Meld is a file and directory comparison tool."),
- version="%prog " + version)
- parser.add_option("-L", "--label", action="append", default=[],
- help=_("Set label to use instead of file name"))
- parser.add_option("-a", "--auto-compare", action="store_true", default=False,
- help=_("Automatically compare all differing files on startup"))
- parser.add_option("-u", "--unified", action="store_true",
- help=_("Ignored for compatibility"))
- parser.add_option("-o", "--output", action="store", type="string",
- dest="outfile", default=None,
- help=_("Set the target file for saving a merge result"))
- parser.add_option("", "--diff", action="callback", callback=self.diff_files_callback,
- dest="diff", default=[],
- help=_("Creates a diff tab for up to 3 supplied files or directories."))
+ description=_("Meld is a file and directory comparison tool."), version="%prog " + version)
+ parser.add_option("-L", "--label", action="append", default=[], help=_("Set label to use instead of file name"))
+ parser.add_option("-a", "--auto-compare", action="store_true", default=False, help=_("Automatically compare all differing files on startup"))
+ parser.add_option("-u", "--unified", action="store_true", help=_("Ignored for compatibility"))
+ parser.add_option("--rsync-list", action="store", type="string", dest="rsync_list", help=_("Fixed list of different files"))
+ parser.add_option("--algorithm", action="store", type="choice", dest="algorithm", choices=("unified","raw","patience"), default="unified", help=_("Algorithm for comparing files"))
+ parser.add_option("-o", "--output", action="store", type="string", dest="outfile", default=None, help=_("Set the target file for saving a merge result"))
+ parser.add_option("--diff", action="callback", callback=self.diff_files_callback, dest="diff", default=[], help=_("Creates a diff tab for up to 3 supplied files or directories."))
options, args = parser.parse_args(rawargs)
if len(args) > 4:
parser.error(_("too many arguments (wanted 0-4, got %d)") % len(args))
@@ -185,7 +179,7 @@ def parse_args(self, rawargs):
parser.error(_("can't compare more than three directories"))
self.window.open_paths(files)
- tab = self.window.open_paths(args, options.auto_compare)
+ tab = self.window.open_paths(args, options.auto_compare, options.rsync_list, options.algorithm)
if tab:
tab.set_labels(options.label)
View
@@ -584,22 +584,22 @@ def _append_page(self, page, icon):
# Allow reordering of tabs
self.notebook.set_tab_reorderable(page.widget, True);
- def append_dirdiff(self, dirs, auto_compare=False):
+ def append_dirdiff(self, dirs, auto_compare=False, rsync_list=None):
assert len(dirs) in (1,2,3)
- doc = dirdiff.DirDiff(app.prefs, len(dirs))
+ doc = dirdiff.DirDiff(app.prefs, len(dirs), rsync_list)
self._append_page(doc, "folder")
doc.set_locations(dirs)
# FIXME: This doesn't work, as dirdiff behaves differently to vcview
if auto_compare:
doc.on_button_diff_clicked(None)
return doc
- def append_filediff(self, files):
+ def append_filediff(self, files, algorithm=None):
assert len(files) in (1, 2, 3, 4)
if len(files) == 4:
doc = filemerge.FileMerge(app.prefs, 3)
else:
- doc = filediff.FileDiff(app.prefs, len(files))
+ doc = filediff.FileDiff(app.prefs, len(files), algorithm)
seq = doc.undosequence
seq.clear()
seq.connect("can-undo", self.on_can_undo)
@@ -608,7 +608,7 @@ def append_filediff(self, files):
doc.set_files(files)
return doc
- def append_diff(self, paths, auto_compare=False):
+ def append_diff(self, paths, auto_compare=False, rsync_list=None, algorithm=None):
dirslist = [p for p in paths if os.path.isdir(p)]
fileslist = [p for p in paths if os.path.isfile(p)]
if dirslist and fileslist:
@@ -631,9 +631,9 @@ def append_diff(self, paths, auto_compare=False):
builtfilelist.append(elem)
return self.append_filediff(builtfilelist)
elif dirslist:
- return self.append_dirdiff(paths, auto_compare)
+ return self.append_dirdiff(paths, auto_compare, rsync_list)
else:
- return self.append_filediff(paths)
+ return self.append_filediff(paths, algorithm)
def append_vcview(self, location, auto_compare=False):
doc = vcview.VcView(app.prefs)
@@ -655,7 +655,7 @@ def cleanup():
doc.connect("create-diff", lambda obj,arg: self.append_diff(arg))
doc.run_diff([path])
- def open_paths(self, paths, auto_compare=False):
+ def open_paths(self, paths, auto_compare=False, rsync_list=None, algorithm=None):
tab = None
if len(paths) == 1:
a = paths[0]
@@ -665,7 +665,7 @@ def open_paths(self, paths, auto_compare=False):
tab = self.append_vcview(a, auto_compare)
elif len(paths) in (2, 3, 4):
- tab = self.append_diff(paths, auto_compare)
+ tab = self.append_diff(paths, auto_compare, rsync_list, algorithm)
return tab
def current_doc(self):
View
@@ -21,11 +21,14 @@
class AutoMergeDiffer(diffutil.Differ):
- _matcher = matchers.MyersSequenceMatcher
- # _matcher = PatienceSequenceMatcher
- def __init__(self):
- diffutil.Differ.__init__(self)
+ def __init__(self, algorithm="unified"):
+ diffutil.Differ.__init__(self, algorithm)
+ self.algorithm = algorithm
+ if (sellf.algorithm == "unified"):
+ _matcher = matchers.MyersSequenceMatcher
+ else:
+ _matcher = PatienceSequenceMatcher
self.auto_merge = False
self.unresolved = []
@@ -162,8 +165,8 @@ def get_unresolved_count(self):
class Merger(diffutil.Differ):
- def __init__(self, ):
- self.differ = AutoMergeDiffer()
+ def __init__(self, algorithm="unified"):
+ self.differ = AutoMergeDiffer(algorithm)
self.differ.auto_merge = True
self.differ.unresolved = []
self.texts = []
Oops, something went wrong.

0 comments on commit d65f554

Please sign in to comment.