new extension: fetch -> combine pull and merge/update
authorVadim Gelfer <vadim.gelfer@gmail.com>
Mon, 07 Aug 2006 17:27:38 -0700
changeset 2800 135823f37304
parent 2799 bd8a9a94139f
child 2801 bd4dada96c2e
new extension: fetch -> combine pull and merge/update pull changes from remote repo. if changes add new head: merge with new head, commit result. else: update working dir to new head. this makes useful command like git 'pull' command.
hgext/fetch.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/fetch.py	Mon Aug 07 17:27:38 2006 -0700
@@ -0,0 +1,90 @@
+# fetch.py - pull and merge remote changes
+#
+# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+
+from mercurial.demandload import *
+from mercurial.i18n import gettext as _
+from mercurial.node import *
+demandload(globals(), 'mercurial:commands,hg,node')
+
+def fetch(ui, repo, source='default', **opts):
+    '''Pull changes from a remote repository, merge new changes if needed.
+
+    This finds all changes from the repository at the specified path
+    or URL and adds them to the local repository.
+
+    If the pulled changes add a new head, the head is automatically
+    merged, and the result of the merge is committed.  Otherwise, the
+    working directory is updated.'''
+
+    def postincoming(other, modheads):
+        if modheads == 0:
+            return 0
+        if modheads == 1:
+            return commands.doupdate(ui, repo)
+        newheads = repo.heads(parent)
+        newchildren = [n for n in repo.heads(parent) if n != parent]
+        newparent = parent
+        if newchildren:
+            commands.doupdate(ui, repo, node=hex(newchildren[0]))
+            newparent = newchildren[0]
+        newheads = [n for n in repo.heads() if n != newparent]
+        err = False
+        if newheads:
+            ui.status(_('merging with new head %d:%s\n') %
+                      (repo.changelog.rev(newheads[0]), short(newheads[0])))
+            err = repo.update(newheads[0], allow=True, remind=False)
+        if not err and len(newheads) > 1:
+            ui.status(_('not merging with %d other new heads '
+                        '(use "hg heads" and "hg merge" to merge them)') %
+                      (len(newheads) - 1))
+        if not err:
+            mod, add, rem = repo.status()[:3]
+            message = (commands.logmessage(opts) or
+                       (_('Automated merge with %s') % other.url()))
+            n = repo.commit(mod + add + rem, message,
+                            opts['user'], opts['date'],
+                            force_editor=opts.get('force_editor'))
+            ui.status(_('new changeset %d:%s merges remote changes '
+                        'with local\n') % (repo.changelog.rev(n),
+                                           short(n)))
+    def pull():
+        commands.setremoteconfig(ui, opts)
+
+        other = hg.repository(ui, ui.expandpath(source))
+        ui.status(_('pulling from %s\n') % source)
+        revs = None
+        if opts['rev'] and not other.local():
+            raise util.Abort(_("fetch -r doesn't work for remote repositories yet"))
+        elif opts['rev']:
+            revs = [other.lookup(rev) for rev in opts['rev']]
+        modheads = repo.pull(other, heads=revs)
+        return postincoming(other, modheads)
+        
+    parent, p2 = repo.dirstate.parents()
+    if parent != repo.changelog.tip():
+        raise util.Abort(_('working dir not at tip '
+                           '(use "hg update" to check out tip)'))
+    if p2 != nullid:
+        raise util.Abort(_('outstanding uncommitted merge'))
+    if len(repo.heads()) > 1:
+        raise util.Abort(_('multiple heads in this repository '
+                           '(use "hg heads" and "hg merge" to merge them)'))
+    return pull()
+
+cmdtable = {
+    'fetch':
+    (fetch,
+     [('e', 'ssh', '', _('specify ssh command to use')),
+      ('m', 'message', '', _('use <text> as commit message')),
+      ('l', 'logfile', '', _('read the commit message from <file>')),
+      ('d', 'date', '', _('record datecode as commit date')),
+      ('u', 'user', '', _('record user as commiter')),
+      ('r', 'rev', [], _('a specific revision you would like to pull')),
+      ('f', 'force-editor', None, _('edit commit message')),
+      ('', 'remotecmd', '', _('hg command to run on the remote side'))],
+     'hg fetch [SOURCE]'),
+    }