merge with crew.
authorVadim Gelfer <vadim.gelfer@gmail.com>
Fri, 28 Jul 2006 10:47:02 -0700
changeset 2721 d1fa79e7b07e
parent 2718 a593813241e5 (current diff)
parent 2720 c91ca61c8953 (diff)
child 2722 10e95059ffd7
merge with crew.
--- a/hgext/mq.py	Fri Jul 28 18:46:02 2006 +0200
+++ b/hgext/mq.py	Fri Jul 28 10:47:02 2006 -0700
@@ -38,7 +38,8 @@
 
 repomap = {}
 
-commands.norepo += " qversion"
+commands.norepo += " qclone qversion"
+
 class queue:
     def __init__(self, ui, path, patchdir=None):
         self.basepath = path
@@ -1177,6 +1178,52 @@
         r.add(['.hgignore', 'series'])
     return 0
 
+def clone(ui, source, dest=None, **opts):
+    '''clone main and patch repository at same time
+
+    If source is local, destination will have no patches applied.  If
+    source is remote, this command can not check if patches are
+    applied in source, so cannot guarantee that patches are not
+    applied in destination.  If you clone remote repository, be sure
+    before that it has no patches applied.
+
+    Source patch repository is looked for in <src>/.hg/patches by
+    default.  Use -p <url> to change.
+    '''
+    ui.setconfig_remoteopts(**opts)
+    if dest is None:
+        dest = hg.defaultdest(source)
+    sr = hg.repository(ui, ui.expandpath(source))
+    qbase, destrev = None, None
+    if sr.local():
+        reposetup(ui, sr)
+        sq = repomap[sr]
+        if sq.applied:
+            qbase = revlog.bin(sq.applied[0].split(':')[0])
+            if not hg.islocal(dest):
+                destrev = sr.parents(qbase)[0]
+    ui.note(_('cloning main repo\n'))
+    sr, dr = hg.clone(ui, sr, dest,
+                      pull=opts['pull'],
+                      rev=destrev,
+                      update=False,
+                      stream=opts['uncompressed'])
+    ui.note(_('cloning patch repo\n'))
+    spr, dpr = hg.clone(ui, opts['patches'] or (sr.url() + '/.hg/patches'),
+                        dr.url() + '/.hg/patches',
+                        pull=opts['pull'],
+                        update=not opts['noupdate'],
+                        stream=opts['uncompressed'])
+    if dr.local():
+        if qbase:
+            ui.note(_('stripping applied patches from destination repo\n'))
+            reposetup(ui, dr)
+            dq = repomap[dr]
+            dq.strip(dr, qbase, update=False, backup=None)
+        if not opts['noupdate']:
+            ui.note(_('updating destination repo\n'))
+            dr.update(dr.changelog.tip())
+
 def commit(ui, repo, *pats, **opts):
     """commit changes in the queue repository"""
     q = repomap[repo]
@@ -1369,6 +1416,16 @@
 
 cmdtable = {
     "qapplied": (applied, [], 'hg qapplied [PATCH]'),
+    "qclone": (clone,
+               [('', 'pull', None, _('use pull protocol to copy metadata')),
+                ('U', 'noupdate', None, _('do not update the new working directories')),
+                ('', 'uncompressed', None,
+                 _('use uncompressed transfer (fast over LAN)')),
+                ('e', 'ssh', '', _('specify ssh command to use')),
+                ('p', 'patches', '', _('location of source patch repo')),
+                ('', 'remotecmd', '',
+                 _('specify hg command to run on the remote side'))],
+               'hg qclone [OPTION]... SOURCE [DEST]'),
     "qcommit|qci":
         (commit,
          commands.table["^commit|ci"][1],
--- a/mercurial/hg.py	Fri Jul 28 18:46:02 2006 +0200
+++ b/mercurial/hg.py	Fri Jul 28 10:47:02 2006 -0700
@@ -57,6 +57,23 @@
     'static-http': static_http,
     }
 
+remote_schemes = [
+    'bundle',
+    'hg',
+    'http',
+    'https',
+    'old-http',
+    'ssh',
+    'static-http',
+    ]
+
+def islocal(repo):
+    '''return true if repo or path is local'''
+    if isinstance(repo, str):
+        c = repo.find(':')
+        return c <= 0 or repo[:c] not in remote_schemes
+    return repo.local()
+
 def repository(ui, path=None, create=0):
     scheme = None
     if path:
@@ -74,6 +91,10 @@
                              scheme)
     return ctor(ui, path)
 
+def defaultdest(source):
+    '''return default destination of clone if none is given'''
+    return os.path.basename(os.path.normpath(source))
+    
 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
           stream=False):
     """Make a copy of an existing repository.
@@ -90,7 +111,9 @@
     If an exception is raised, the partly cloned/updated destination
     repository will be deleted.
 
-    Keyword arguments:
+    Arguments:
+
+    source: repository object or URL
 
     dest: URL of destination repository to create (defaults to base
     name of source repository)
@@ -105,8 +128,24 @@
     update: update working directory after clone completes, if
     destination is local repository
     """
+    if isinstance(source, str):
+        src_repo = repository(ui, source)
+    else:
+        src_repo = source
+        source = src_repo.url()
+
     if dest is None:
-        dest = os.path.basename(os.path.normpath(source))
+        dest = defaultdest(source)
+
+    def localpath(path):
+        if path.startswith('file://'):
+            return path[7:]
+        if path.startswith('file:'):
+            return path[5:]
+        return path
+
+    dest = localpath(dest)
+    source = localpath(source)
 
     if os.path.exists(dest):
         raise util.Abort(_("destination '%s' already exists"), dest)
@@ -121,8 +160,6 @@
             if self.dir_:
                 self.rmtree(self.dir_, True)
 
-    src_repo = repository(ui, source)
-
     dest_repo = None
     try:
         dest_repo = repository(ui, dest)
@@ -133,7 +170,7 @@
     dest_path = None
     dir_cleanup = None
     if dest_repo.local():
-        dest_path = os.path.realpath(dest)
+        dest_path = os.path.realpath(dest_repo.root)
         dir_cleanup = DirCleanup(dest_path)
 
     abspath = source