hgext/journal.py
author Yuya Nishihara <yuya@tcha.org>
Sun, 10 Jul 2016 21:03:06 +0900
changeset 29676 c3a9cd78b151
parent 29675 12f04946053c
child 29677 69890b5dd32b
permissions -rw-r--r--
formatter: add function to convert list to appropriate format (issue5217) Before, it wasn't possible for formatter to handle array structure other than date tuple. We've discussed that at the last sprint, which ended we would probably want to allow only templatable data structure, i.e. a list of dicts: data(tags=[{'tag': a}, {'tag': b}, ...]) Unfortunately, it turned out not working well with template functions: "{ifcontains(a, tags, ...)}" ^^^^^^^^^^^^^^^^^^ "a in tags", where tags should be a plain list/set of tags So the formatter must at least know if the type [{}] was constructed from a plain list or was actually a list of dicts. This patch introduces new explicit interface to convert an array structure to an appropriate data type for the current formatter, which can be used as follows: fm.write('tags', _('tags: %s\n'), fm.formatlist(tags, name='tag')) No separate fm.data() call should be necessary.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     1
# journal.py
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     2
#
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     3
# Copyright 2014-2016 Facebook, Inc.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     4
#
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     7
"""Track previous positions of bookmarks (EXPERIMENTAL)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     8
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     9
This extension adds a new command: `hg journal`, which shows you where
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    10
bookmarks were previously located.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    11
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    12
"""
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    13
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    14
from __future__ import absolute_import
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    15
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    16
import collections
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
    17
import errno
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    18
import os
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    19
import weakref
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    20
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    21
from mercurial.i18n import _
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    22
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    23
from mercurial import (
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    24
    bookmarks,
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    25
    cmdutil,
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    26
    commands,
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    27
    dirstate,
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    28
    dispatch,
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    29
    error,
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    30
    extensions,
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
    31
    hg,
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    32
    localrepo,
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    33
    lock,
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    34
    node,
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    35
    util,
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    36
)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    37
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
    38
from . import share
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
    39
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    40
cmdtable = {}
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    41
command = cmdutil.command(cmdtable)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    42
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    43
# Note for extension authors: ONLY specify testedwith = 'internal' for
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    44
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    45
# be specifying the version(s) of Mercurial they are tested with, or
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    46
# leave the attribute unspecified.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    47
testedwith = 'internal'
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    48
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    49
# storage format version; increment when the format changes
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    50
storageversion = 0
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    51
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    52
# namespaces
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    53
bookmarktype = 'bookmark'
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    54
wdirparenttype = 'wdirparent'
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
    55
# In a shared repository, what shared feature name is used
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
    56
# to indicate this namespace is shared with the source?
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
    57
sharednamespaces = {
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
    58
    bookmarktype: hg.sharedbookmarks,
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
    59
}
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    60
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    61
# Journal recording, register hooks and storage object
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    62
def extsetup(ui):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    63
    extensions.wrapfunction(dispatch, 'runcommand', runcommand)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    64
    extensions.wrapfunction(bookmarks.bmstore, '_write', recordbookmarks)
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    65
    extensions.wrapfunction(
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    66
        dirstate.dirstate, '_writedirstate', recorddirstateparents)
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    67
    extensions.wrapfunction(
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    68
        localrepo.localrepository.dirstate, 'func', wrapdirstate)
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
    69
    extensions.wrapfunction(hg, 'postshare', wrappostshare)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
    70
    extensions.wrapfunction(hg, 'copystore', unsharejournal)
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    71
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    72
def reposetup(ui, repo):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    73
    if repo.local():
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    74
        repo.journal = journalstorage(repo)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    75
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    76
def runcommand(orig, lui, repo, cmd, fullargs, *args):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    77
    """Track the command line options for recording in the journal"""
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    78
    journalstorage.recordcommand(*fullargs)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    79
    return orig(lui, repo, cmd, fullargs, *args)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    80
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    81
# hooks to record dirstate changes
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    82
def wrapdirstate(orig, repo):
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    83
    """Make journal storage available to the dirstate object"""
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    84
    dirstate = orig(repo)
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    85
    if util.safehasattr(repo, 'journal'):
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    86
        dirstate.journalstorage = repo.journal
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    87
    return dirstate
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    88
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    89
def recorddirstateparents(orig, dirstate, dirstatefp):
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    90
    """Records all dirstate parent changes in the journal."""
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    91
    if util.safehasattr(dirstate, 'journalstorage'):
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    92
        old = [node.nullid, node.nullid]
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    93
        nodesize = len(node.nullid)
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    94
        try:
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    95
            # The only source for the old state is in the dirstate file still
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    96
            # on disk; the in-memory dirstate object only contains the new
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    97
            # state. dirstate._opendirstatefile() switches beteen .hg/dirstate
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    98
            # and .hg/dirstate.pending depending on the transaction state.
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
    99
            with dirstate._opendirstatefile() as fp:
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   100
                state = fp.read(2 * nodesize)
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   101
            if len(state) == 2 * nodesize:
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   102
                old = [state[:nodesize], state[nodesize:]]
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   103
        except IOError:
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   104
            pass
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   105
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   106
        new = dirstate.parents()
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   107
        if old != new:
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   108
            # only record two hashes if there was a merge
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   109
            oldhashes = old[:1] if old[1] == node.nullid else old
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   110
            newhashes = new[:1] if new[1] == node.nullid else new
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   111
            dirstate.journalstorage.record(
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   112
                wdirparenttype, '.', oldhashes, newhashes)
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   113
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   114
    return orig(dirstate, dirstatefp)
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   115
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   116
# hooks to record bookmark changes (both local and remote)
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   117
def recordbookmarks(orig, store, fp):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   118
    """Records all bookmark changes in the journal."""
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   119
    repo = store._repo
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   120
    if util.safehasattr(repo, 'journal'):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   121
        oldmarks = bookmarks.bmstore(repo)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   122
        for mark, value in store.iteritems():
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   123
            oldvalue = oldmarks.get(mark, node.nullid)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   124
            if value != oldvalue:
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   125
                repo.journal.record(bookmarktype, mark, oldvalue, value)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   126
    return orig(store, fp)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   127
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   128
# shared repository support
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   129
def _readsharedfeatures(repo):
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   130
    """A set of shared features for this repository"""
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   131
    try:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   132
        return set(repo.vfs.read('shared').splitlines())
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   133
    except IOError as inst:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   134
        if inst.errno != errno.ENOENT:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   135
            raise
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   136
        return set()
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   137
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   138
def _mergeentriesiter(*iterables, **kwargs):
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   139
    """Given a set of sorted iterables, yield the next entry in merged order
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   140
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   141
    Note that by default entries go from most recent to oldest.
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   142
    """
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   143
    order = kwargs.pop('order', max)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   144
    iterables = [iter(it) for it in iterables]
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   145
    # this tracks still active iterables; iterables are deleted as they are
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   146
    # exhausted, which is why this is a dictionary and why each entry also
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   147
    # stores the key. Entries are mutable so we can store the next value each
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   148
    # time.
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   149
    iterable_map = {}
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   150
    for key, it in enumerate(iterables):
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   151
        try:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   152
            iterable_map[key] = [next(it), key, it]
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   153
        except StopIteration:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   154
            # empty entry, can be ignored
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   155
            pass
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   156
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   157
    while iterable_map:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   158
        value, key, it = order(iterable_map.itervalues())
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   159
        yield value
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   160
        try:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   161
            iterable_map[key][0] = next(it)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   162
        except StopIteration:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   163
            # this iterable is empty, remove it from consideration
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   164
            del iterable_map[key]
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   165
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   166
def wrappostshare(orig, sourcerepo, destrepo, **kwargs):
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   167
    """Mark this shared working copy as sharing journal information"""
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   168
    orig(sourcerepo, destrepo, **kwargs)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   169
    with destrepo.vfs('shared', 'a') as fp:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   170
        fp.write('journal\n')
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   171
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   172
def unsharejournal(orig, ui, repo, repopath):
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   173
    """Copy shared journal entries into this repo when unsharing"""
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   174
    if (repo.path == repopath and repo.shared() and
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   175
            util.safehasattr(repo, 'journal')):
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   176
        sharedrepo = share._getsrcrepo(repo)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   177
        sharedfeatures = _readsharedfeatures(repo)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   178
        if sharedrepo and sharedfeatures > set(['journal']):
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   179
            # there is a shared repository and there are shared journal entries
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   180
            # to copy. move shared date over from source to destination but
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   181
            # move the local file first
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   182
            if repo.vfs.exists('journal'):
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   183
                journalpath = repo.join('journal')
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   184
                util.rename(journalpath, journalpath + '.bak')
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   185
            storage = repo.journal
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   186
            local = storage._open(
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   187
                repo.vfs, filename='journal.bak', _newestfirst=False)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   188
            shared = (
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   189
                e for e in storage._open(sharedrepo.vfs, _newestfirst=False)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   190
                if sharednamespaces.get(e.namespace) in sharedfeatures)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   191
            for entry in _mergeentriesiter(local, shared, order=min):
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   192
                storage._write(repo.vfs, entry)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   193
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   194
    return orig(ui, repo, repopath)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   195
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   196
class journalentry(collections.namedtuple(
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   197
        'journalentry',
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   198
        'timestamp user command namespace name oldhashes newhashes')):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   199
    """Individual journal entry
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   200
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   201
    * timestamp: a mercurial (time, timezone) tuple
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   202
    * user: the username that ran the command
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   203
    * namespace: the entry namespace, an opaque string
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   204
    * name: the name of the changed item, opaque string with meaning in the
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   205
      namespace
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   206
    * command: the hg command that triggered this record
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   207
    * oldhashes: a tuple of one or more binary hashes for the old location
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   208
    * newhashes: a tuple of one or more binary hashes for the new location
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   209
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   210
    Handles serialisation from and to the storage format. Fields are
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   211
    separated by newlines, hashes are written out in hex separated by commas,
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   212
    timestamp and timezone are separated by a space.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   213
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   214
    """
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   215
    @classmethod
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   216
    def fromstorage(cls, line):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   217
        (time, user, command, namespace, name,
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   218
         oldhashes, newhashes) = line.split('\n')
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   219
        timestamp, tz = time.split()
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   220
        timestamp, tz = float(timestamp), int(tz)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   221
        oldhashes = tuple(node.bin(hash) for hash in oldhashes.split(','))
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   222
        newhashes = tuple(node.bin(hash) for hash in newhashes.split(','))
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   223
        return cls(
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   224
            (timestamp, tz), user, command, namespace, name,
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   225
            oldhashes, newhashes)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   226
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   227
    def __str__(self):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   228
        """String representation for storage"""
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   229
        time = ' '.join(map(str, self.timestamp))
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   230
        oldhashes = ','.join([node.hex(hash) for hash in self.oldhashes])
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   231
        newhashes = ','.join([node.hex(hash) for hash in self.newhashes])
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   232
        return '\n'.join((
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   233
            time, self.user, self.command, self.namespace, self.name,
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   234
            oldhashes, newhashes))
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   235
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   236
class journalstorage(object):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   237
    """Storage for journal entries
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   238
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   239
    Entries are divided over two files; one with entries that pertain to the
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   240
    local working copy *only*, and one with entries that are shared across
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   241
    multiple working copies when shared using the share extension.
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   242
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   243
    Entries are stored with NUL bytes as separators. See the journalentry
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   244
    class for the per-entry structure.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   245
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   246
    The file format starts with an integer version, delimited by a NUL.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   247
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   248
    This storage uses a dedicated lock; this makes it easier to avoid issues
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   249
    with adding entries that added when the regular wlock is unlocked (e.g.
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   250
    the dirstate).
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   251
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   252
    """
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   253
    _currentcommand = ()
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   254
    _lockref = None
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   255
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   256
    def __init__(self, repo):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   257
        self.user = util.getuser()
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   258
        self.ui = repo.ui
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   259
        self.vfs = repo.vfs
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   260
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   261
        # is this working copy using a shared storage?
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   262
        self.sharedfeatures = self.sharedvfs = None
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   263
        if repo.shared():
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   264
            features = _readsharedfeatures(repo)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   265
            sharedrepo = share._getsrcrepo(repo)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   266
            if sharedrepo is not None and 'journal' in features:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   267
                self.sharedvfs = sharedrepo.vfs
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   268
                self.sharedfeatures = features
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   269
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   270
    # track the current command for recording in journal entries
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   271
    @property
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   272
    def command(self):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   273
        commandstr = ' '.join(
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   274
            map(util.shellquote, journalstorage._currentcommand))
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   275
        if '\n' in commandstr:
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   276
            # truncate multi-line commands
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   277
            commandstr = commandstr.partition('\n')[0] + ' ...'
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   278
        return commandstr
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   279
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   280
    @classmethod
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   281
    def recordcommand(cls, *fullargs):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   282
        """Set the current hg arguments, stored with recorded entries"""
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   283
        # Set the current command on the class because we may have started
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   284
        # with a non-local repo (cloning for example).
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   285
        cls._currentcommand = fullargs
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   286
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   287
    def jlock(self, vfs):
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   288
        """Create a lock for the journal file"""
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   289
        if self._lockref and self._lockref():
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   290
            raise error.Abort(_('journal lock does not support nesting'))
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   291
        desc = _('journal of %s') % vfs.base
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   292
        try:
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   293
            l = lock.lock(vfs, 'journal.lock', 0, desc=desc)
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   294
        except error.LockHeld as inst:
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   295
            self.ui.warn(
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   296
                _("waiting for lock on %s held by %r\n") % (desc, inst.locker))
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   297
            # default to 600 seconds timeout
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   298
            l = lock.lock(
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   299
                vfs, 'journal.lock',
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   300
                int(self.ui.config("ui", "timeout", "600")), desc=desc)
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   301
            self.ui.warn(_("got lock after %s seconds\n") % l.delay)
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   302
        self._lockref = weakref.ref(l)
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   303
        return l
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   304
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   305
    def record(self, namespace, name, oldhashes, newhashes):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   306
        """Record a new journal entry
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   307
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   308
        * namespace: an opaque string; this can be used to filter on the type
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   309
          of recorded entries.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   310
        * name: the name defining this entry; for bookmarks, this is the
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   311
          bookmark name. Can be filtered on when retrieving entries.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   312
        * oldhashes and newhashes: each a single binary hash, or a list of
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   313
          binary hashes. These represent the old and new position of the named
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   314
          item.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   315
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   316
        """
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   317
        if not isinstance(oldhashes, list):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   318
            oldhashes = [oldhashes]
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   319
        if not isinstance(newhashes, list):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   320
            newhashes = [newhashes]
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   321
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   322
        entry = journalentry(
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   323
            util.makedate(), self.user, self.command, namespace, name,
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   324
            oldhashes, newhashes)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   325
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   326
        vfs = self.vfs
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   327
        if self.sharedvfs is not None:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   328
            # write to the shared repository if this feature is being
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   329
            # shared between working copies.
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   330
            if sharednamespaces.get(namespace) in self.sharedfeatures:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   331
                vfs = self.sharedvfs
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   332
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   333
        self._write(vfs, entry)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   334
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   335
    def _write(self, vfs, entry):
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   336
        with self.jlock(vfs):
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   337
            version = None
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   338
            # open file in amend mode to ensure it is created if missing
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   339
            with vfs('journal', mode='a+b', atomictemp=True) as f:
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   340
                f.seek(0, os.SEEK_SET)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   341
                # Read just enough bytes to get a version number (up to 2
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   342
                # digits plus separator)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   343
                version = f.read(3).partition('\0')[0]
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   344
                if version and version != str(storageversion):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   345
                    # different version of the storage. Exit early (and not
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   346
                    # write anything) if this is not a version we can handle or
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   347
                    # the file is corrupt. In future, perhaps rotate the file
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   348
                    # instead?
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   349
                    self.ui.warn(
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   350
                        _("unsupported journal file version '%s'\n") % version)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   351
                    return
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   352
                if not version:
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   353
                    # empty file, write version first
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   354
                    f.write(str(storageversion) + '\0')
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   355
                f.seek(0, os.SEEK_END)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   356
                f.write(str(entry) + '\0')
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   357
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   358
    def filtered(self, namespace=None, name=None):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   359
        """Yield all journal entries with the given namespace or name
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   360
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   361
        Both the namespace and the name are optional; if neither is given all
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   362
        entries in the journal are produced.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   363
29504
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   364
        Matching supports regular expressions by using the `re:` prefix
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   365
        (use `literal:` to match names or namespaces that start with `re:`)
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   366
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   367
        """
29504
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   368
        if namespace is not None:
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   369
            namespace = util.stringmatcher(namespace)[-1]
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   370
        if name is not None:
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   371
            name = util.stringmatcher(name)[-1]
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   372
        for entry in self:
29504
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   373
            if namespace is not None and not namespace(entry.namespace):
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   374
                continue
29504
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   375
            if name is not None and not name(entry.name):
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   376
                continue
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   377
            yield entry
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   378
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   379
    def __iter__(self):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   380
        """Iterate over the storage
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   381
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   382
        Yields journalentry instances for each contained journal record.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   383
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   384
        """
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   385
        local = self._open(self.vfs)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   386
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   387
        if self.sharedvfs is None:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   388
            return local
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   389
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   390
        # iterate over both local and shared entries, but only those
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   391
        # shared entries that are among the currently shared features
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   392
        shared = (
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   393
            e for e in self._open(self.sharedvfs)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   394
            if sharednamespaces.get(e.namespace) in self.sharedfeatures)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   395
        return _mergeentriesiter(local, shared)
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   396
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   397
    def _open(self, vfs, filename='journal', _newestfirst=True):
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   398
        if not vfs.exists(filename):
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   399
            return
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   400
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   401
        with vfs(filename) as f:
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   402
            raw = f.read()
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   403
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   404
        lines = raw.split('\0')
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   405
        version = lines and lines[0]
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   406
        if version != str(storageversion):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   407
            version = version or _('not available')
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   408
            raise error.Abort(_("unknown journal file version '%s'") % version)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   409
29503
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   410
        # Skip the first line, it's a version number. Normally we iterate over
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   411
        # these in reverse order to list newest first; only when copying across
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   412
        # a shared storage do we forgo reversing.
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   413
        lines = lines[1:]
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   414
        if _newestfirst:
0103b673d6ca journal: add share extension support
Martijn Pieters <mjpieters@fb.com>
parents: 29502
diff changeset
   415
            lines = reversed(lines)
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   416
        for line in lines:
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   417
            if not line:
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   418
                continue
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   419
            yield journalentry.fromstorage(line)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   420
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   421
# journal reading
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   422
# log options that don't make sense for journal
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   423
_ignoreopts = ('no-merges', 'graph')
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   424
@command(
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   425
    'journal', [
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   426
        ('', 'all', None, 'show history for all names'),
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   427
        ('c', 'commits', None, 'show commit metadata'),
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   428
    ] + [opt for opt in commands.logopts if opt[1] not in _ignoreopts],
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   429
    '[OPTION]... [BOOKMARKNAME]')
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   430
def journal(ui, repo, *args, **opts):
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   431
    """show the previous position of bookmarks and the working copy
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   432
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   433
    The journal is used to see the previous commits that bookmarks and the
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   434
    working copy pointed to. By default the previous locations for the working
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   435
    copy.  Passing a bookmark name will show all the previous positions of
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   436
    that bookmark. Use the --all switch to show previous locations for all
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   437
    bookmarks and the working copy; each line will then include the bookmark
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   438
    name, or '.' for the working copy, as well.
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   439
29504
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   440
    If `name` starts with `re:`, the remainder of the name is treated as
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   441
    a regular expression. To match a name that actually starts with `re:`,
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   442
    use the prefix `literal:`.
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   443
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   444
    By default hg journal only shows the commit hash and the command that was
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   445
    running at that time. -v/--verbose will show the prior hash, the user, and
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   446
    the time at which it happened.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   447
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   448
    Use -c/--commits to output log information on each commit hash; at this
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   449
    point you can use the usual `--patch`, `--git`, `--stat` and `--template`
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   450
    switches to alter the log output for these.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   451
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   452
    `hg journal -T json` can be used to produce machine readable output.
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   453
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   454
    """
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   455
    name = '.'
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   456
    if opts.get('all'):
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   457
        if args:
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   458
            raise error.Abort(
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   459
                _("You can't combine --all and filtering on a name"))
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   460
        name = None
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   461
    if args:
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   462
        name = args[0]
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   463
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   464
    fm = ui.formatter('journal', opts)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   465
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   466
    if opts.get("template") != "json":
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   467
        if name is None:
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   468
            displayname = _('the working copy and bookmarks')
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   469
        else:
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   470
            displayname = "'%s'" % name
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   471
        ui.status(_("previous locations of %s:\n") % displayname)
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   472
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   473
    limit = cmdutil.loglimit(opts)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   474
    entry = None
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   475
    for count, entry in enumerate(repo.journal.filtered(name=name)):
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   476
        if count == limit:
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   477
            break
29675
12f04946053c journal: use fm.hexfunc() to get full hash in JSON/template output (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29504
diff changeset
   478
        newhashesstr = ','.join([fm.hexfunc(hash) for hash in entry.newhashes])
12f04946053c journal: use fm.hexfunc() to get full hash in JSON/template output (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29504
diff changeset
   479
        oldhashesstr = ','.join([fm.hexfunc(hash) for hash in entry.oldhashes])
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   480
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   481
        fm.startitem()
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   482
        fm.condwrite(ui.verbose, 'oldhashes', '%s -> ', oldhashesstr)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   483
        fm.write('newhashes', '%s', newhashesstr)
29502
8361131b4768 journal: add dirstate tracking
Martijn Pieters <mjpieters@fb.com>
parents: 29443
diff changeset
   484
        fm.condwrite(ui.verbose, 'user', ' %-8s', entry.user)
29504
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   485
        fm.condwrite(
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   486
            opts.get('all') or name.startswith('re:'),
7503d8874617 journal: add support for seaching by pattern
Martijn Pieters <mjpieters@fb.com>
parents: 29503
diff changeset
   487
            'name', '  %-8s', entry.name)
29443
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   488
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   489
        timestring = util.datestr(entry.timestamp, '%Y-%m-%d %H:%M %1%2')
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   490
        fm.condwrite(ui.verbose, 'date', ' %s', timestring)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   491
        fm.write('command', '  %s\n', entry.command)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   492
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   493
        if opts.get("commits"):
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   494
            displayer = cmdutil.show_changeset(ui, repo, opts, buffered=False)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   495
            for hash in entry.newhashes:
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   496
                try:
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   497
                    ctx = repo[hash]
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   498
                    displayer.show(ctx)
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   499
                except error.RepoLookupError as e:
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   500
                    fm.write('repolookuperror', "%s\n\n", str(e))
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   501
            displayer.close()
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   502
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   503
    fm.end()
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   504
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   505
    if entry is None:
cf092a3d202a journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   506
        ui.status(_("no recorded locations\n"))