mirror of
https://github.com/facebook/sapling.git
synced 2024-12-29 08:02:24 +03:00
db7377ae0c
Reviewed By: xavierd Differential Revision: D20928614 fbshipit-source-id: beafe9a1aa260e1ac398056e93795c5231139a06
203 lines
6.2 KiB
Python
203 lines
6.2 KiB
Python
from __future__ import absolute_import
|
|
|
|
import itertools
|
|
|
|
from edenscm.hgext import absorb
|
|
from hghave import require
|
|
|
|
|
|
class simplefctx(object):
|
|
def __init__(self, content):
|
|
self.content = content.encode("utf-8")
|
|
|
|
def data(self):
|
|
assert isinstance(self.content, bytes)
|
|
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 list(map(insertreturns, x))
|
|
|
|
|
|
def removereturns(x):
|
|
# the revert of "insertreturns"
|
|
if isinstance(x, bytes):
|
|
x = x.decode("utf-8")
|
|
if isinstance(x, str):
|
|
return x.replace("\n", "")
|
|
else:
|
|
return list(map(removereturns, x))
|
|
|
|
|
|
def assertlistequal(lhs, rhs, decorator=lambda x: x):
|
|
if lhs != rhs and decorator(lhs) != decorator(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(list(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)
|