mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 08:47:12 +03:00
613561b5e7
Summary: Update hg absorb to use the templater and display the first line of the description of the affected commits. Also change the default behaviour to display the changes and prompt the user to confirm that absorb is going to do what they want. Use the new `-a` option to get the old behaviour. Reviewed By: quark-zju Differential Revision: D10366510 fbshipit-source-id: 23df2e5ab2d21a0805a16e7118686a29634d2918
199 lines
6.0 KiB
Python
199 lines
6.0 KiB
Python
from __future__ import absolute_import
|
|
|
|
import itertools
|
|
|
|
from hgext import absorb
|
|
|
|
|
|
class simplefctx(object):
|
|
def __init__(self, content):
|
|
self.content = content
|
|
|
|
def data(self):
|
|
return self.content
|
|
|
|
|
|
def insertreturns(x):
|
|
# insert "\n"s after each single char
|
|
if isinstance(x, str):
|
|
return "".join(ch + "\n" for ch in x)
|
|
else:
|
|
return map(insertreturns, x)
|
|
|
|
|
|
def removereturns(x):
|
|
# the revert of "insertreturns"
|
|
if isinstance(x, str):
|
|
return x.replace("\n", "")
|
|
else:
|
|
return map(removereturns, x)
|
|
|
|
|
|
def assertlistequal(lhs, rhs, decorator=lambda x: x):
|
|
if lhs != rhs:
|
|
raise RuntimeError(
|
|
"mismatch:\n actual: %r\n expected: %r"
|
|
% tuple(map(decorator, [lhs, rhs]))
|
|
)
|
|
|
|
|
|
def testfilefixup(oldcontents, workingcopy, expectedcontents, fixups=None):
|
|
"""([str], str, [str], [(rev, a1, a2, b1, b2)]?) -> None
|
|
|
|
workingcopy is a string, of which every character denotes a single line.
|
|
|
|
oldcontents, expectedcontents are lists of strings, every character of
|
|
every string denots a single line.
|
|
|
|
if fixups is not None, it's the expected fixups list and will be checked.
|
|
"""
|
|
expectedcontents = insertreturns(expectedcontents)
|
|
oldcontents = insertreturns(oldcontents)
|
|
workingcopy = insertreturns(workingcopy)
|
|
state = absorb.filefixupstate(map(simplefctx, oldcontents), "path")
|
|
state.diffwith(simplefctx(workingcopy))
|
|
if fixups is not None:
|
|
assertlistequal(state.fixups, fixups)
|
|
state.apply()
|
|
assertlistequal(state.finalcontents, expectedcontents, removereturns)
|
|
|
|
|
|
def buildcontents(linesrevs):
|
|
# linesrevs: [(linecontent : str, revs : [int])]
|
|
revs = set(itertools.chain(*[revs for line, revs in linesrevs]))
|
|
return [""] + ["".join([l for l, rs in linesrevs if r in rs]) for r in sorted(revs)]
|
|
|
|
|
|
# input case 0: one single commit
|
|
case0 = ["", "11"]
|
|
|
|
# replace a single chunk
|
|
testfilefixup(case0, "", ["", ""])
|
|
testfilefixup(case0, "2", ["", "2"])
|
|
testfilefixup(case0, "22", ["", "22"])
|
|
testfilefixup(case0, "222", ["", "222"])
|
|
|
|
# input case 1: 3 lines, each commit adds one line
|
|
case1 = buildcontents([("1", [1, 2, 3]), ("2", [2, 3]), ("3", [3])])
|
|
|
|
# 1:1 line mapping
|
|
testfilefixup(case1, "123", case1)
|
|
testfilefixup(case1, "12c", ["", "1", "12", "12c"])
|
|
testfilefixup(case1, "1b3", ["", "1", "1b", "1b3"])
|
|
testfilefixup(case1, "1bc", ["", "1", "1b", "1bc"])
|
|
testfilefixup(case1, "a23", ["", "a", "a2", "a23"])
|
|
testfilefixup(case1, "a2c", ["", "a", "a2", "a2c"])
|
|
testfilefixup(case1, "ab3", ["", "a", "ab", "ab3"])
|
|
testfilefixup(case1, "abc", ["", "a", "ab", "abc"])
|
|
|
|
# non 1:1 edits
|
|
testfilefixup(case1, "abcd", case1)
|
|
testfilefixup(case1, "ab", case1)
|
|
|
|
# deletion
|
|
testfilefixup(case1, "", ["", "", "", ""])
|
|
testfilefixup(case1, "1", ["", "1", "1", "1"])
|
|
testfilefixup(case1, "2", ["", "", "2", "2"])
|
|
testfilefixup(case1, "3", ["", "", "", "3"])
|
|
testfilefixup(case1, "13", ["", "1", "1", "13"])
|
|
|
|
# replaces
|
|
testfilefixup(case1, "1bb3", ["", "1", "1bb", "1bb3"])
|
|
|
|
# (confusing) replaces
|
|
testfilefixup(case1, "1bbb", case1)
|
|
testfilefixup(case1, "bbbb", case1)
|
|
testfilefixup(case1, "bbb3", case1)
|
|
testfilefixup(case1, "1b", case1)
|
|
testfilefixup(case1, "bb", case1)
|
|
testfilefixup(case1, "b3", case1)
|
|
|
|
# insertions at the beginning and the end
|
|
testfilefixup(case1, "123c", ["", "1", "12", "123c"])
|
|
testfilefixup(case1, "a123", ["", "a1", "a12", "a123"])
|
|
|
|
# (confusing) insertions
|
|
testfilefixup(case1, "1a23", case1)
|
|
testfilefixup(case1, "12b3", case1)
|
|
|
|
# input case 2: delete in the middle
|
|
case2 = buildcontents([("11", [1, 2]), ("22", [1]), ("33", [1, 2])])
|
|
|
|
# deletion (optimize code should make it 2 chunks)
|
|
testfilefixup(case2, "", ["", "22", ""], fixups=[(4, 0, 2, 0, 0), (4, 2, 4, 0, 0)])
|
|
|
|
# 1:1 line mapping
|
|
testfilefixup(case2, "aaaa", ["", "aa22aa", "aaaa"])
|
|
|
|
# non 1:1 edits
|
|
# note: unlike case0, the chunk is not "continuous" and no edit allowed
|
|
testfilefixup(case2, "aaa", case2)
|
|
|
|
# input case 3: rev 3 reverts rev 2
|
|
case3 = buildcontents([("1", [1, 2, 3]), ("2", [2]), ("3", [1, 2, 3])])
|
|
|
|
# 1:1 line mapping
|
|
testfilefixup(case3, "13", case3)
|
|
testfilefixup(case3, "1b", ["", "1b", "12b", "1b"])
|
|
testfilefixup(case3, "a3", ["", "a3", "a23", "a3"])
|
|
testfilefixup(case3, "ab", ["", "ab", "a2b", "ab"])
|
|
|
|
# non 1:1 edits
|
|
testfilefixup(case3, "a", case3)
|
|
testfilefixup(case3, "abc", case3)
|
|
|
|
# deletion
|
|
testfilefixup(case3, "", ["", "", "2", ""])
|
|
|
|
# insertion
|
|
testfilefixup(case3, "a13c", ["", "a13c", "a123c", "a13c"])
|
|
|
|
# input case 4: a slightly complex case
|
|
case4 = buildcontents(
|
|
[
|
|
("1", [1, 2, 3]),
|
|
("2", [2, 3]),
|
|
("3", [1, 2]),
|
|
("4", [1, 3]),
|
|
("5", [3]),
|
|
("6", [2, 3]),
|
|
("7", [2]),
|
|
("8", [2, 3]),
|
|
("9", [3]),
|
|
]
|
|
)
|
|
|
|
testfilefixup(case4, "1245689", case4)
|
|
testfilefixup(case4, "1a2456bbb", case4)
|
|
testfilefixup(case4, "1abc5689", case4)
|
|
testfilefixup(case4, "1ab5689", ["", "134", "1a3678", "1ab5689"])
|
|
testfilefixup(case4, "aa2bcd8ee", ["", "aa34", "aa23d78", "aa2bcd8ee"])
|
|
testfilefixup(case4, "aa2bcdd8ee", ["", "aa34", "aa23678", "aa24568ee"])
|
|
testfilefixup(case4, "aaaaaa", case4)
|
|
testfilefixup(case4, "aa258b", ["", "aa34", "aa2378", "aa258b"])
|
|
testfilefixup(case4, "25bb", ["", "34", "23678", "25689"])
|
|
testfilefixup(case4, "27", ["", "34", "23678", "245689"])
|
|
testfilefixup(case4, "28", ["", "34", "2378", "28"])
|
|
testfilefixup(case4, "", ["", "34", "37", ""])
|
|
|
|
# input case 5: replace a small chunk which is near a deleted line
|
|
case5 = buildcontents([("12", [1, 2]), ("3", [1]), ("4", [1, 2])])
|
|
|
|
testfilefixup(case5, "1cd4", ["", "1cd34", "1cd4"])
|
|
|
|
# input case 6: base "changeset" is immutable
|
|
case6 = ["1357", "0125678"]
|
|
|
|
testfilefixup(case6, "0125678", case6)
|
|
testfilefixup(case6, "0a25678", case6)
|
|
testfilefixup(case6, "0a256b8", case6)
|
|
testfilefixup(case6, "abcdefg", ["1357", "a1c5e7g"])
|
|
testfilefixup(case6, "abcdef", case6)
|
|
testfilefixup(case6, "", ["1357", "157"])
|
|
testfilefixup(case6, "0123456789", ["1357", "0123456789"])
|
|
|
|
# input case 7: change an empty file
|
|
case7 = [""]
|
|
|
|
testfilefixup(case7, "1", case7)
|