1. Graham Helliwell
  2. hg sync

Commits

Graham Helliwell  committed c3bfb3c

More refactoring, Synchronizer has its own copy of opts, and therefore is more of a single-usage class.

  • Participants
  • Parent commits ffb35c1
  • Branches default

Comments (0)

Files changed (1)

File sync.py

View file
 
     Returns 0 on success.
     """
-
-    synchronizer = Synchronizer(ui, repo, source)
     date = opts.get('date')
     if date:
         opts['date'] = util.parsedate(date)
-
-    synchronizer.dosync(opts)
+    synchronizer = Synchronizer(ui, repo, source, opts)
+    synchronizer.dosync()
 
 class Synchronizer:
-    def __init__(self, ui, repo, source):
+    def __init__(self, ui, repo, source, opts):
         self.ui = ui
         self.repo = repo
         self.source = source
+        self.opts = opts
+        self.remoterepository = hg.peer(repo, opts, ui.expandpath(source))
 
-    def dosync(self, opts):
+    def dosync(self):
         """pull changes from a remote repository, merge new changes if needed.
 
         This finds all changes from the repository at the specified path
         Returns 0 on success.
         """
 
-        ui = self.ui
-        repo = self.repo
-
-        parent, p2 = repo.dirstate.parents()
-        branch = repo.dirstate.branch()
+        initialrevision, p2 = self.repo.dirstate.parents()
 
         if p2 != nullid:
             raise util.Abort(_('outstanding uncommitted merge'))
 
         wlock = lock = None
         try:
-            wlock = repo.wlock()
-            lock = repo.lock()
+            wlock = self.repo.wlock()
+            lock = self.repo.lock()
 
-            #pull
-            remoterepository = hg.peer(repo, opts, ui.expandpath(self.source))
+            self.dopull()
 
-            ui.status(_('pulling from %s\n') % util.hidepassword(ui.expandpath(self.source)))
-            repo.pull(remoterepository)
-            ui.write('pull complete\n')
-            mod, add, rem, del_ = repo.status()[:4]
+            self.raiseifuncleanstatus()
 
-            if mod or add or rem or del_:
-                raise util.Abort('outstanding uncommitted changes, push skipped, not in sync\n')
+            self.updateormerge(initialrevision)
 
+            self.push()
 
-            bheads = repo.branchheads(branch)
-            bheads = [head for head in bheads if len(repo[head].children()) == 0]
-            if len(bheads) > 2:
-                ui.status(_('not merging with %d remote repository new branch heads '
-                            '(use "hg heads ." and "hg merge" to merge them)\n') %
-                          (len(bheads) - 1))
-                raise util.Abort('push skipped, not in sync\n')
-
-            # Is this a simple fast-forward along the current branch?
-            newheads = repo.branchheads(branch)
-            newchildren = repo.changelog.nodesbetween([parent], newheads)[2]
-            if len(newheads) == 1 and len(newchildren) and  newchildren[0] != parent:
-                ui.status('updating local repository')
-                updatefailed =  hg.update(repo, newchildren[0]) #Returns true if unresolved conflicts exist
-                if updatefailed:
-                    ui.status('merge conflicts occurred, update skipped\n')
-                    raise util.Abort('push skipped, not in sync\n')
-            elif len(newheads) > 1:
-                # Otherwise, let's merge.
-                # By default, we consider the repository we're pulling
-                # *from* as authoritative, so we merge our changes into
-                # theirs.
-                if opts['switch_parent']:
-                    firstparent, secondparent = parent, newheads[0]
-                else:
-                    firstparent, secondparent = newheads[0], parent
-                    self.updateClean(firstparent)
-
-                ui.status(_('merging with %d:%s\n') %
-                          (repo.changelog.rev(secondparent), short(secondparent)))
-                # We want ui.merge internal:prompt
-                if not hg.merge(repo, secondparent, remind=False):
-                    ui.status('')
-                    if not ui.promptchoice(_('Merge failed, do you want to revert [Y/n]: '), ['&Yes', '&No']):
-                        self.updateClean(firstparent)
-                        raise util.Abort('merge failed and reverted, please merge remaining heads manually and sync again')
-                    else:
-                        raise util.Abort('merge failed, please resolve remaining merge conflicts manually, commit and sync again')
-
-                # we don't translate commit messages
-                message = (cmdutil.logmessage(ui, opts) or
-                           ('Automated merge with %s' %
-                            urllib2.unquote(util.removeauth(remoterepository.url()))))
-                editor = cmdutil.commiteditor
-                if opts.get('edit'):
-                    editor = cmdutil.commitforceeditor
-                n = repo.commit(message, opts['user'], opts['date'], editor=editor)
-                ui.status(_('new changeset %d:%s merges remote changes '
-                            'with local\n') % (repo.changelog.rev(n),
-                                               short(n)))
-
-            ui.status(_('pushing to %s\n') % util.hidepassword(ui.expandpath(self.source)))
-            if repo.push(remoterepository) == 1:
-                raise util.Abort('push failed, please check your synchronization settings')
-            ui.status('push complete\n')
-            ui.status('sync complete\n')
+            self.ui.status('sync complete\n')
 
 
         finally:
             release(lock, wlock)
 
+    def dopull(self):
+        self.ui.status(_('pulling from %s\n') % util.hidepassword(self.ui.expandpath(self.source)))
+        self.repo.pull(self.remoterepository)
+        self.ui.write('pull complete\n')
+
+    def raiseifuncleanstatus(self):
+        mod, add, rem, del_ = self.repo.status()[:4]
+        if mod or add or rem or del_:
+            raise util.Abort('outstanding uncommitted changes, push skipped, not in sync\n')
+
+    def updateormerge(self, initialrevision):
+        branch = self.repo.dirstate.branch()
+        heads = self.repo.branchheads(branch)
+        bheads = [head for head in heads if len(self.repo[head].children()) == 0]
+        if len(bheads) > 2:
+            self.ui.status(_('not merging with %d remote repository new branch heads '
+                        '(use "hg heads ." and "hg merge" to merge them)\n') %
+                      (len(bheads) - 1))
+            raise util.Abort('push skipped, not in sync\n')
+
+        # Is this a simple fast-forward along the current branch?
+        newchildren = self.repo.changelog.nodesbetween([initialrevision], heads)[2]
+        if len(heads) == 1 and len(newchildren) and  newchildren[0] != initialrevision:
+            self.ui.status('updating local repository')
+            updatefailed =  hg.update(self.repo, newchildren[0]) #Returns true if unresolved conflicts exist
+            if updatefailed:
+                self.ui.status('merge conflicts occurred, update skipped\n')
+                raise util.Abort('push skipped, not in sync\n')
+        elif len(heads) > 1:
+            # Otherwise, let's merge.
+            # By default, we consider the repository we're pulling
+            # *from* as authoritative, so we merge our changes into
+            # theirs.
+            if self.opts['switch_parent']:
+                firstparent, secondparent = initialrevision, heads[0]
+            else:
+                firstparent, secondparent = heads[0], initialrevision
+                self.updateClean(firstparent)
+
+            self.merge(initialrevision, secondparent)
+            self.commitmerge(self.remoterepository, self.opts)
 
     def updateClean(self, revision):
         self.ui.status(_('updating to %d:%s\n') %
                    short(revision)))
         hg.clean(self.repo, revision)
 
+    def merge(self, initialrevision, other):
+        self.ui.status(_('merging with %d:%s\n') %
+                  (self.repo.changelog.rev(other), short(other)))
+
+        if not hg.merge(self.repo, other, remind=False):
+            self.ui.status('')
+            if not self.ui.promptchoice(_('Merge failed, do you want to revert [Y/n]: '), ['&Yes', '&No']):
+                self.updateClean(initialrevision)
+                raise util.Abort('merge failed and reverted, please merge remaining heads manually and sync again')
+            else:
+                raise util.Abort('merge failed, please resolve remaining merge conflicts manually, commit and sync again')
+
+    def commitmerge(self, opts):
+        message = (cmdutil.logmessage(self.ui, opts) or
+                   ('Automated merge with %s' %
+                    urllib2.unquote(util.removeauth(self.remoterepository.url()))))
+        editor = cmdutil.commiteditor
+        if opts.get('edit'):
+            editor = cmdutil.commitforceeditor
+        n = self.repo.commit(message, opts['user'], opts['date'], editor=editor)
+        self.ui.status(_('new changeset %d:%s merges remote changes '
+                    'with local\n') % (self.repo.changelog.rev(n),
+                                       short(n)))
+
+    def push(self):
+        self.ui.status(_('pushing to %s\n') % util.hidepassword(self.ui.expandpath(self.source)))
+        if self.repo.push(self.remoterepository) == 1:
+            raise util.Abort('push failed, please check your synchronization settings')
+        self.ui.status('push complete\n')
+
+
+
 cmdtable = {
     'sync':
         (sync,