hgext/absorb.py
author Boris Feld <boris.feld@octobus.net>
Mon, 14 Jan 2019 18:19:22 +0100
changeset 41278 41f14e8f335f
parent 41260 c146651a78e1
child 41365 876494fd967d
permissions -rw-r--r--
revsetbenchmark: add more example for roots usages We test the `roots` revset in setting similar to our test for `heads`. Note that the algorithm used for roots can give result without consuming the full input set. This provides a significant speedup when testing or accessing a single value. We can't just replace it with simple, full algorithm like we did for `heads`. See performance number below: 0) roots((tip~100::) - (tip~100::tip)) 1) roots((0::) - (0::tip)) 2) roots(tip~100:) 3) roots(:42) 4) roots(not public()) 5) roots((0:tip)::) 6) roots(0::tip) 7) 42:68 and roots(42:tip) 8) roots(0:tip) 9) roots((:42) + (tip~42:)) 10) roots(all()) 11) roots(-10000:-1) 12) (-5000:-1000) and roots(-10000:-1) 13) roots(matching(tip, "author")) 14) roots(matching(tip, "author")) and -10000:-1 15) (-10000:-1) and roots(matching(tip, "author")) plain min max first last reverse rev..rst rev..ast sort sor..rst sor..ast 00) 0.000789 0.000801 0.000801 0.000819 0.000784 0.000774 0.000793 0.000816 0.000815 0.000831 0.000799 01) 0.097610 0.002717 0.096706 0.002615 0.059189 0.089033 0.059862 0.002644 0.098058 0.002640 0.058992 02) 0.000709 0.000117 0.000382 0.000136 0.000384 0.000724 0.000412 0.000133 0.000733 0.000159 0.000416 03) 0.000075 0.000064 0.000093 0.000080 0.000097 0.000089 0.000123 0.000079 0.000105 0.000102 0.000126 04) 0.000055 0.000071 0.000070 0.000087 0.000075 0.000066 0.000100 0.000085 0.000082 0.000110 0.000102 05) 0.088043 0.001084 0.087816 0.001097 0.048049 0.072454 0.047673 0.001089 0.088491 0.001163 0.047824 06) 0.058761 0.001727 0.059324 0.001850 0.058562 0.059198 0.058998 0.001743 0.058556 0.001874 0.059420 07) 0.000131 0.000121 0.000145 0.000138 0.000150 0.000142 0.000178 0.000135 0.000160 0.000163 0.000179 08) 0.058003 0.000077 0.032327 0.000093 0.031966 0.056812 0.031753 0.000092 0.057113 0.000116 0.031933 09) 0.000503 0.000145 0.000469 0.000161 0.000476 0.000564 0.000502 0.000160 0.000537 0.000187 0.000500 10) 0.056654 0.000058 0.033104 0.000073 0.032157 0.056598 0.031877 0.000071 0.056433 0.000094 0.031819 11) 0.005842 0.000081 0.001907 0.000101 0.001883 0.005868 0.001915 0.000099 0.005836 0.000122 0.001896 12) 0.003237 0.000634 0.001784 0.000655 0.001803 0.003245 0.001837 0.000649 0.003231 0.000680 0.001858
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
     1
# absorb.py
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
     2
#
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
     3
# Copyright 2016 Facebook, Inc.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
     4
#
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
     7
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
     8
"""apply working directory changes to changesets (EXPERIMENTAL)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
     9
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    10
The absorb extension provides a command to use annotate information to
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    11
amend modified chunks into the corresponding non-public changesets.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    12
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    13
::
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    14
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    15
    [absorb]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    16
    # only check 50 recent non-public changesets at most
38961
19344143b3e1 absorb: following UI conventions
David Demelier <markand@malikania.fr>
parents: 38932
diff changeset
    17
    max-stack-size = 50
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    18
    # whether to add noise to new commits to avoid obsolescence cycle
38961
19344143b3e1 absorb: following UI conventions
David Demelier <markand@malikania.fr>
parents: 38932
diff changeset
    19
    add-noise = 1
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    20
    # make `amend --correlated` a shortcut to the main command
38961
19344143b3e1 absorb: following UI conventions
David Demelier <markand@malikania.fr>
parents: 38932
diff changeset
    21
    amend-flag = correlated
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    22
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    23
    [color]
40188
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
    24
    absorb.description = yellow
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    25
    absorb.node = blue bold
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    26
    absorb.path = bold
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    27
"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    28
38922
ec0697f4f9c9 absorb: note some TODOs from the code review
Augie Fackler <augie@google.com>
parents: 38921
diff changeset
    29
# TODO:
ec0697f4f9c9 absorb: note some TODOs from the code review
Augie Fackler <augie@google.com>
parents: 38921
diff changeset
    30
#  * Rename config items to [commands] namespace
ec0697f4f9c9 absorb: note some TODOs from the code review
Augie Fackler <augie@google.com>
parents: 38921
diff changeset
    31
#  * Converge getdraftstack() with other code in core
ec0697f4f9c9 absorb: note some TODOs from the code review
Augie Fackler <augie@google.com>
parents: 38921
diff changeset
    32
#  * move many attributes on fixupstate to be private
ec0697f4f9c9 absorb: note some TODOs from the code review
Augie Fackler <augie@google.com>
parents: 38921
diff changeset
    33
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    34
from __future__ import absolute_import
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    35
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    36
import collections
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    37
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    38
from mercurial.i18n import _
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    39
from mercurial import (
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    40
    cmdutil,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    41
    commands,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    42
    context,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    43
    crecord,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    44
    error,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    45
    linelog,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    46
    mdiff,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    47
    node,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    48
    obsolete,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    49
    patch,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    50
    phases,
38920
a5c8c5476339 absorb: use pycompat to get xrange
Augie Fackler <augie@google.com>
parents: 38919
diff changeset
    51
    pycompat,
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    52
    registrar,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    53
    repair,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    54
    scmutil,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    55
    util,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    56
)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    57
from mercurial.utils import (
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    58
    stringutil,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    59
)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    60
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    61
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    62
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    63
# be specifying the version(s) of Mercurial they are tested with, or
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    64
# leave the attribute unspecified.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    65
testedwith = 'ships-with-hg-core'
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    66
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    67
cmdtable = {}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    68
command = registrar.command(cmdtable)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    69
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    70
configtable = {}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    71
configitem = registrar.configitem(configtable)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    72
38961
19344143b3e1 absorb: following UI conventions
David Demelier <markand@malikania.fr>
parents: 38932
diff changeset
    73
configitem('absorb', 'add-noise', default=True)
19344143b3e1 absorb: following UI conventions
David Demelier <markand@malikania.fr>
parents: 38932
diff changeset
    74
configitem('absorb', 'amend-flag', default=None)
19344143b3e1 absorb: following UI conventions
David Demelier <markand@malikania.fr>
parents: 38932
diff changeset
    75
configitem('absorb', 'max-stack-size', default=50)
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    76
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    77
colortable = {
40188
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
    78
    'absorb.description': 'yellow',
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    79
    'absorb.node': 'blue bold',
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    80
    'absorb.path': 'bold',
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    81
}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    82
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    83
defaultdict = collections.defaultdict
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    84
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    85
class nullui(object):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    86
    """blank ui object doing nothing"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    87
    debugflag = False
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    88
    verbose = False
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    89
    quiet = True
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    90
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    91
    def __getitem__(name):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    92
        def nullfunc(*args, **kwds):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    93
            return
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    94
        return nullfunc
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    95
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    96
class emptyfilecontext(object):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    97
    """minimal filecontext representing an empty file"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    98
    def data(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
    99
        return ''
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   100
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   101
    def node(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   102
        return node.nullid
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   103
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   104
def uniq(lst):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   105
    """list -> list. remove duplicated items without changing the order"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   106
    seen = set()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   107
    result = []
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   108
    for x in lst:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   109
        if x not in seen:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   110
            seen.add(x)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   111
            result.append(x)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   112
    return result
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   113
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   114
def getdraftstack(headctx, limit=None):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   115
    """(ctx, int?) -> [ctx]. get a linear stack of non-public changesets.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   116
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   117
    changesets are sorted in topo order, oldest first.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   118
    return at most limit items, if limit is a positive number.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   119
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   120
    merges are considered as non-draft as well. i.e. every commit
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   121
    returned has and only has 1 parent.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   122
    """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   123
    ctx = headctx
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   124
    result = []
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   125
    while ctx.phase() != phases.public:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   126
        if limit and len(result) >= limit:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   127
            break
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   128
        parents = ctx.parents()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   129
        if len(parents) != 1:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   130
            break
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   131
        result.append(ctx)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   132
        ctx = parents[0]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   133
    result.reverse()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   134
    return result
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   135
38918
2ac40e86f604 absorb: avoid mutable default arg
Augie Fackler <augie@google.com>
parents: 38917
diff changeset
   136
def getfilestack(stack, path, seenfctxs=None):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   137
    """([ctx], str, set) -> [fctx], {ctx: fctx}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   138
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   139
    stack is a list of contexts, from old to new. usually they are what
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   140
    "getdraftstack" returns.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   141
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   142
    follows renames, but not copies.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   143
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   144
    seenfctxs is a set of filecontexts that will be considered "immutable".
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   145
    they are usually what this function returned in earlier calls, useful
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   146
    to avoid issues that a file was "moved" to multiple places and was then
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   147
    modified differently, like: "a" was copied to "b", "a" was also copied to
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   148
    "c" and then "a" was deleted, then both "b" and "c" were "moved" from "a"
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   149
    and we enforce only one of them to be able to affect "a"'s content.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   150
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   151
    return an empty list and an empty dict, if the specified path does not
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   152
    exist in stack[-1] (the top of the stack).
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   153
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   154
    otherwise, return a list of de-duplicated filecontexts, and the map to
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   155
    convert ctx in the stack to fctx, for possible mutable fctxs. the first item
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   156
    of the list would be outside the stack and should be considered immutable.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   157
    the remaining items are within the stack.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   158
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   159
    for example, given the following changelog and corresponding filelog
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   160
    revisions:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   161
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   162
      changelog: 3----4----5----6----7
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   163
      filelog:   x    0----1----1----2 (x: no such file yet)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   164
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   165
    - if stack = [5, 6, 7], returns ([0, 1, 2], {5: 1, 6: 1, 7: 2})
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   166
    - if stack = [3, 4, 5], returns ([e, 0, 1], {4: 0, 5: 1}), where "e" is a
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   167
      dummy empty filecontext.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   168
    - if stack = [2], returns ([], {})
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   169
    - if stack = [7], returns ([1, 2], {7: 2})
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   170
    - if stack = [6, 7], returns ([1, 2], {6: 1, 7: 2}), although {6: 1} can be
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   171
      removed, since 1 is immutable.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   172
    """
38918
2ac40e86f604 absorb: avoid mutable default arg
Augie Fackler <augie@google.com>
parents: 38917
diff changeset
   173
    if seenfctxs is None:
2ac40e86f604 absorb: avoid mutable default arg
Augie Fackler <augie@google.com>
parents: 38917
diff changeset
   174
        seenfctxs = set()
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   175
    assert stack
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   176
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   177
    if path not in stack[-1]:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   178
        return [], {}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   179
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   180
    fctxs = []
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   181
    fctxmap = {}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   182
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   183
    pctx = stack[0].p1() # the public (immutable) ctx we stop at
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   184
    for ctx in reversed(stack):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   185
        if path not in ctx: # the file is added in the next commit
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   186
            pctx = ctx
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   187
            break
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   188
        fctx = ctx[path]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   189
        fctxs.append(fctx)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   190
        if fctx in seenfctxs: # treat fctx as the immutable one
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   191
            pctx = None # do not add another immutable fctx
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   192
            break
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   193
        fctxmap[ctx] = fctx # only for mutable fctxs
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   194
        renamed = fctx.renamed()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   195
        if renamed:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   196
            path = renamed[0] # follow rename
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   197
            if path in ctx: # but do not follow copy
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   198
                pctx = ctx.p1()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   199
                break
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   200
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   201
    if pctx is not None: # need an extra immutable fctx
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   202
        if path in pctx:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   203
            fctxs.append(pctx[path])
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   204
        else:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   205
            fctxs.append(emptyfilecontext())
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   206
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   207
    fctxs.reverse()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   208
    # note: we rely on a property of hg: filerev is not reused for linear
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   209
    # history. i.e. it's impossible to have:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   210
    #   changelog:  4----5----6 (linear, no merges)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   211
    #   filelog:    1----2----1
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   212
    #                         ^ reuse filerev (impossible)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   213
    # because parents are part of the hash. if that's not true, we need to
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   214
    # remove uniq and find a different way to identify fctxs.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   215
    return uniq(fctxs), fctxmap
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   216
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   217
class overlaystore(patch.filestore):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   218
    """read-only, hybrid store based on a dict and ctx.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   219
    memworkingcopy: {path: content}, overrides file contents.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   220
    """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   221
    def __init__(self, basectx, memworkingcopy):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   222
        self.basectx = basectx
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   223
        self.memworkingcopy = memworkingcopy
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   224
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   225
    def getfile(self, path):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   226
        """comply with mercurial.patch.filestore.getfile"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   227
        if path not in self.basectx:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   228
            return None, None, None
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   229
        fctx = self.basectx[path]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   230
        if path in self.memworkingcopy:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   231
            content = self.memworkingcopy[path]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   232
        else:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   233
            content = fctx.data()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   234
        mode = (fctx.islink(), fctx.isexec())
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   235
        renamed = fctx.renamed() # False or (path, node)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   236
        return content, mode, (renamed and renamed[0])
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   237
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   238
def overlaycontext(memworkingcopy, ctx, parents=None, extra=None):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   239
    """({path: content}, ctx, (p1node, p2node)?, {}?) -> memctx
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   240
    memworkingcopy overrides file contents.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   241
    """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   242
    # parents must contain 2 items: (node1, node2)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   243
    if parents is None:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   244
        parents = ctx.repo().changelog.parents(ctx.node())
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   245
    if extra is None:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   246
        extra = ctx.extra()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   247
    date = ctx.date()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   248
    desc = ctx.description()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   249
    user = ctx.user()
38987
9204445ad54c absorb: port partway to Python 3
Augie Fackler <augie@google.com>
parents: 38961
diff changeset
   250
    files = set(ctx.files()).union(memworkingcopy)
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   251
    store = overlaystore(ctx, memworkingcopy)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   252
    return context.memctx(
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   253
        repo=ctx.repo(), parents=parents, text=desc,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   254
        files=files, filectxfn=store, user=user, date=date,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   255
        branch=None, extra=extra)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   256
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   257
class filefixupstate(object):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   258
    """state needed to apply fixups to a single file
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   259
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   260
    internally, it keeps file contents of several revisions and a linelog.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   261
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   262
    the linelog uses odd revision numbers for original contents (fctxs passed
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   263
    to __init__), and even revision numbers for fixups, like:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   264
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   265
        linelog rev 1: self.fctxs[0] (from an immutable "public" changeset)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   266
        linelog rev 2: fixups made to self.fctxs[0]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   267
        linelog rev 3: self.fctxs[1] (a child of fctxs[0])
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   268
        linelog rev 4: fixups made to self.fctxs[1]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   269
        ...
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   270
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   271
    a typical use is like:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   272
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   273
        1. call diffwith, to calculate self.fixups
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   274
        2. (optionally), present self.fixups to the user, or change it
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   275
        3. call apply, to apply changes
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   276
        4. read results from "finalcontents", or call getfinalcontent
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   277
    """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   278
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   279
    def __init__(self, fctxs, path, ui=None, opts=None):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   280
        """([fctx], ui or None) -> None
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   281
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   282
        fctxs should be linear, and sorted by topo order - oldest first.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   283
        fctxs[0] will be considered as "immutable" and will not be changed.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   284
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   285
        self.fctxs = fctxs
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   286
        self.path = path
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   287
        self.ui = ui or nullui()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   288
        self.opts = opts or {}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   289
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   290
        # following fields are built from fctxs. they exist for perf reason
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   291
        self.contents = [f.data() for f in fctxs]
38987
9204445ad54c absorb: port partway to Python 3
Augie Fackler <augie@google.com>
parents: 38961
diff changeset
   292
        self.contentlines = pycompat.maplist(mdiff.splitnewlines, self.contents)
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   293
        self.linelog = self._buildlinelog()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   294
        if self.ui.debugflag:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   295
            assert self._checkoutlinelog() == self.contents
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   296
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   297
        # following fields will be filled later
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   298
        self.chunkstats = [0, 0] # [adopted, total : int]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   299
        self.targetlines = [] # [str]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   300
        self.fixups = [] # [(linelog rev, a1, a2, b1, b2)]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   301
        self.finalcontents = [] # [str]
40188
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   302
        self.ctxaffected = set()
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   303
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   304
    def diffwith(self, targetfctx, fm=None):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   305
        """calculate fixups needed by examining the differences between
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   306
        self.fctxs[-1] and targetfctx, chunk by chunk.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   307
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   308
        targetfctx is the target state we move towards. we may or may not be
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   309
        able to get there because not all modified chunks can be amended into
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   310
        a non-public fctx unambiguously.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   311
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   312
        call this only once, before apply().
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   313
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   314
        update self.fixups, self.chunkstats, and self.targetlines.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   315
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   316
        a = self.contents[-1]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   317
        alines = self.contentlines[-1]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   318
        b = targetfctx.data()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   319
        blines = mdiff.splitnewlines(b)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   320
        self.targetlines = blines
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   321
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   322
        self.linelog.annotate(self.linelog.maxrev)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   323
        annotated = self.linelog.annotateresult # [(linelog rev, linenum)]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   324
        assert len(annotated) == len(alines)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   325
        # add a dummy end line to make insertion at the end easier
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   326
        if annotated:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   327
            dummyendline = (annotated[-1][0], annotated[-1][1] + 1)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   328
            annotated.append(dummyendline)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   329
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   330
        # analyse diff blocks
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   331
        for chunk in self._alldiffchunks(a, b, alines, blines):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   332
            newfixups = self._analysediffchunk(chunk, annotated)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   333
            self.chunkstats[0] += bool(newfixups) # 1 or 0
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   334
            self.chunkstats[1] += 1
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   335
            self.fixups += newfixups
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   336
            if fm is not None:
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   337
                self._showchanges(fm, alines, blines, chunk, newfixups)
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   338
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   339
    def apply(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   340
        """apply self.fixups. update self.linelog, self.finalcontents.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   341
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   342
        call this only once, before getfinalcontent(), after diffwith().
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   343
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   344
        # the following is unnecessary, as it's done by "diffwith":
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   345
        #   self.linelog.annotate(self.linelog.maxrev)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   346
        for rev, a1, a2, b1, b2 in reversed(self.fixups):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   347
            blines = self.targetlines[b1:b2]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   348
            if self.ui.debugflag:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   349
                idx = (max(rev - 1, 0)) // 2
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   350
                self.ui.write(_('%s: chunk %d:%d -> %d lines\n')
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   351
                              % (node.short(self.fctxs[idx].node()),
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   352
                                 a1, a2, len(blines)))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   353
            self.linelog.replacelines(rev, a1, a2, b1, b2)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   354
        if self.opts.get('edit_lines', False):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   355
            self.finalcontents = self._checkoutlinelogwithedits()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   356
        else:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   357
            self.finalcontents = self._checkoutlinelog()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   358
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   359
    def getfinalcontent(self, fctx):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   360
        """(fctx) -> str. get modified file content for a given filecontext"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   361
        idx = self.fctxs.index(fctx)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   362
        return self.finalcontents[idx]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   363
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   364
    def _analysediffchunk(self, chunk, annotated):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   365
        """analyse a different chunk and return new fixups found
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   366
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   367
        return [] if no lines from the chunk can be safely applied.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   368
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   369
        the chunk (or lines) cannot be safely applied, if, for example:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   370
          - the modified (deleted) lines belong to a public changeset
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   371
            (self.fctxs[0])
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   372
          - the chunk is a pure insertion and the adjacent lines (at most 2
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   373
            lines) belong to different non-public changesets, or do not belong
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   374
            to any non-public changesets.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   375
          - the chunk is modifying lines from different changesets.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   376
            in this case, if the number of lines deleted equals to the number
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   377
            of lines added, assume it's a simple 1:1 map (could be wrong).
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   378
            otherwise, give up.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   379
          - the chunk is modifying lines from a single non-public changeset,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   380
            but other revisions touch the area as well. i.e. the lines are
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   381
            not continuous as seen from the linelog.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   382
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   383
        a1, a2, b1, b2 = chunk
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   384
        # find involved indexes from annotate result
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   385
        involved = annotated[a1:a2]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   386
        if not involved and annotated: # a1 == a2 and a is not empty
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   387
            # pure insertion, check nearby lines. ignore lines belong
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   388
            # to the public (first) changeset (i.e. annotated[i][0] == 1)
38919
dc4750b2a04e absorb: use set literal to avoid intermediate list
Augie Fackler <augie@google.com>
parents: 38918
diff changeset
   389
            nearbylinenums = {a2, max(0, a1 - 1)}
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   390
            involved = [annotated[i]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   391
                        for i in nearbylinenums if annotated[i][0] != 1]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   392
        involvedrevs = list(set(r for r, l in involved))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   393
        newfixups = []
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   394
        if len(involvedrevs) == 1 and self._iscontinuous(a1, a2 - 1, True):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   395
            # chunk belongs to a single revision
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   396
            rev = involvedrevs[0]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   397
            if rev > 1:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   398
                fixuprev = rev + 1
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   399
                newfixups.append((fixuprev, a1, a2, b1, b2))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   400
        elif a2 - a1 == b2 - b1 or b1 == b2:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   401
            # 1:1 line mapping, or chunk was deleted
38920
a5c8c5476339 absorb: use pycompat to get xrange
Augie Fackler <augie@google.com>
parents: 38919
diff changeset
   402
            for i in pycompat.xrange(a1, a2):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   403
                rev, linenum = annotated[i]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   404
                if rev > 1:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   405
                    if b1 == b2: # deletion, simply remove that single line
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   406
                        nb1 = nb2 = 0
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   407
                    else: # 1:1 line mapping, change the corresponding rev
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   408
                        nb1 = b1 + i - a1
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   409
                        nb2 = nb1 + 1
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   410
                    fixuprev = rev + 1
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   411
                    newfixups.append((fixuprev, i, i + 1, nb1, nb2))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   412
        return self._optimizefixups(newfixups)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   413
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   414
    @staticmethod
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   415
    def _alldiffchunks(a, b, alines, blines):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   416
        """like mdiff.allblocks, but only care about differences"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   417
        blocks = mdiff.allblocks(a, b, lines1=alines, lines2=blines)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   418
        for chunk, btype in blocks:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   419
            if btype != '!':
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   420
                continue
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   421
            yield chunk
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   422
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   423
    def _buildlinelog(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   424
        """calculate the initial linelog based on self.content{,line}s.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   425
        this is similar to running a partial "annotate".
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   426
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   427
        llog = linelog.linelog()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   428
        a, alines = '', []
38920
a5c8c5476339 absorb: use pycompat to get xrange
Augie Fackler <augie@google.com>
parents: 38919
diff changeset
   429
        for i in pycompat.xrange(len(self.contents)):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   430
            b, blines = self.contents[i], self.contentlines[i]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   431
            llrev = i * 2 + 1
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   432
            chunks = self._alldiffchunks(a, b, alines, blines)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   433
            for a1, a2, b1, b2 in reversed(list(chunks)):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   434
                llog.replacelines(llrev, a1, a2, b1, b2)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   435
            a, alines = b, blines
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   436
        return llog
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   437
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   438
    def _checkoutlinelog(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   439
        """() -> [str]. check out file contents from linelog"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   440
        contents = []
38920
a5c8c5476339 absorb: use pycompat to get xrange
Augie Fackler <augie@google.com>
parents: 38919
diff changeset
   441
        for i in pycompat.xrange(len(self.contents)):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   442
            rev = (i + 1) * 2
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   443
            self.linelog.annotate(rev)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   444
            content = ''.join(map(self._getline, self.linelog.annotateresult))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   445
            contents.append(content)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   446
        return contents
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   447
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   448
    def _checkoutlinelogwithedits(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   449
        """() -> [str]. prompt all lines for edit"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   450
        alllines = self.linelog.getalllines()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   451
        # header
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   452
        editortext = (_('HG: editing %s\nHG: "y" means the line to the right '
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   453
                        'exists in the changeset to the top\nHG:\n')
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   454
                      % self.fctxs[-1].path())
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   455
        # [(idx, fctx)]. hide the dummy emptyfilecontext
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   456
        visiblefctxs = [(i, f)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   457
                        for i, f in enumerate(self.fctxs)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   458
                        if not isinstance(f, emptyfilecontext)]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   459
        for i, (j, f) in enumerate(visiblefctxs):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   460
            editortext += (_('HG: %s/%s %s %s\n') %
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   461
                           ('|' * i, '-' * (len(visiblefctxs) - i + 1),
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   462
                            node.short(f.node()),
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   463
                            f.description().split('\n',1)[0]))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   464
        editortext += _('HG: %s\n') % ('|' * len(visiblefctxs))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   465
        # figure out the lifetime of a line, this is relatively inefficient,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   466
        # but probably fine
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   467
        lineset = defaultdict(lambda: set()) # {(llrev, linenum): {llrev}}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   468
        for i, f in visiblefctxs:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   469
            self.linelog.annotate((i + 1) * 2)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   470
            for l in self.linelog.annotateresult:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   471
                lineset[l].add(i)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   472
        # append lines
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   473
        for l in alllines:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   474
            editortext += ('    %s : %s' %
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   475
                           (''.join([('y' if i in lineset[l] else ' ')
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   476
                                     for i, _f in visiblefctxs]),
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   477
                            self._getline(l)))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   478
        # run editor
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   479
        editedtext = self.ui.edit(editortext, '', action='absorb')
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   480
        if not editedtext:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   481
            raise error.Abort(_('empty editor text'))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   482
        # parse edited result
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   483
        contents = ['' for i in self.fctxs]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   484
        leftpadpos = 4
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   485
        colonpos = leftpadpos + len(visiblefctxs) + 1
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   486
        for l in mdiff.splitnewlines(editedtext):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   487
            if l.startswith('HG:'):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   488
                continue
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   489
            if l[colonpos - 1:colonpos + 2] != ' : ':
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   490
                raise error.Abort(_('malformed line: %s') % l)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   491
            linecontent = l[colonpos + 2:]
41260
c146651a78e1 absorb: add a pycompat.bytestr() to fix --edit-lines functionality on Python 3
Augie Fackler <augie@google.com>
parents: 40951
diff changeset
   492
            for i, ch in enumerate(
c146651a78e1 absorb: add a pycompat.bytestr() to fix --edit-lines functionality on Python 3
Augie Fackler <augie@google.com>
parents: 40951
diff changeset
   493
                    pycompat.bytestr(l[leftpadpos:colonpos - 1])):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   494
                if ch == 'y':
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   495
                    contents[visiblefctxs[i][0]] += linecontent
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   496
        # chunkstats is hard to calculate if anything changes, therefore
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   497
        # set them to just a simple value (1, 1).
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   498
        if editedtext != editortext:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   499
            self.chunkstats = [1, 1]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   500
        return contents
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   501
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   502
    def _getline(self, lineinfo):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   503
        """((rev, linenum)) -> str. convert rev+line number to line content"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   504
        rev, linenum = lineinfo
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   505
        if rev & 1: # odd: original line taken from fctxs
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   506
            return self.contentlines[rev // 2][linenum]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   507
        else: # even: fixup line from targetfctx
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   508
            return self.targetlines[linenum]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   509
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   510
    def _iscontinuous(self, a1, a2, closedinterval=False):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   511
        """(a1, a2 : int) -> bool
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   512
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   513
        check if these lines are continuous. i.e. no other insertions or
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   514
        deletions (from other revisions) among these lines.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   515
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   516
        closedinterval decides whether a2 should be included or not. i.e. is
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   517
        it [a1, a2), or [a1, a2] ?
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   518
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   519
        if a1 >= a2:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   520
            return True
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   521
        llog = self.linelog
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   522
        offset1 = llog.getoffset(a1)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   523
        offset2 = llog.getoffset(a2) + int(closedinterval)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   524
        linesinbetween = llog.getalllines(offset1, offset2)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   525
        return len(linesinbetween) == a2 - a1 + int(closedinterval)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   526
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   527
    def _optimizefixups(self, fixups):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   528
        """[(rev, a1, a2, b1, b2)] -> [(rev, a1, a2, b1, b2)].
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   529
        merge adjacent fixups to make them less fragmented.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   530
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   531
        result = []
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   532
        pcurrentchunk = [[-1, -1, -1, -1, -1]]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   533
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   534
        def pushchunk():
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   535
            if pcurrentchunk[0][0] != -1:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   536
                result.append(tuple(pcurrentchunk[0]))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   537
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   538
        for i, chunk in enumerate(fixups):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   539
            rev, a1, a2, b1, b2 = chunk
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   540
            lastrev = pcurrentchunk[0][0]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   541
            lasta2 = pcurrentchunk[0][2]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   542
            lastb2 = pcurrentchunk[0][4]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   543
            if (a1 == lasta2 and b1 == lastb2 and rev == lastrev and
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   544
                    self._iscontinuous(max(a1 - 1, 0), a1)):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   545
                # merge into currentchunk
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   546
                pcurrentchunk[0][2] = a2
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   547
                pcurrentchunk[0][4] = b2
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   548
            else:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   549
                pushchunk()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   550
                pcurrentchunk[0] = list(chunk)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   551
        pushchunk()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   552
        return result
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   553
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   554
    def _showchanges(self, fm, alines, blines, chunk, fixups):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   555
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   556
        def trim(line):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   557
            if line.endswith('\n'):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   558
                line = line[:-1]
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   559
            return line
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   560
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   561
        # this is not optimized for perf but _showchanges only gets executed
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   562
        # with an extra command-line flag.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   563
        a1, a2, b1, b2 = chunk
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   564
        aidxs, bidxs = [0] * (a2 - a1), [0] * (b2 - b1)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   565
        for idx, fa1, fa2, fb1, fb2 in fixups:
38920
a5c8c5476339 absorb: use pycompat to get xrange
Augie Fackler <augie@google.com>
parents: 38919
diff changeset
   566
            for i in pycompat.xrange(fa1, fa2):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   567
                aidxs[i - a1] = (max(idx, 1) - 1) // 2
38920
a5c8c5476339 absorb: use pycompat to get xrange
Augie Fackler <augie@google.com>
parents: 38919
diff changeset
   568
            for i in pycompat.xrange(fb1, fb2):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   569
                bidxs[i - b1] = (max(idx, 1) - 1) // 2
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   570
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   571
        fm.startitem()
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   572
        fm.write('hunk', '        %s\n',
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   573
                 '@@ -%d,%d +%d,%d @@'
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   574
                 % (a1, a2 - a1, b1, b2 - b1), label='diff.hunk')
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   575
        fm.data(path=self.path, linetype='hunk')
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   576
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   577
        def writeline(idx, diffchar, line, linetype, linelabel):
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   578
            fm.startitem()
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   579
            node = ''
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   580
            if idx:
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   581
                ctx = self.fctxs[idx]
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   582
                fm.context(fctx=ctx)
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   583
                node = ctx.hex()
40188
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   584
                self.ctxaffected.add(ctx.changectx())
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   585
            fm.write('node', '%-7.7s ', node, label='absorb.node')
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   586
            fm.write('diffchar ' + linetype, '%s%s\n', diffchar, line,
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   587
                     label=linelabel)
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   588
            fm.data(path=self.path, linetype=linetype)
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   589
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   590
        for i in pycompat.xrange(a1, a2):
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   591
            writeline(aidxs[i - a1], '-', trim(alines[i]), 'deleted',
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   592
                      'diff.deleted')
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   593
        for i in pycompat.xrange(b1, b2):
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   594
            writeline(bidxs[i - b1], '+', trim(blines[i]), 'inserted',
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   595
                      'diff.inserted')
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   596
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   597
class fixupstate(object):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   598
    """state needed to run absorb
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   599
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   600
    internally, it keeps paths and filefixupstates.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   601
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   602
    a typical use is like filefixupstates:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   603
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   604
        1. call diffwith, to calculate fixups
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   605
        2. (optionally), present fixups to the user, or edit fixups
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   606
        3. call apply, to apply changes to memory
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   607
        4. call commit, to commit changes to hg database
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   608
    """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   609
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   610
    def __init__(self, stack, ui=None, opts=None):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   611
        """([ctx], ui or None) -> None
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   612
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   613
        stack: should be linear, and sorted by topo order - oldest first.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   614
        all commits in stack are considered mutable.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   615
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   616
        assert stack
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   617
        self.ui = ui or nullui()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   618
        self.opts = opts or {}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   619
        self.stack = stack
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   620
        self.repo = stack[-1].repo().unfiltered()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   621
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   622
        # following fields will be filled later
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   623
        self.paths = [] # [str]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   624
        self.status = None # ctx.status output
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   625
        self.fctxmap = {} # {path: {ctx: fctx}}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   626
        self.fixupmap = {} # {path: filefixupstate}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   627
        self.replacemap = {} # {oldnode: newnode or None}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   628
        self.finalnode = None # head after all fixups
40188
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   629
        self.ctxaffected = set() # ctx that will be absorbed into
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   630
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   631
    def diffwith(self, targetctx, match=None, fm=None):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   632
        """diff and prepare fixups. update self.fixupmap, self.paths"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   633
        # only care about modified files
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   634
        self.status = self.stack[-1].status(targetctx, match)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   635
        self.paths = []
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   636
        # but if --edit-lines is used, the user may want to edit files
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   637
        # even if they are not modified
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   638
        editopt = self.opts.get('edit_lines')
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   639
        if not self.status.modified and editopt and match:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   640
            interestingpaths = match.files()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   641
        else:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   642
            interestingpaths = self.status.modified
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   643
        # prepare the filefixupstate
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   644
        seenfctxs = set()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   645
        # sorting is necessary to eliminate ambiguity for the "double move"
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   646
        # case: "hg cp A B; hg cp A C; hg rm A", then only "B" can affect "A".
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   647
        for path in sorted(interestingpaths):
38921
e930df0f9a55 absorb: use ui.debug() instead of open-coding it
Augie Fackler <augie@google.com>
parents: 38920
diff changeset
   648
            self.ui.debug('calculating fixups for %s\n' % path)
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   649
            targetfctx = targetctx[path]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   650
            fctxs, ctx2fctx = getfilestack(self.stack, path, seenfctxs)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   651
            # ignore symbolic links or binary, or unchanged files
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   652
            if any(f.islink() or stringutil.binary(f.data())
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   653
                   for f in [targetfctx] + fctxs
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   654
                   if not isinstance(f, emptyfilecontext)):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   655
                continue
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   656
            if targetfctx.data() == fctxs[-1].data() and not editopt:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   657
                continue
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   658
            seenfctxs.update(fctxs[1:])
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   659
            self.fctxmap[path] = ctx2fctx
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   660
            fstate = filefixupstate(fctxs, path, ui=self.ui, opts=self.opts)
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   661
            if fm is not None:
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   662
                fm.startitem()
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   663
                fm.plain('showing changes for ')
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   664
                fm.write('path', '%s\n', path, label='absorb.path')
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   665
                fm.data(linetype='path')
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   666
            fstate.diffwith(targetfctx, fm)
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   667
            self.fixupmap[path] = fstate
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   668
            self.paths.append(path)
40188
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   669
            self.ctxaffected.update(fstate.ctxaffected)
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   670
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   671
    def apply(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   672
        """apply fixups to individual filefixupstates"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   673
        for path, state in self.fixupmap.iteritems():
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   674
            if self.ui.debugflag:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   675
                self.ui.write(_('applying fixups to %s\n') % path)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   676
            state.apply()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   677
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   678
    @property
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   679
    def chunkstats(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   680
        """-> {path: chunkstats}. collect chunkstats from filefixupstates"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   681
        return dict((path, state.chunkstats)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   682
                    for path, state in self.fixupmap.iteritems())
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   683
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   684
    def commit(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   685
        """commit changes. update self.finalnode, self.replacemap"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   686
        with self.repo.wlock(), self.repo.lock():
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   687
            with self.repo.transaction('absorb') as tr:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   688
                self._commitstack()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   689
                self._movebookmarks(tr)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   690
                if self.repo['.'].node() in self.replacemap:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   691
                    self._moveworkingdirectoryparent()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   692
                if self._useobsolete:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   693
                    self._obsoleteoldcommits()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   694
            if not self._useobsolete: # strip must be outside transactions
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   695
                self._stripoldcommits()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   696
        return self.finalnode
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   697
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   698
    def printchunkstats(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   699
        """print things like '1 of 2 chunk(s) applied'"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   700
        ui = self.ui
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   701
        chunkstats = self.chunkstats
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   702
        if ui.verbose:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   703
            # chunkstats for each file
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   704
            for path, stat in chunkstats.iteritems():
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   705
                if stat[0]:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   706
                    ui.write(_('%s: %d of %d chunk(s) applied\n')
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   707
                             % (path, stat[0], stat[1]))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   708
        elif not ui.quiet:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   709
            # a summary for all files
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   710
            stats = chunkstats.values()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   711
            applied, total = (sum(s[i] for s in stats) for i in (0, 1))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   712
            ui.write(_('%d of %d chunk(s) applied\n') % (applied, total))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   713
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   714
    def _commitstack(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   715
        """make new commits. update self.finalnode, self.replacemap.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   716
        it is splitted from "commit" to avoid too much indentation.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   717
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   718
        # last node (20-char) committed by us
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   719
        lastcommitted = None
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   720
        # p1 which overrides the parent of the next commit, "None" means use
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   721
        # the original parent unchanged
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   722
        nextp1 = None
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   723
        for ctx in self.stack:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   724
            memworkingcopy = self._getnewfilecontents(ctx)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   725
            if not memworkingcopy and not lastcommitted:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   726
                # nothing changed, nothing commited
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   727
                nextp1 = ctx
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   728
                continue
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   729
            msg = ''
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   730
            if self._willbecomenoop(memworkingcopy, ctx, nextp1):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   731
                # changeset is no longer necessary
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   732
                self.replacemap[ctx.node()] = None
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   733
                msg = _('became empty and was dropped')
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   734
            else:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   735
                # changeset needs re-commit
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   736
                nodestr = self._commitsingle(memworkingcopy, ctx, p1=nextp1)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   737
                lastcommitted = self.repo[nodestr]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   738
                nextp1 = lastcommitted
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   739
                self.replacemap[ctx.node()] = lastcommitted.node()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   740
                if memworkingcopy:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   741
                    msg = _('%d file(s) changed, became %s') % (
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   742
                        len(memworkingcopy), self._ctx2str(lastcommitted))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   743
                else:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   744
                    msg = _('became %s') % self._ctx2str(lastcommitted)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   745
            if self.ui.verbose and msg:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   746
                self.ui.write(_('%s: %s\n') % (self._ctx2str(ctx), msg))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   747
        self.finalnode = lastcommitted and lastcommitted.node()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   748
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   749
    def _ctx2str(self, ctx):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   750
        if self.ui.debugflag:
40150
1be1689d9ce9 absorb: print '{rev}:' as a prefix to the hash
Matt Harbison <matt_harbison@yahoo.com>
parents: 39786
diff changeset
   751
            return '%d:%s' % (ctx.rev(), ctx.hex())
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   752
        else:
40150
1be1689d9ce9 absorb: print '{rev}:' as a prefix to the hash
Matt Harbison <matt_harbison@yahoo.com>
parents: 39786
diff changeset
   753
            return '%d:%s' % (ctx.rev(), node.short(ctx.node()))
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   754
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   755
    def _getnewfilecontents(self, ctx):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   756
        """(ctx) -> {path: str}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   757
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   758
        fetch file contents from filefixupstates.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   759
        return the working copy overrides - files different from ctx.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   760
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   761
        result = {}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   762
        for path in self.paths:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   763
            ctx2fctx = self.fctxmap[path] # {ctx: fctx}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   764
            if ctx not in ctx2fctx:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   765
                continue
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   766
            fctx = ctx2fctx[ctx]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   767
            content = fctx.data()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   768
            newcontent = self.fixupmap[path].getfinalcontent(fctx)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   769
            if content != newcontent:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   770
                result[fctx.path()] = newcontent
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   771
        return result
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   772
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   773
    def _movebookmarks(self, tr):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   774
        repo = self.repo
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   775
        needupdate = [(name, self.replacemap[hsh])
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   776
                      for name, hsh in repo._bookmarks.iteritems()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   777
                      if hsh in self.replacemap]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   778
        changes = []
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   779
        for name, hsh in needupdate:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   780
            if hsh:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   781
                changes.append((name, hsh))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   782
                if self.ui.verbose:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   783
                    self.ui.write(_('moving bookmark %s to %s\n')
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   784
                                  % (name, node.hex(hsh)))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   785
            else:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   786
                changes.append((name, None))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   787
                if self.ui.verbose:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   788
                    self.ui.write(_('deleting bookmark %s\n') % name)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   789
        repo._bookmarks.applychanges(repo, tr, changes)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   790
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   791
    def _moveworkingdirectoryparent(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   792
        if not self.finalnode:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   793
            # Find the latest not-{obsoleted,stripped} parent.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   794
            revs = self.repo.revs('max(::. - %ln)', self.replacemap.keys())
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   795
            ctx = self.repo[revs.first()]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   796
            self.finalnode = ctx.node()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   797
        else:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   798
            ctx = self.repo[self.finalnode]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   799
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   800
        dirstate = self.repo.dirstate
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   801
        # dirstate.rebuild invalidates fsmonitorstate, causing "hg status" to
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   802
        # be slow. in absorb's case, no need to invalidate fsmonitorstate.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   803
        noop = lambda: 0
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   804
        restore = noop
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   805
        if util.safehasattr(dirstate, '_fsmonitorstate'):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   806
            bak = dirstate._fsmonitorstate.invalidate
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   807
            def restore():
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   808
                dirstate._fsmonitorstate.invalidate = bak
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   809
            dirstate._fsmonitorstate.invalidate = noop
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   810
        try:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   811
            with dirstate.parentchange():
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   812
                dirstate.rebuild(ctx.node(), ctx.manifest(), self.paths)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   813
        finally:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   814
            restore()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   815
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   816
    @staticmethod
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   817
    def _willbecomenoop(memworkingcopy, ctx, pctx=None):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   818
        """({path: content}, ctx, ctx) -> bool. test if a commit will be noop
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   819
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   820
        if it will become an empty commit (does not change anything, after the
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   821
        memworkingcopy overrides), return True. otherwise return False.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   822
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   823
        if not pctx:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   824
            parents = ctx.parents()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   825
            if len(parents) != 1:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   826
                return False
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   827
            pctx = parents[0]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   828
        # ctx changes more files (not a subset of memworkingcopy)
38987
9204445ad54c absorb: port partway to Python 3
Augie Fackler <augie@google.com>
parents: 38961
diff changeset
   829
        if not set(ctx.files()).issubset(set(memworkingcopy)):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   830
            return False
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   831
        for path, content in memworkingcopy.iteritems():
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   832
            if path not in pctx or path not in ctx:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   833
                return False
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   834
            fctx = ctx[path]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   835
            pfctx = pctx[path]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   836
            if pfctx.flags() != fctx.flags():
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   837
                return False
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   838
            if pfctx.data() != content:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   839
                return False
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   840
        return True
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   841
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   842
    def _commitsingle(self, memworkingcopy, ctx, p1=None):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   843
        """(ctx, {path: content}, node) -> node. make a single commit
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   844
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   845
        the commit is a clone from ctx, with a (optionally) different p1, and
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   846
        different file contents replaced by memworkingcopy.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   847
        """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   848
        parents = p1 and (p1, node.nullid)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   849
        extra = ctx.extra()
38961
19344143b3e1 absorb: following UI conventions
David Demelier <markand@malikania.fr>
parents: 38932
diff changeset
   850
        if self._useobsolete and self.ui.configbool('absorb', 'add-noise'):
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   851
            extra['absorb_source'] = ctx.hex()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   852
        mctx = overlaycontext(memworkingcopy, ctx, parents, extra=extra)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   853
        # preserve phase
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   854
        with mctx.repo().ui.configoverride({
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   855
            ('phases', 'new-commit'): ctx.phase()}):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   856
            return mctx.commit()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   857
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   858
    @util.propertycache
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   859
    def _useobsolete(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   860
        """() -> bool"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   861
        return obsolete.isenabled(self.repo, obsolete.createmarkersopt)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   862
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   863
    def _obsoleteoldcommits(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   864
        relations = [(self.repo[k], v and (self.repo[v],) or ())
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   865
                     for k, v in self.replacemap.iteritems()]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   866
        if relations:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   867
            obsolete.createmarkers(self.repo, relations)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   868
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   869
    def _stripoldcommits(self):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   870
        nodelist = self.replacemap.keys()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   871
        # make sure we don't strip innocent children
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   872
        revs = self.repo.revs('%ln - (::(heads(%ln::)-%ln))', nodelist,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   873
                              nodelist, nodelist)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   874
        tonode = self.repo.changelog.node
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   875
        nodelist = [tonode(r) for r in revs]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   876
        if nodelist:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   877
            repair.strip(self.repo.ui, self.repo, nodelist)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   878
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   879
def _parsechunk(hunk):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   880
    """(crecord.uihunk or patch.recordhunk) -> (path, (a1, a2, [bline]))"""
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   881
    if type(hunk) not in (crecord.uihunk, patch.recordhunk):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   882
        return None, None
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   883
    path = hunk.header.filename()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   884
    a1 = hunk.fromline + len(hunk.before) - 1
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   885
    # remove before and after context
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   886
    hunk.before = hunk.after = []
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   887
    buf = util.stringio()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   888
    hunk.write(buf)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   889
    patchlines = mdiff.splitnewlines(buf.getvalue())
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   890
    # hunk.prettystr() will update hunk.removed
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   891
    a2 = a1 + hunk.removed
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   892
    blines = [l[1:] for l in patchlines[1:] if l[0] != '-']
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   893
    return path, (a1, a2, blines)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   894
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   895
def overlaydiffcontext(ctx, chunks):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   896
    """(ctx, [crecord.uihunk]) -> memctx
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   897
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   898
    return a memctx with some [1] patches (chunks) applied to ctx.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   899
    [1]: modifications are handled. renames, mode changes, etc. are ignored.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   900
    """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   901
    # sadly the applying-patch logic is hardly reusable, and messy:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   902
    # 1. the core logic "_applydiff" is too heavy - it writes .rej files, it
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   903
    #    needs a file stream of a patch and will re-parse it, while we have
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   904
    #    structured hunk objects at hand.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   905
    # 2. a lot of different implementations about "chunk" (patch.hunk,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   906
    #    patch.recordhunk, crecord.uihunk)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   907
    # as we only care about applying changes to modified files, no mode
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   908
    # change, no binary diff, and no renames, it's probably okay to
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   909
    # re-invent the logic using much simpler code here.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   910
    memworkingcopy = {} # {path: content}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   911
    patchmap = defaultdict(lambda: []) # {path: [(a1, a2, [bline])]}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   912
    for path, info in map(_parsechunk, chunks):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   913
        if not path or not info:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   914
            continue
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   915
        patchmap[path].append(info)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   916
    for path, patches in patchmap.iteritems():
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   917
        if path not in ctx or not patches:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   918
            continue
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   919
        patches.sort(reverse=True)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   920
        lines = mdiff.splitnewlines(ctx[path].data())
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   921
        for a1, a2, blines in patches:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   922
            lines[a1:a2] = blines
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   923
        memworkingcopy[path] = ''.join(lines)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   924
    return overlaycontext(memworkingcopy, ctx)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   925
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   926
def absorb(ui, repo, stack=None, targetctx=None, pats=None, opts=None):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   927
    """pick fixup chunks from targetctx, apply them to stack.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   928
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   929
    if targetctx is None, the working copy context will be used.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   930
    if stack is None, the current draft stack will be used.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   931
    return fixupstate.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   932
    """
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   933
    if stack is None:
38961
19344143b3e1 absorb: following UI conventions
David Demelier <markand@malikania.fr>
parents: 38932
diff changeset
   934
        limit = ui.configint('absorb', 'max-stack-size')
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   935
        stack = getdraftstack(repo['.'], limit)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   936
        if limit and len(stack) >= limit:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   937
            ui.warn(_('absorb: only the recent %d changesets will '
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   938
                      'be analysed\n')
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   939
                    % limit)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   940
    if not stack:
39453
ab452995eaff absorb: clarify the reason for not finding changesets to modify
Matt Harbison <matt_harbison@yahoo.com>
parents: 38987
diff changeset
   941
        raise error.Abort(_('no mutable changeset to change'))
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   942
    if targetctx is None: # default to working copy
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   943
        targetctx = repo[None]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   944
    if pats is None:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   945
        pats = ()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   946
    if opts is None:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   947
        opts = {}
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   948
    state = fixupstate(stack, ui=ui, opts=opts)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   949
    matcher = scmutil.match(targetctx, pats, opts)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   950
    if opts.get('interactive'):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   951
        diff = patch.diff(repo, stack[-1].node(), targetctx.node(), matcher)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   952
        origchunks = patch.parsepatch(diff)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   953
        chunks = cmdutil.recordfilter(ui, origchunks)[0]
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   954
        targetctx = overlaydiffcontext(stack[-1], chunks)
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   955
    fm = None
40190
31dfa7dac4c9 absorb: prompt user to accept absorb changes by default
Mark Thomas <mbthomas@fb.com>
parents: 40188
diff changeset
   956
    if opts.get('print_changes') or not opts.get('apply_changes'):
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   957
        fm = ui.formatter('absorb', opts)
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   958
    state.diffwith(targetctx, matcher, fm)
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   959
    if fm is not None:
40188
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   960
        fm.startitem()
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   961
        fm.write("count", "\n%d changesets affected\n", len(state.ctxaffected))
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   962
        fm.data(linetype='summary')
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   963
        for ctx in reversed(stack):
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   964
            if ctx not in state.ctxaffected:
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   965
                continue
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   966
            fm.startitem()
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   967
            fm.context(ctx=ctx)
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   968
            fm.data(linetype='changeset')
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   969
            fm.write('node', '%-7.7s ', ctx.hex(), label='absorb.node')
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   970
            descfirstline = ctx.description().splitlines()[0]
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   971
            fm.write('descfirstline', '%s\n', descfirstline,
2c5316796f45 absorb: print summary of changesets affected
Mark Thomas <mbthomas@fb.com>
parents: 40187
diff changeset
   972
                     label='absorb.description')
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   973
        fm.end()
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   974
    if not opts.get('dry_run'):
40951
e993a86cfcb8 absorb: don't prompt to apply changes when there are none to apply
Danny Hooper <hooper@google.com>
parents: 40295
diff changeset
   975
        if (not opts.get('apply_changes') and
e993a86cfcb8 absorb: don't prompt to apply changes when there are none to apply
Danny Hooper <hooper@google.com>
parents: 40295
diff changeset
   976
            state.ctxaffected and
e993a86cfcb8 absorb: don't prompt to apply changes when there are none to apply
Danny Hooper <hooper@google.com>
parents: 40295
diff changeset
   977
            ui.promptchoice("apply changes (yn)? $$ &Yes $$ &No", default=1)):
e993a86cfcb8 absorb: don't prompt to apply changes when there are none to apply
Danny Hooper <hooper@google.com>
parents: 40295
diff changeset
   978
            raise error.Abort(_('absorb cancelled\n'))
40190
31dfa7dac4c9 absorb: prompt user to accept absorb changes by default
Mark Thomas <mbthomas@fb.com>
parents: 40188
diff changeset
   979
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   980
        state.apply()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   981
        if state.commit():
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   982
            state.printchunkstats()
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   983
        elif not ui.quiet:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   984
            ui.write(_('nothing applied\n'))
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   985
    return state
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   986
40295
fa88170c10bb help: adding a proper declaration for shortlist/basic commands (API)
Rodrigo Damazio <rdamazio@google.com>
parents: 40293
diff changeset
   987
@command('absorb',
40190
31dfa7dac4c9 absorb: prompt user to accept absorb changes by default
Mark Thomas <mbthomas@fb.com>
parents: 40188
diff changeset
   988
         [('a', 'apply-changes', None,
31dfa7dac4c9 absorb: prompt user to accept absorb changes by default
Mark Thomas <mbthomas@fb.com>
parents: 40188
diff changeset
   989
           _('apply changes without prompting for confirmation')),
31dfa7dac4c9 absorb: prompt user to accept absorb changes by default
Mark Thomas <mbthomas@fb.com>
parents: 40188
diff changeset
   990
          ('p', 'print-changes', None,
40210
8f192f2c4a1e absorb: update help text
Mark Thomas <mbthomas@fb.com>
parents: 40190
diff changeset
   991
           _('always print which changesets are modified by which changes')),
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   992
          ('i', 'interactive', None,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   993
           _('interactively select which chunks to apply (EXPERIMENTAL)')),
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   994
          ('e', 'edit-lines', None,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   995
           _('edit what lines belong to which changesets before commit '
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
   996
             '(EXPERIMENTAL)')),
40187
dcda50856843 absorb: use a formatter to generate output
Mark Thomas <mbthomas@fb.com>
parents: 40150
diff changeset
   997
         ] + commands.dryrunopts + commands.templateopts + commands.walkopts,
40293
c303d65d2e34 help: assigning categories to existing commands
rdamazio@google.com
parents: 40210
diff changeset
   998
         _('hg absorb [OPTION] [FILE]...'),
40295
fa88170c10bb help: adding a proper declaration for shortlist/basic commands (API)
Rodrigo Damazio <rdamazio@google.com>
parents: 40293
diff changeset
   999
         helpcategory=command.CATEGORY_COMMITTING,
fa88170c10bb help: adding a proper declaration for shortlist/basic commands (API)
Rodrigo Damazio <rdamazio@google.com>
parents: 40293
diff changeset
  1000
         helpbasic=True)
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1001
def absorbcmd(ui, repo, *pats, **opts):
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1002
    """incorporate corrections into the stack of draft changesets
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1003
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1004
    absorb analyzes each change in your working directory and attempts to
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1005
    amend the changed lines into the changesets in your stack that first
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1006
    introduced those lines.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1007
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1008
    If absorb cannot find an unambiguous changeset to amend for a change,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1009
    that change will be left in the working directory, untouched. They can be
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1010
    observed by :hg:`status` or :hg:`diff` afterwards. In other words,
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1011
    absorb does not write to the working directory.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1012
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1013
    Changesets outside the revset `::. and not public() and not merge()` will
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1014
    not be changed.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1015
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1016
    Changesets that become empty after applying the changes will be deleted.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1017
40210
8f192f2c4a1e absorb: update help text
Mark Thomas <mbthomas@fb.com>
parents: 40190
diff changeset
  1018
    By default, absorb will show what it plans to do and prompt for
8f192f2c4a1e absorb: update help text
Mark Thomas <mbthomas@fb.com>
parents: 40190
diff changeset
  1019
    confirmation.  If you are confident that the changes will be absorbed
8f192f2c4a1e absorb: update help text
Mark Thomas <mbthomas@fb.com>
parents: 40190
diff changeset
  1020
    to the correct place, run :hg:`absorb -a` to apply the changes
8f192f2c4a1e absorb: update help text
Mark Thomas <mbthomas@fb.com>
parents: 40190
diff changeset
  1021
    immediately.
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1022
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1023
    Returns 0 on success, 1 if all chunks were ignored and nothing amended.
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1024
    """
39786
d50125dec2c1 py3: fix kwargs handling in hgext/absorb.py
Pulkit Goyal <pulkit@yandex-team.ru>
parents: 39453
diff changeset
  1025
    opts = pycompat.byteskwargs(opts)
38917
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1026
    state = absorb(ui, repo, pats=pats, opts=opts)
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1027
    if sum(s[0] for s in state.chunkstats.values()) == 0:
5111d11b8719 absorb: import extension from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
  1028
        return 1