[Checkins] SVN: zope.fssync/trunk/src/zope/fssync/ Add support for avoiding conflicts in certain types of merge opertions

Amos Latteier amos at latteier.com
Tue Mar 10 14:21:54 EDT 2009


Log message for revision 97814:
  Add support for avoiding conflicts in certain types of merge opertions 
  by ignoring local changes.
  

Changed:
  U   zope.fssync/trunk/src/zope/fssync/CHANGES.txt
  U   zope.fssync/trunk/src/zope/fssync/fsmerger.py
  U   zope.fssync/trunk/src/zope/fssync/tests/test_fsmerger.py

-=-
Modified: zope.fssync/trunk/src/zope/fssync/CHANGES.txt
===================================================================
--- zope.fssync/trunk/src/zope/fssync/CHANGES.txt	2009-03-10 18:00:07 UTC (rev 97813)
+++ zope.fssync/trunk/src/zope/fssync/CHANGES.txt	2009-03-10 18:21:53 UTC (rev 97814)
@@ -10,6 +10,10 @@
       when adding multiple objects at the same time that depend on
       each other. Callbacks can in turn return callbacks.
 
+    - Add support to FSMerger to allow locally modified files to be
+      overwritten by files returned from the server. The purpose of
+      this is to avoid conflicts after commit on files that are
+      formatted differently on the server from local versions.
 
   After Zope 3.4.0b1 (trunk only)
 

Modified: zope.fssync/trunk/src/zope/fssync/fsmerger.py
===================================================================
--- zope.fssync/trunk/src/zope/fssync/fsmerger.py	2009-03-10 18:00:07 UTC (rev 97813)
+++ zope.fssync/trunk/src/zope/fssync/fsmerger.py	2009-03-10 18:21:53 UTC (rev 97814)
@@ -29,9 +29,13 @@
 
 class FSMerger(object):
 
-    """Higher-level three-way file and directory merger."""
+    """Higher-level three-way file and directory merger.
 
-    def __init__(self, metadata, reporter):
+    If overwrite_local is True, then local should be replaced with
+    the remote, regardless of local changes.
+    """
+
+    def __init__(self, metadata, reporter, overwrite_local=False):
         """Constructor.
 
         Arguments are a metadata database and a reporting function.
@@ -39,6 +43,7 @@
         self.metadata = metadata
         self.reporter = reporter
         self.merger = Merger(metadata)
+        self.overwrite_local = overwrite_local
 
     def merge(self, local, remote):
         """Merge remote file or directory into local file or directory."""
@@ -155,7 +160,6 @@
 
     def merge_files(self, local, remote):
         """Merge remote file into local file."""
-
         # Reset sticky conflict if file was removed
         entry = self.metadata.getentry(local)
         conflict = entry.get("conflict")
@@ -164,6 +168,9 @@
 
         original = fsutil.getoriginal(local)
         action, state = self.merger.classify_files(local, original, remote)
+        if action == 'Merge' and state == 'Modified' and self.overwrite_local:
+            action = 'Copy'
+            state = 'Uptodate'
         state = self.merger.merge_files(local, original, remote,
                                         action, state) or state
         self.reportaction(action, state, local)

Modified: zope.fssync/trunk/src/zope/fssync/tests/test_fsmerger.py
===================================================================
--- zope.fssync/trunk/src/zope/fssync/tests/test_fsmerger.py	2009-03-10 18:00:07 UTC (rev 97813)
+++ zope.fssync/trunk/src/zope/fssync/tests/test_fsmerger.py	2009-03-10 18:21:53 UTC (rev 97814)
@@ -211,10 +211,11 @@
                   localentry, remoteentry,
                   expected_reports_template,
                   expected_localdata, expected_origdata, expected_remotedata,
-                  expected_localentry, expected_remoteentry):
+                  expected_localentry, expected_remoteentry,
+                  overwrite_local=False):
         # Generic test setup to test merging files
         reports = []
-        m = FSMerger(self.metadata, reports.append)
+        m = FSMerger(self.metadata, reports.append, overwrite_local)
 
         localtopdir = self.tempdir()
         remotetopdir = self.tempdir()
@@ -467,6 +468,64 @@
                        None, None, None,
                        {}, {})
 
+
+    def test_overwrite_local(self):
+        # make sure that we normally get a conflict when the orginal,
+        # local, and remote versions are different
+        conflict = "<<<<<<< %l\nl\n=======\nr\n>>>>>>> %r\n"
+        self.mergetest("foo", "l\n", "a\n", "r\n", self.entry, self.entry,
+                       ["C %l"], conflict, "r\n", "r\n",
+                       self.make_conflict_entry, self.entry)
+
+        # now try to same thing but with overwrite_local set to
+        # true. This time the local and original should be replaced
+        # with the remote file.
+        self.mergetest("foo", "l\n", "a\n", "r\n", self.entry, self.entry,
+                       ["U %l"], "r\n", "r\n", "r\n",
+                       self.entry, self.entry, True)
+
+        # try it when the original and local are the same, but the
+        # remote is different. In this case the overwrite_local
+        # setting doesn't change things.
+        self.mergetest("foo", "a\n", "a\n", "r\n", self.entry, self.entry,
+                       ["U %l"], "r\n", "r\n", "r\n",
+                       self.entry, self.entry, True)
+
+        self.mergetest("foo", "a\n", "a\n", "r\n", self.entry, self.entry,
+                       ["U %l"], "r\n", "r\n", "r\n",
+                       self.entry, self.entry)
+
+        # testing if remote is the same as local. Again,
+        # overwrite_local shouldn't change things.
+        self.mergetest("foo", "l\n", "a\n", "l\n", self.entry, self.entry,
+                       ["U %l"], "l\n", "l\n", "l\n",
+                       self.entry, self.entry, True)
+
+        self.mergetest("foo", "l\n", "a\n", "l\n", self.entry, self.entry,
+                       ["U %l"], "l\n", "l\n", "l\n",
+                       self.entry, self.entry)
+
+        # How about when all are the same? Again overwrite_local
+        # shouldn't change anything.
+        self.mergetest("foo", "a\n", "a\n", "a\n", self.entry, self.entry,
+                       [], "a\n", "a\n", "a\n",
+                       self.entry, self.entry, True)
+
+        self.mergetest("foo", "a\n", "a\n", "a\n", self.entry, self.entry,
+                       [], "a\n", "a\n", "a\n",
+                       self.entry, self.entry)
+
+        # test when original and remote are the same. Again,
+        # overwrite_local shouldn't make any difference.
+        self.mergetest("foo", "l\n", "a\n", "a\n", self.entry, self.entry,
+                       ["M %l"], "l\n", "a\n", "a\n",
+                       self.entry, self.entry, True)
+
+        self.mergetest("foo", "l\n", "a\n", "a\n", self.entry, self.entry,
+                       ["M %l"], "l\n", "a\n", "a\n",
+                       self.entry, self.entry)
+
+
 def test_suite():
     s = unittest.TestSuite()
     s.addTest(unittest.makeSuite(TestFSMerger))



More information about the Checkins mailing list