hgext/bookflow.py
author Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
Tue, 02 Jul 2019 12:55:51 -0400
changeset 42619 20d0e59be79b
parent 41031 b53c5651fcf6
child 43076 2372284d9457
permissions -rw-r--r--
tests: show the files fields of changelogs for many merges I don't think there's coverage for many of the subtle cases, and I found it hard to understand what the code is doing by reading it. The test takes 40s to run on a laptop, or 9s with --chg. I have yet to find a description of what the files field is supposed to be for merges. I thought it could be one of: 1. the files added/modified/removed relative to p1 (wouldn't seem useful, but `hg diff -c -r mergerev` has this behavior) 2. the files with filelog nodes not in either parent (i.e., what is needed to create a bundle out of a commit) 3. the files added/removed/modified files by merge itself [1] It's clearly not 1, because file contents merges are symmetric. It's clearly not 2 because removed files and exec bit changes are listed. It's also not 3 but I think it's intended to be 3 and the differences are bugs. Assuming 3, the test shows that, for merges, the list of files both overapproximates and underapproximates. All the cases involve file changes not in the filelog but in the manifest (existence of file at revision, exec bit and file vs symlink). I didn't look at all underapproximations, but they looked minor. The two overapproximations are problematic though because they both cause potentially long lists of files when merging cleanly. [1] even what it means for the merge commit itself to change a file is not completely trivial. A file in the merge being the same as in one of the parent is too lax as it would consider that merges change nothing when they revert all the changes done on one side. The criteria used in the test and in the next commit for "merge didn't touch a file" is: - the parents and the merge all have the same file - or, one parent didn't touch the file and the other parent contains the same file as the merge Differential Revision: https://phab.mercurial-scm.org/D6612
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
40834
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
     1
"""implements bookmark-based branching (EXPERIMENTAL)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
     2
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
     3
 - Disables creation of new branches (config: enable_branches=False).
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
     4
 - Requires an active bookmark on commit (config: require_bookmark=True).
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
     5
 - Doesn't move the active bookmark on update, only on commit.
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
     6
 - Requires '--rev' for moving an existing bookmark.
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
     7
 - Protects special bookmarks (config: protect=@).
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
     8
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
     9
 flow related commands
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    10
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    11
    :hg book NAME: create a new bookmark
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    12
    :hg book NAME -r REV: move bookmark to revision (fast-forward)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    13
    :hg up|co NAME: switch to bookmark
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    14
    :hg push -B .: push active bookmark
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    15
"""
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    16
from __future__ import absolute_import
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    17
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    18
from mercurial.i18n import _
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    19
from mercurial import (
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    20
    bookmarks,
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    21
    commands,
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    22
    error,
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    23
    extensions,
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    24
    registrar,
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    25
)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    26
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    27
MY_NAME = 'bookflow'
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    28
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    29
configtable = {}
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    30
configitem = registrar.configitem(configtable)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    31
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    32
configitem(MY_NAME, 'protect', ['@'])
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    33
configitem(MY_NAME, 'require-bookmark', True)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    34
configitem(MY_NAME, 'enable-branches', False)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    35
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    36
cmdtable = {}
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    37
command = registrar.command(cmdtable)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    38
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    39
def commit_hook(ui, repo, **kwargs):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    40
    active = repo._bookmarks.active
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    41
    if active:
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    42
        if active in ui.configlist(MY_NAME, 'protect'):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    43
            raise error.Abort(
41031
b53c5651fcf6 py3: convert `'{}'.format(foo)` to `'%s' % foo` in the bookflow extension
Matt Harbison <matt_harbison@yahoo.com>
parents: 40834
diff changeset
    44
                _('cannot commit, bookmark %s is protected') % active)
40834
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    45
        if not cwd_at_bookmark(repo, active):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    46
            raise error.Abort(
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    47
       _('cannot commit, working directory out of sync with active bookmark'),
41031
b53c5651fcf6 py3: convert `'{}'.format(foo)` to `'%s' % foo` in the bookflow extension
Matt Harbison <matt_harbison@yahoo.com>
parents: 40834
diff changeset
    48
                hint=_("run 'hg up %s'") % active)
40834
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    49
    elif ui.configbool(MY_NAME, 'require-bookmark', True):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    50
        raise error.Abort(_('cannot commit without an active bookmark'))
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    51
    return 0
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    52
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    53
def bookmarks_update(orig, repo, parents, node):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    54
    if len(parents) == 2:
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    55
        # called during commit
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    56
        return orig(repo, parents, node)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    57
    else:
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    58
        # called during update
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    59
        return False
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    60
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    61
def bookmarks_addbookmarks(
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    62
        orig, repo, tr, names, rev=None, force=False, inactive=False):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    63
    if not rev:
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    64
        marks = repo._bookmarks
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    65
        for name in names:
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    66
            if name in marks:
41031
b53c5651fcf6 py3: convert `'{}'.format(foo)` to `'%s' % foo` in the bookflow extension
Matt Harbison <matt_harbison@yahoo.com>
parents: 40834
diff changeset
    67
                raise error.Abort(_(
b53c5651fcf6 py3: convert `'{}'.format(foo)` to `'%s' % foo` in the bookflow extension
Matt Harbison <matt_harbison@yahoo.com>
parents: 40834
diff changeset
    68
                    "bookmark %s already exists, to move use the --rev option"
b53c5651fcf6 py3: convert `'{}'.format(foo)` to `'%s' % foo` in the bookflow extension
Matt Harbison <matt_harbison@yahoo.com>
parents: 40834
diff changeset
    69
                    ) % name)
40834
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    70
    return orig(repo, tr, names, rev, force, inactive)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    71
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    72
def commands_commit(orig, ui, repo, *args, **opts):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    73
    commit_hook(ui, repo)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    74
    return orig(ui, repo, *args, **opts)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    75
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    76
def commands_pull(orig, ui, repo, *args, **opts):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    77
    rc = orig(ui, repo, *args, **opts)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    78
    active = repo._bookmarks.active
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    79
    if active and not cwd_at_bookmark(repo, active):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    80
        ui.warn(_(
41031
b53c5651fcf6 py3: convert `'{}'.format(foo)` to `'%s' % foo` in the bookflow extension
Matt Harbison <matt_harbison@yahoo.com>
parents: 40834
diff changeset
    81
            "working directory out of sync with active bookmark, run "
b53c5651fcf6 py3: convert `'{}'.format(foo)` to `'%s' % foo` in the bookflow extension
Matt Harbison <matt_harbison@yahoo.com>
parents: 40834
diff changeset
    82
            "'hg up %s'"
b53c5651fcf6 py3: convert `'{}'.format(foo)` to `'%s' % foo` in the bookflow extension
Matt Harbison <matt_harbison@yahoo.com>
parents: 40834
diff changeset
    83
        ) % active)
40834
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    84
    return rc
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    85
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    86
def commands_branch(orig, ui, repo, label=None, **opts):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    87
    if label and not opts.get(r'clean') and not opts.get(r'rev'):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    88
        raise error.Abort(
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    89
         _("creating named branches is disabled and you should use bookmarks"),
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    90
            hint="see 'hg help bookflow'")
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    91
    return orig(ui, repo, label, **opts)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    92
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    93
def cwd_at_bookmark(repo, mark):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    94
    mark_id = repo._bookmarks[mark]
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    95
    cur_id = repo.lookup('.')
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    96
    return cur_id == mark_id
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    97
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    98
def uisetup(ui):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
    99
    extensions.wrapfunction(bookmarks, 'update', bookmarks_update)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
   100
    extensions.wrapfunction(bookmarks, 'addbookmarks', bookmarks_addbookmarks)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
   101
    extensions.wrapcommand(commands.table, 'commit', commands_commit)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
   102
    extensions.wrapcommand(commands.table, 'pull', commands_pull)
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
   103
    if not ui.configbool(MY_NAME, 'enable-branches'):
9cec7a36bab8 bookflow: new extension for bookmark-based branching
idlsoft <idlsoft@gmail.com>
parents:
diff changeset
   104
        extensions.wrapcommand(commands.table, 'branch', commands_branch)