[PATCH 2 of 3 V3] journal: add share extension support

Yuya Nishihara yuya at tcha.org
Fri Jul 8 11:24:13 EDT 2016


On Thu, 07 Jul 2016 18:00:06 +0100, Martijn Pieters wrote:
> # HG changeset patch
> # User Martijn Pieters <mjpieters at fb.com>
> # Date 1467714538 -3600
> #      Tue Jul 05 11:28:58 2016 +0100
> # Node ID e125ff50245cb519307dc75d606c9c8061784488
> # Parent  1f282c1e1df71e1a433df354000feed5c06ad625
> journal: add share extension support
>
> Rather than put everything into one journal file, split entries up in *shared*
> and *local* entries. Working copy changes are local to a specific working copy,
> so should remain local only. Other entries are shared with the source if so
> configured when the share was created.

So operations are recorded to the journal storage where they should belong,
which makes me feel the new shared feature, "journal", is unnecessary. We'd
always want to record bookmark changes to the source repo if bookmarks are
shared.

> +def _mergeentriesiter(*iterables, **kwargs):
> +    """Given a set of sorted iterables, yield the next entry in merged order
> +
> +    Note that by default entries go from most recent to oldest.
> +    """
> +    order = kwargs.pop('order', max)
> +    iterables = [iter(it) for it in iterables]
> +    # this tracks still active iterables; iterables are deleted as they are
> +    # exhausted, which is why this is a dictionary and why each entry also
> +    # stores the key. Entries are mutable so we can store the next value each
> +    # time.
> +    iterable_map = {}
> +    for key, it in enumerate(iterables):
> +        try:
> +            iterable_map[key] = [next(it), key, it]
> +        except StopIteration:
> +            # empty entry, can be ignored
> +            pass
> +    if not iterable_map:
> +        # all iterables where empty
> +        return
> +
> +    while True:

Nit: could be "while iterable_map:"

> +        value, key, it = order(iterable_map.itervalues())
> +        yield value
> +        try:
> +            iterable_map[key][0] = next(it)
> +        except StopIteration:
> +            # this iterable is empty, remove it from consideration
> +            del iterable_map[key]
> +            if not iterable_map:
> +                # all iterables are empty
> +                return

> +def unsharejournal(orig, ui, repo, repopath):
> +    """Copy shared journal entries into this repo when unsharing"""
> +    if repo.shared() and util.safehasattr(repo, 'journal'):
> +        sharedrepo = share._getsrcrepo(repo)
> +        sharedfeatures = _readsharedfeatures(repo)
> +        if sharedrepo and sharedfeatures > set(['journal']):
> +            # there is a shared repository and there are shared journal entries
> +            # to copy. move shared date over from source to destination but
> +            # move the local file first
> +            if repo.vfs.exists('journal'):
> +                journalpath = repo.join('journal')
> +                util.rename(journalpath, journalpath + '.bak')
> +            storage = repo.journal
> +            local = storage._open(
> +                repo.vfs, filename='journal.bak', _newestfirst=False)
> +            shared = (
> +                e for e in storage._open(sharedrepo.vfs, _newestfirst=False)
> +                if sharednamespaces.get(e.namespace) in sharedfeatures)
> +            for entry in _mergeentriesiter(local, shared, order=min):
> +                storage._write(repo.vfs, entry)

"hg clone" of shared repo will add wrong record to the source repo.

  $ hg share foo bar
  $ hg clone bar baz  # repo=bar, repopath=baz

> +        # is this working copy using a shared storage?
> +        self.sharedfeatures = self.svfs = None
> +        if repo.shared():
> +            features = _readsharedfeatures(repo)
> +            sharedrepo = share._getsrcrepo(repo)
> +            if sharedrepo is not None and 'journal' in features:
> +                self.svfs = sharedrepo.vfs
> +                self.sharedfeatures = features

Nit: "svfs" seems confusing since repo.svfs is store, but journal.svfs is
non-store of shared repo.


More information about the Mercurial-devel mailing list