]> scripts.mit.edu Git - wizard.git/commitdiff
Implement MediaWiki scaffolding for auto conflict resolution; untested.
authorEdward Z. Yang <ezyang@mit.edu>
Sat, 10 Oct 2009 06:39:52 +0000 (02:39 -0400)
committerEdward Z. Yang <ezyang@mit.edu>
Sat, 10 Oct 2009 06:39:52 +0000 (02:39 -0400)
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
wizard/app/mediawiki.py
wizard/command/upgrade.py
wizard/deploy.py
wizard/resolve.py
wizard/tests/resolve_test.py

index 3fdec143f66fce2a0da23cbb42f939ad021e3cd6..e356c8f8eb1f389ec83b48819a3afb83bc29690f 100644 (file)
@@ -6,7 +6,7 @@ import logging
 import shlex
 import shutil
 
-from wizard import app, deploy, install, scripts, shell, util
+from wizard import app, deploy, install, resolve, scripts, shell, util
 from wizard.app import php
 
 def make_filename_regex(var):
@@ -26,6 +26,13 @@ seed = {
         'WIZARD_SECRETKEY': ('wgSecretKey', 'wgProxyKey'),
         }
 
+resolutions = {
+#'LocalSettings.php': [
+#    ("""
+#""", [])
+#    ]
+}
+
 class Application(deploy.Application):
     parametrized_files = ['LocalSettings.php', 'php.ini']
     deprecated_keys = set(['WIZARD_IP']) | php.deprecated_keys
@@ -59,6 +66,24 @@ class Application(deploy.Application):
         if type(out) is list:
             out.append(page)
         return page.find("<!-- Served") != -1
+    def resolveConflicts(self, dir):
+        # XXX: this is pretty generic
+        resolved = True
+        with util.ChangeDirectory(dir):
+            sh = shell.Shell()
+            for file in sh.eval("git", "ls-files", "--unmerged").splitlines():
+                if file in resolutions:
+                    contents = open(file, "r").read()
+                    for spec, result in resolutions:
+                        contents = resolve.resolve(contents, spec, result)
+                    if not resolve.is_conflict(contents):
+                        open(file, "w").write(contents)
+                        sh.call("git", "add", file)
+                    else:
+                        resolved = False
+                else:
+                    resolved = False
+        return resolved
     def install(self, version, options):
         try:
             os.unlink("LocalSettings.php")
index 041cd80a275d4e1df5b458db2177ba7f2e503ca6..da15d56c6e948b3dd88a5b5f408d8c398f5cd825 100644 (file)
@@ -204,7 +204,13 @@ def perform_merge(sh, repo, d, version, use_shm):
     try:
         sh.call("git", "merge", next_virtual_commit)
     except shell.CallError:
+        # Run the application's specific merge resolution algorithms
+        # and see if we can salvage it
         curdir = os.getcwd()
+        if d.application.resolveConflicts(curdir):
+            logging.info("Resolved conflicts with application specific knowledge")
+            sh.call("git", "commit", "-a", "-m", "merge")
+            return
         logging.info("Conflict info:\n", sh.eval("git", "diff"))
         if use_shm:
             # Keeping all of our autoinstalls in shared memory is
index 366fcfaa78d0d6cf2f3f9b372feb033202a2ee9e..bdea87e4385cd20421866a7276d0e0ca506a61e1 100644 (file)
@@ -373,6 +373,14 @@ class Application(object):
                 contents = contents.replace(key, value)
             f = open(fullpath, "w")
             f.write(contents)
+    def resolveConflicts(self, dir):
+        """
+        Takes a directory with conflicted files and attempts to
+        resolve them.  Returns whether or not all conflicted
+        files were resolved or not.  Fully resolved files are
+        added to the index, but no commit is made.
+        """
+        return False
     def prepareConfig(self, deployment):
         """
         Takes a deployment and replaces any explicit instances
index e2de1f217bce12bb16a0b41e33e73eabeae358b8..ae178d57a4ba700e600a304a183376d54ccbba3b 100644 (file)
@@ -97,7 +97,10 @@ def result_to_repl(result, mappings):
 
 def resolve(contents, spec, result):
     rstring, mappings = spec_to_regex(spec)
-    print rstring
     regex = re.compile(rstring, re.DOTALL)
     repl = result_to_repl(result, mappings)
     return regex.sub(repl, contents)
+
+def is_conflict(contents):
+    # Really really simple heuristic
+    return "<<<<<<<" in contents
index 39bd32c8ffc5d0306f5be55b72a8c60d24286d6d..65e17d4d7b7a05144d0f89aff802d22d2cd35bcd 100644 (file)
@@ -81,3 +81,7 @@ blah blah
 top
 the user is right
 """
+
+def test_is_conflict():
+    assert not resolve.is_conflict("foobar\nbar")
+    assert resolve.is_conflict("bar\n<<<<<<< HEAD\n=======\n>>>>>>> abcd\nbar")