hgext/share.py
author Gregory Szorc <gregory.szorc@gmail.com>
Mon, 25 May 2015 17:14:11 -0700
changeset 25402 0c2ded041d10
parent 25186 80c5b2666a96
child 25660 328739ea70c3
permissions -rw-r--r--
exchange: support transferring .hgtags fnodes mapping On Mozilla's mozilla-beta repository .hgtags fnodes resolution takes ~18s from a clean cache on my machine. This means that the first time a user runs `hg tags`, `hg log`, or any other command that displays or accesses tags data, a ~18s pause will occur. There is no output during this pause. This results in a poor user experience and perception that Mercurial is slow. The .hgtags changeset to filenode mapping is deterministic. This patch takes advantage of that property by implementing support for transferring .hgtags filenodes mappings in a dedicated bundle2 part. When a client advertising support for the "hgtagsfnodes" capability requests a bundle, a mapping of changesets to .hgtags filenodes will be sent to the client. Only mappings of head changesets included in the bundle will be sent. The transfer of this mapping effectively eliminates one time tags cache related pauses after initial clone. The mappings are sent as binary data. So, 40 bytes per pair of SHA-1s. On the aforementioned mozilla-beta repository, 659 * 40 = 26,360 raw bytes of mappings are sent over the wire (in addition to the bundle part headers). Assuming 18s to populate the cache, we only need to transfer this extra data faster than 1.5 KB/s for overall clone + tags cache population time to be shorter. Put into perspective, the mozilla-beta repository is ~1 GB in size. So, this additional data constitutes <0.01% of the cloned data. The marginal overhead for a multi-second performance win on clones in my opinion justifies an on-by-default behavior.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8801
28eaf6f8abce share: add experimental share extension
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
28eaf6f8abce share: add experimental share extension
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
28eaf6f8abce share: add experimental share extension
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10256
diff changeset
     4
# GNU General Public License version 2 or any later version.
8801
28eaf6f8abce share: add experimental share extension
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
8894
868670dbc237 extensions: improve the consistency of synopses
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
     6
'''share a common history between several working directories'''
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8807
diff changeset
     7
8801
28eaf6f8abce share: add experimental share extension
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
from mercurial.i18n import _
23548
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
     9
from mercurial import cmdutil, hg, util, extensions, bookmarks
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    10
from mercurial.hg import repository, parseurl
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    11
import errno
15079
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    12
21253
d2ce7a20fe86 share: declare commands using decorator
Gregory Szorc <gregory.szorc@gmail.com>
parents: 20056
diff changeset
    13
cmdtable = {}
d2ce7a20fe86 share: declare commands using decorator
Gregory Szorc <gregory.szorc@gmail.com>
parents: 20056
diff changeset
    14
command = cmdutil.command(cmdtable)
25186
80c5b2666a96 extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents: 24364
diff changeset
    15
# Note for extension authors: ONLY specify testedwith = 'internal' for
80c5b2666a96 extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents: 24364
diff changeset
    16
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
80c5b2666a96 extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents: 24364
diff changeset
    17
# be specifying the version(s) of Mercurial they are tested with, or
80c5b2666a96 extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents: 24364
diff changeset
    18
# leave the attribute unspecified.
16743
38caf405d010 hgext: mark all first-party extensions as such
Augie Fackler <raf@durin42.com>
parents: 15082
diff changeset
    19
testedwith = 'internal'
38caf405d010 hgext: mark all first-party extensions as such
Augie Fackler <raf@durin42.com>
parents: 15082
diff changeset
    20
21253
d2ce7a20fe86 share: declare commands using decorator
Gregory Szorc <gregory.szorc@gmail.com>
parents: 20056
diff changeset
    21
@command('share',
24364
135b23868f45 commands: replace "working copy" with "working directory" in help/messages
Yuya Nishihara <yuya@tcha.org>
parents: 23883
diff changeset
    22
    [('U', 'noupdate', None, _('do not create a working directory')),
23614
cd79fb4d75fd share: add option to share bookmarks
Ryan McElroy <rmcelroy@fb.com>
parents: 23548
diff changeset
    23
     ('B', 'bookmarks', None, _('also share bookmarks'))],
cd79fb4d75fd share: add option to share bookmarks
Ryan McElroy <rmcelroy@fb.com>
parents: 23548
diff changeset
    24
    _('[-U] [-B] SOURCE [DEST]'),
21772
5a4d1a6c605f share: define norepo in command decorator
Gregory Szorc <gregory.szorc@gmail.com>
parents: 21253
diff changeset
    25
    norepo=True)
23614
cd79fb4d75fd share: add option to share bookmarks
Ryan McElroy <rmcelroy@fb.com>
parents: 23548
diff changeset
    26
def share(ui, source, dest=None, noupdate=False, bookmarks=False):
10798
e46c19c586fa share: drop experimental label
Martin Geisler <mg@lazybytes.net>
parents: 10263
diff changeset
    27
    """create a new shared repository
8801
28eaf6f8abce share: add experimental share extension
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    28
9273
4b8b0c124b99 share: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9075
diff changeset
    29
    Initialize a new repository and working directory that shares its
23614
cd79fb4d75fd share: add option to share bookmarks
Ryan McElroy <rmcelroy@fb.com>
parents: 23548
diff changeset
    30
    history (and optionally bookmarks) with another repository.
8801
28eaf6f8abce share: add experimental share extension
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
12389
4ac734b9b3fd Use note admonition
Erik Zielke <ez@aragost.com>
parents: 10798
diff changeset
    32
    .. note::
19997
de16c673455b documentation: add an extra newline after note directive
Simon Heimberg <simohe@besonet.ch>
parents: 19399
diff changeset
    33
12389
4ac734b9b3fd Use note admonition
Erik Zielke <ez@aragost.com>
parents: 10798
diff changeset
    34
       using rollback or extensions that destroy/modify history (mq,
4ac734b9b3fd Use note admonition
Erik Zielke <ez@aragost.com>
parents: 10798
diff changeset
    35
       rebase, etc.) can cause considerable confusion with shared
4ac734b9b3fd Use note admonition
Erik Zielke <ez@aragost.com>
parents: 10798
diff changeset
    36
       clones. In particular, if two shared clones are both updated to
4ac734b9b3fd Use note admonition
Erik Zielke <ez@aragost.com>
parents: 10798
diff changeset
    37
       the same changeset, and one of them destroys that changeset
4ac734b9b3fd Use note admonition
Erik Zielke <ez@aragost.com>
parents: 10798
diff changeset
    38
       with rollback, the other clone will suddenly stop working: all
4ac734b9b3fd Use note admonition
Erik Zielke <ez@aragost.com>
parents: 10798
diff changeset
    39
       operations will fail with "abort: working directory has unknown
4ac734b9b3fd Use note admonition
Erik Zielke <ez@aragost.com>
parents: 10798
diff changeset
    40
       parent". The only known workaround is to use debugsetparents on
19399
02465cafb0a9 share: remove reference to tip
Matt Mackall <mpm@selenic.com>
parents: 18825
diff changeset
    41
       the broken clone to reset it to a changeset that still exists.
8801
28eaf6f8abce share: add experimental share extension
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
    """
28eaf6f8abce share: add experimental share extension
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    43
23614
cd79fb4d75fd share: add option to share bookmarks
Ryan McElroy <rmcelroy@fb.com>
parents: 23548
diff changeset
    44
    return hg.share(ui, source, dest, not noupdate, bookmarks)
8801
28eaf6f8abce share: add experimental share extension
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    45
21253
d2ce7a20fe86 share: declare commands using decorator
Gregory Szorc <gregory.szorc@gmail.com>
parents: 20056
diff changeset
    46
@command('unshare', [], '')
15079
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    47
def unshare(ui, repo):
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    48
    """convert a shared repository to a normal one
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    49
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    50
    Copy the store data to the repo and remove the sharedpath data.
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    51
    """
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    52
23666
965788d9ae09 localrepo: introduce shared method to check if a repository is shared
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 23626
diff changeset
    53
    if not repo.shared():
15079
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    54
        raise util.Abort(_("this is not a shared repo"))
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    55
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    56
    destlock = lock = None
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    57
    lock = repo.lock()
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    58
    try:
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    59
        # we use locks here because if we race with commit, we
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    60
        # can end up with extra data in the cloned revlogs that's
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    61
        # not pointed to by changesets, thus causing verify to
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    62
        # fail
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    63
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    64
        destlock = hg.copystore(ui, repo, repo.path)
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    65
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    66
        sharefile = repo.join('sharedpath')
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    67
        util.rename(sharefile, sharefile + '.old')
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    68
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    69
        repo.requirements.discard('sharedpath')
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    70
        repo._writerequirements()
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    71
    finally:
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    72
        destlock and destlock.release()
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    73
        lock and lock.release()
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    74
ea96bdda593c hgext: introduce unshare command
Simon Heimberg <simohe@besonet.ch>
parents: 12389
diff changeset
    75
    # update store, spath, sopener and sjoin of repo
20056
cbcd85fa75c0 share: fix unshare calling wrong repo.__init__() method
Brodie Rao <brodie@sf.io>
parents: 19997
diff changeset
    76
    repo.unfiltered().__init__(repo.baseui, repo.root)
23548
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    77
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    78
def extsetup(ui):
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    79
    extensions.wrapfunction(bookmarks.bmstore, 'getbkfile', getbkfile)
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    80
    extensions.wrapfunction(bookmarks.bmstore, 'recordchange', recordchange)
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    81
    extensions.wrapfunction(bookmarks.bmstore, 'write', write)
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    82
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    83
def _hassharedbookmarks(repo):
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    84
    """Returns whether this repo has shared bookmarks"""
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    85
    try:
23883
7e71898a7cdc share: replace the bookmarks.shared file with an entry on a new "shared" file
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 23666
diff changeset
    86
        shared = repo.vfs.read('shared').splitlines()
23548
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    87
    except IOError, inst:
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    88
        if inst.errno != errno.ENOENT:
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    89
            raise
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    90
        return False
23883
7e71898a7cdc share: replace the bookmarks.shared file with an entry on a new "shared" file
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 23666
diff changeset
    91
    return 'bookmarks' in shared
23548
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    92
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    93
def _getsrcrepo(repo):
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    94
    """
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    95
    Returns the source repository object for a given shared repository.
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    96
    If repo is not a shared repository, return None.
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
    97
    """
23626
012a7b482d68 share: use the 'sharedpath' attr on repo instead of reloading from the file
Matt Harbison <matt_harbison@yahoo.com>
parents: 23625
diff changeset
    98
    if repo.sharedpath == repo.path:
012a7b482d68 share: use the 'sharedpath' attr on repo instead of reloading from the file
Matt Harbison <matt_harbison@yahoo.com>
parents: 23625
diff changeset
    99
        return None
012a7b482d68 share: use the 'sharedpath' attr on repo instead of reloading from the file
Matt Harbison <matt_harbison@yahoo.com>
parents: 23625
diff changeset
   100
012a7b482d68 share: use the 'sharedpath' attr on repo instead of reloading from the file
Matt Harbison <matt_harbison@yahoo.com>
parents: 23625
diff changeset
   101
    # the sharedpath always ends in the .hg; we want the path to the repo
012a7b482d68 share: use the 'sharedpath' attr on repo instead of reloading from the file
Matt Harbison <matt_harbison@yahoo.com>
parents: 23625
diff changeset
   102
    source = repo.vfs.split(repo.sharedpath)[0]
012a7b482d68 share: use the 'sharedpath' attr on repo instead of reloading from the file
Matt Harbison <matt_harbison@yahoo.com>
parents: 23625
diff changeset
   103
    srcurl, branches = parseurl(source)
012a7b482d68 share: use the 'sharedpath' attr on repo instead of reloading from the file
Matt Harbison <matt_harbison@yahoo.com>
parents: 23625
diff changeset
   104
    return repository(repo.ui, srcurl)
23548
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   105
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   106
def getbkfile(orig, self, repo):
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   107
    if _hassharedbookmarks(repo):
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   108
        srcrepo = _getsrcrepo(repo)
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   109
        if srcrepo is not None:
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   110
            repo = srcrepo
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   111
    return orig(self, repo)
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   112
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   113
def recordchange(orig, self, tr):
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   114
    # Continue with write to local bookmarks file as usual
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   115
    orig(self, tr)
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   116
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   117
    if _hassharedbookmarks(self._repo):
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   118
        srcrepo = _getsrcrepo(self._repo)
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   119
        if srcrepo is not None:
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   120
            category = 'share-bookmarks'
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   121
            tr.addpostclose(category, lambda tr: self._writerepo(srcrepo))
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   122
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   123
def write(orig, self):
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   124
    # First write local bookmarks file in case we ever unshare
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   125
    orig(self)
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   126
    if _hassharedbookmarks(self._repo):
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   127
        srcrepo = _getsrcrepo(self._repo)
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   128
        if srcrepo is not None:
141baca16059 share: implement shared bookmark functionality
Ryan McElroy <rmcelroy@fb.com>
parents: 21772
diff changeset
   129
            self._writerepo(srcrepo)