Пример #1
0
def unified_diff(lines1, lines2):
    matches = find_matches(lines1, lines2)
    if     len(matches) == 0 or \
           matches[-1][0]+matches[-1][2] != len(lines1) or \
           matches[-1][1]+matches[-1][2] != len(lines2):
        matches.append((len(lines1), len(lines2), 0))

    text = []
    if matches[0][:2] == (0, 0):
        line = line2 = max(matches[0][2] - 3, 0)
        length = min(matches[0][2], 3)
        m = 1
    else:
        line, line2 = -1, 0
        length = 0
        m = 0
    while m < len(matches):
        # capture as much as possible under this header
        m_end = m
        while True:
            line_end, line2_end, length_end = matches[m_end]
            if length_end > 6 or m_end + 1 == len(matches):
                break
            m_end += 1
        length_end = min(length_end, 3)

        # print the diff header for all the hunks we can cover
        lfudge = max(0, line)
        header = "@@ -%d,%d +%d,%d @@\n" % \
                 (lfudge + 1,  line_end - lfudge + length_end,
                  line2 + 1, line2_end - line2 + length_end)
        text.append(header)

        # print out all the covered hunks with context
        for m in xrange(m, m_end+1):
            # fill out the previous context
            for line in xrange(line, line+length):
                text.append(' ' + lines1[line] + "\n")
            line2 += length - 1
            s1, s2, length = matches[m]
            # print the removed and added lines
            for line in xrange(line+1, s1):
                text.append('-' + lines1[line] + "\n")
            for line2 in xrange(line2+1, s2):
                text.append('+' + lines2[line2] + "\n")
            line  += 1
            line2 += 1

        len_full = length
        length = min(3, length)
        # print the trailing context
        for i in xrange(line, line + length):
            text.append(' ' + lines1[i] + "\n")

        # setup stuff for the next iteration
        line  = s1 + len_full - length
        line2 = s2 + len_full - length
        m += 1

    return ''.join(text)
Пример #2
0
def unified_diff(lines1, lines2):
    matches = find_matches(lines1, lines2)
    if     len(matches) == 0 or \
           matches[-1][0]+matches[-1][2] != len(lines1) or \
           matches[-1][1]+matches[-1][2] != len(lines2):
        matches.append((len(lines1), len(lines2), 0))

    text = []
    if matches[0][:2] == (0, 0):
        line = line2 = max(matches[0][2] - 3, 0)
        length = min(matches[0][2], 3)
        m = 1
    else:
        line, line2 = -1, 0
        length = 0
        m = 0
    while m < len(matches):
        # capture as much as possible under this header
        m_end = m
        while True:
            line_end, line2_end, length_end = matches[m_end]
            if length_end > 6 or m_end + 1 == len(matches):
                break
            m_end += 1
        length_end = min(length_end, 3)

        # print the diff header for all the hunks we can cover
        lfudge = max(0, line)
        header = "@@ -%d,%d +%d,%d @@\n" % \
                 (lfudge + 1,  line_end - lfudge + length_end,
                  line2 + 1, line2_end - line2 + length_end)
        text.append(header)

        # print out all the covered hunks with context
        for m in xrange(m, m_end + 1):
            # fill out the previous context
            for line in xrange(line, line + length):
                text.append(' ' + lines1[line] + "\n")
            line2 += length - 1
            s1, s2, length = matches[m]
            # print the removed and added lines
            for line in xrange(line + 1, s1):
                text.append('-' + lines1[line] + "\n")
            for line2 in xrange(line2 + 1, s2):
                text.append('+' + lines2[line2] + "\n")
            line += 1
            line2 += 1

        len_full = length
        length = min(3, length)
        # print the trailing context
        for i in xrange(line, line + length):
            text.append(' ' + lines1[i] + "\n")

        # setup stuff for the next iteration
        line = s1 + len_full - length
        line2 = s2 + len_full - length
        m += 1

    return ''.join(text)
Пример #3
0
def _find_conflict(local, local_line_points, local_points, remote,
                   remote_line_points, remote_points):
    assert len(local_line_points) == len(local) + 1
    assert len(remote_line_points) == len(remote) + 1

    lpdict = Set(local_points)
    for point in local_line_points:
        assert point in lpdict

    rpdict = Set(remote_points)
    for point in remote_line_points:
        assert point in rpdict

    result = []
    result_line_points = []
    lastl, lastr = 0, 0

    selector = SelectLinePoint()
    selector.push(local_points)
    selector.push(remote_points)

    for (lpos, rpos, matchlen) in find_matches(
            local, remote) + [(len(local), len(remote), 0)]:
        rapplied = _is_applied(remote_line_points[lastr:rpos + 1], lpdict)
        lapplied = _is_applied(local_line_points[lastl:lpos + 1], rpdict)
        if rapplied and not lapplied:
            result.extend(local[lastl:lpos + matchlen])
            result_line_points.extend(local_line_points[lastl:lpos + 1])
        elif lapplied and not rapplied:
            result.extend(remote[lastr:rpos + matchlen])
            result_line_points.extend(remote_line_points[lastr:rpos + 1])
        elif (lastl, lastr) == (len(local), len(remote)):
            result_line_points.append(
                selector.select(local_line_points[-1], remote_line_points[-1]))
        elif (lpos, rpos) == (0, 0):
            result.extend(local[:matchlen])
            result_line_points.append(
                selector.select(local_line_points[0], remote_line_points[0]))
        else:
            result.append((local[lastl:lpos], remote[lastr:rpos]))
            result.extend(local[lpos:lpos + matchlen])
            result_line_points.append((local_line_points[lastl:lpos + 1],
                                       remote_line_points[lastr:rpos + 1]))
            result_line_points.append(None)
        for i in xrange(1, matchlen):
            result_line_points.append(
                selector.select(local_line_points[lpos + i],
                                remote_line_points[rpos + i]))
        lastl, lastr = lpos + matchlen, rpos + matchlen

    result_points = selector.dump()
    return (result, result_line_points, result_points)
Пример #4
0
def find_annotation(precursors, resolution):
    result = [None] * len(resolution)

    selector = SelectLinePoint()

    for i in xrange(len(precursors)):
        match = find_matches(precursors[i][0], resolution)

        pre = precursors[i][0]
        pre_line_points = precursors[i][1]
        selector.push(precursors[i][2])

        for (matchold, matchnew, matchlen) in match:
            for j in xrange(matchlen):
                result[matchnew + j] = selector.select(result[matchnew + j], pre_line_points[matchold + j])

    return result
Пример #5
0
def standard_diff(lines1, lines2):
    matches = find_matches(lines1, lines2)
    if len(matches) == 0 or matches[0][0] != 0 or matches[0][1] != 0:
        matches.insert(0, (0, 0, 0))
    if     matches[-1][0]+matches[-1][2] != len(lines1) or \
           matches[-1][1]+matches[-1][2] != len(lines2):
        matches.append((len(lines1), len(lines2), 0))

    text = []
    i = 0
    j = 0
    for i2, j2, l in matches:
        if i2 == i and j2 == j:
            i += l
            j += l
            continue
        if i2 == i:
            at = str(i)
        elif i2 == i + 1:
            at = str(i2)
        else:
            at = "%d,%d" % (i + 1, i2)
        if j2 == j:
            bt = str(j)
        elif j2 == j + 1:
            bt = str(j2)
        else:
            bt = "%d,%d" % (j + 1, j2)
        if i2 > i:
            if j2 > j:
                text.extend([at, 'c', bt, "\n"])
            else:
                text.extend([at, 'd', bt, "\n"])
        else:
            text.extend([at, 'a', bt, "\n"])
        for i in xrange(i, i2):
            text.extend(["< ", lines1[i], "\n"])
        if i2 > i and j2 > j:
            text.append("---\n")
        for j in xrange(j, j2):
            text.extend(["> ", lines2[j], "\n"])
        i = i2 + l
        j = j2 + l

    return ''.join(text)
Пример #6
0
def standard_diff(lines1, lines2):
    matches = find_matches(lines1, lines2)
    if len(matches) == 0 or matches[0][0] != 0 or matches[0][1] != 0:
        matches.insert(0, (0, 0, 0))
    if     matches[-1][0]+matches[-1][2] != len(lines1) or \
           matches[-1][1]+matches[-1][2] != len(lines2):
        matches.append((len(lines1), len(lines2), 0))

    text = []
    i = 0
    j = 0
    for i2, j2, l in matches:
        if i2 == i and j2 == j:
            i += l
            j += l
            continue
        if i2 == i:
            at = str(i)
        elif i2 == i + 1:
            at = str(i2)
        else:
            at = "%d,%d" % (i+1, i2)
        if j2 == j:
            bt = str(j)
        elif j2 == j + 1:
            bt = str(j2)
        else:
            bt = "%d,%d" % (j+1, j2)
        if i2 > i:
            if j2 > j:
                text.extend([at, 'c', bt, "\n"])
            else:
                text.extend([at, 'd', bt, "\n"])
        else:
            text.extend([at, 'a', bt, "\n"])
        for i in xrange(i, i2):
            text.extend(["< ", lines1[i], "\n"])
        if i2 > i and j2 > j:
            text.append("---\n")
        for j in xrange(j, j2):
            text.extend(["> ", lines2[j], "\n"])
        i = i2 + l
        j = j2 + l

    return ''.join(text)
Пример #7
0
def _find_conflict(local, local_line_points, local_points, remote, remote_line_points, remote_points):
    assert len(local_line_points) == len(local) + 1
    assert len(remote_line_points) == len(remote) + 1

    lpdict = Set(local_points)
    for point in local_line_points:
        assert point in lpdict

    rpdict = Set(remote_points)
    for point in remote_line_points:
        assert point in rpdict

    result = []
    result_line_points = []
    lastl, lastr = 0, 0

    selector = SelectLinePoint()
    selector.push(local_points)
    selector.push(remote_points)

    for (lpos, rpos, matchlen) in find_matches(local, remote) + [(len(local), len(remote), 0)]:
        rapplied = _is_applied(remote_line_points[lastr:rpos + 1], lpdict)
        lapplied = _is_applied(local_line_points[lastl:lpos + 1], rpdict)
        if rapplied and not lapplied:
            result.extend(local[lastl:lpos + matchlen])
            result_line_points.extend(local_line_points[lastl:lpos + 1])
        elif lapplied and not rapplied:
            result.extend(remote[lastr:rpos + matchlen])
            result_line_points.extend(remote_line_points[lastr:rpos + 1])
        elif (lastl, lastr) == (len(local), len(remote)):
            result_line_points.append(selector.select(local_line_points[-1], remote_line_points[-1]))
        elif (lpos, rpos) == (0, 0):
            result.extend(local[:matchlen])
            result_line_points.append(selector.select(local_line_points[0], remote_line_points[0]))
        else:
            result.append((local[lastl:lpos], remote[lastr:rpos]))
            result.extend(local[lpos:lpos + matchlen])
            result_line_points.append((local_line_points[lastl:lpos + 1], remote_line_points[lastr:rpos + 1]))
            result_line_points.append(None)
        for i in xrange(1, matchlen):
            result_line_points.append(selector.select(local_line_points[lpos + i], remote_line_points[rpos + i]))
        lastl, lastr = lpos + matchlen, rpos + matchlen

    result_points = selector.dump()
    return (result, result_line_points, result_points)
Пример #8
0
def find_annotation(precursors, resolution):
    result = [None] * len(resolution)

    selector = SelectLinePoint()

    for i in xrange(len(precursors)):
        match = find_matches(precursors[i][0], resolution)

        pre = precursors[i][0]
        pre_line_points = precursors[i][1]
        selector.push(precursors[i][2])

        for (matchold, matchnew, matchlen) in match:
            for j in xrange(matchlen):
                result[matchnew + j] = selector.select(
                    result[matchnew + j], pre_line_points[matchold + j])

    return result
Пример #9
0
def find_resolution(precursors, resolution):
    result = [None] * (len(resolution) + 1)
    ms = [[] for i in xrange(len(precursors))]

    selector = SelectLinePoint()

    ms = []
    for i in xrange(len(precursors)):
        ms.append(find_matches(precursors[i][0], resolution))

        pre = precursors[i][0]
        pre_line_points = precursors[i][1]
        selector.push(precursors[i][2])

        for (matchold, matchnew, matchlen) in ms[i]:
            begina, beginb, mlen = matchold + 1, matchnew + 1, matchlen - 1
            if (matchold, matchnew) == (0, 0):
                (begina, beginb, mlen) = (0, 0, mlen + 1)
            if (matchold + matchlen, matchnew + matchlen) == (len(pre),
                                                              len(resolution)):
                mlen += 1
            for j in xrange(mlen):
                result[beginb + j] = selector.select(
                    result[beginb + j], pre_line_points[begina + j])

    # mark each line as to whether we need a newline for it
    hits = [False] * len(resolution)
    for i in xrange(len(ms)):
        for (matchold, matchnew, matchlen) in ms[i]:
            hits[matchnew:matchnew + matchlen] = [True] * matchlen

    # this may seem weird, but there's this really annoying ambiguous clean
    # merge case which sometimes turns up when the match algorithm finds an
    # "incorrect" match. the same conflicts which the person has just resolved
    # will happen again on merges through other repositories. this code
    # puts in new line points to prevent that from happening.
    if len(precursors) > 1:
        breaks = []
        for i in xrange(len(precursors)):
            l, lp, p = precursors[i]
            lastl, lastr = 0, 0
            ms[i].append((len(l), len(resolution), 0))
            for (lpos, rpos, mlen) in ms[i]:
                # if it doesn't declare itself the winner, it will cause
                # conflicts later
                rapplied = _is_applied(result[lastr:rpos + 1], p)
                if     (lpos, rpos) == (0, 0) or \
                       (lastl, lastr) == (len(l), len(resolution)):
                    pass
                elif rapplied:
                    breaks.append((lastr, rpos - lastr))

                    # fix hits so newlines are created
                    hits[lastr:rpos] = [False] * (rpos - lastr)

                lastl, lastr = lpos + mlen, rpos + mlen
        breaks.sort()

        # make the matches not overlap the breaks
        for i in xrange(len(ms)):
            newms = []
            cur_match = 0
            try:
                for (bpos, blen) in breaks:
                    lpos, rpos, mlen = ms[i][cur_match]

                    # no overlap, nothing to do
                    while rpos + mlen <= bpos:
                        newms.append(ms[i][cur_match])
                        cur_match += 1
                        if cur_match >= len(ms[i]):
                            raise NoMoreMatchesException
                        lpos, rpos, mlen = ms[i][cur_match]

                    # some overlap at the end of the match
                    if rpos < bpos:
                        newms.append((lpos, rpos, bpos - rpos))

                    # full overlap
                    while rpos + mlen <= bpos + blen:
                        cur_match += 1
                        if cur_match >= len(ms[i]):
                            raise NoMoreMatchesException
                        lpos, rpos, mlen = ms[i][cur_match]

                    # partial overlap, fix it up for the next iteration
                    if rpos < bpos + blen:
                        adj = bpos + blen - rpos
                        m = (lpos + adj, bpos + blen, mlen - adj)
                        ms[i][cur_match] = m
            except NoMoreMatchesException:
                pass

            # add remaining matches at the end, dropping the dummy
            newms.extend(ms[i][cur_match:-1])

            ms[i] = newms

        # reset results
        for (bpos, blen) in breaks:
            result[bpos:bpos + blen + 1] = [None] * (blen + 1)

    # figure out what's not covered by matches
    newlines = []
    pos = 0
    while pos < len(hits):
        if hits[pos]:
            pos += 1
        else:
            n = []
            j = pos
            while j < len(hits) and not hits[j]:
                n.append(resolution[j])
                j += 1
            newlines.append((pos, n))
            pos = j

    return (result, ms, newlines)
Пример #10
0
def find_resolution(precursors, resolution):
    result = [None] * (len(resolution) + 1)
    ms = [[] for i in xrange(len(precursors))]

    selector = SelectLinePoint()

    ms = []
    for i in xrange(len(precursors)):
        ms.append(find_matches(precursors[i][0], resolution))

        pre = precursors[i][0]
        pre_line_points = precursors[i][1]
        selector.push(precursors[i][2])

        for (matchold, matchnew, matchlen) in ms[i]:
            begina, beginb, mlen = matchold + 1, matchnew + 1, matchlen - 1
            if (matchold, matchnew) == (0, 0):
                (begina, beginb, mlen) = (0, 0, mlen + 1)
            if (matchold + matchlen, matchnew + matchlen) == (len(pre), len(resolution)):
                mlen += 1
            for j in xrange(mlen):
                result[beginb + j] = selector.select(result[beginb + j], pre_line_points[begina + j])

    # mark each line as to whether we need a newline for it
    hits = [False] * len(resolution)
    for i in xrange(len(ms)):
        for (matchold, matchnew, matchlen) in ms[i]:
            hits[matchnew:matchnew + matchlen] = [True] * matchlen

    # this may seem weird, but there's this really annoying ambiguous clean
    # merge case which sometimes turns up when the match algorithm finds an
    # "incorrect" match. the same conflicts which the person has just resolved
    # will happen again on merges through other repositories. this code
    # puts in new line points to prevent that from happening.
    if len(precursors) > 1:
        breaks = []
        for i in xrange(len(precursors)):
            l, lp, p = precursors[i]
            lastl, lastr = 0, 0
            ms[i].append((len(l), len(resolution), 0))
            for (lpos, rpos, mlen) in ms[i]:
                # if it doesn't declare itself the winner, it will cause
                # conflicts later
                rapplied = _is_applied(result[lastr:rpos + 1], p)
                if     (lpos, rpos) == (0, 0) or \
                       (lastl, lastr) == (len(l), len(resolution)):
                    pass
                elif rapplied:
                    breaks.append((lastr, rpos - lastr))

                    # fix hits so newlines are created
                    hits[lastr:rpos] = [False] * (rpos - lastr)

                lastl, lastr = lpos + mlen, rpos + mlen
        breaks.sort()

        # make the matches not overlap the breaks
        for i in xrange(len(ms)):
            newms = []
            cur_match = 0
            try:
                for (bpos, blen) in breaks:
                    lpos, rpos, mlen = ms[i][cur_match]

                    # no overlap, nothing to do
                    while rpos + mlen <= bpos:
                        newms.append(ms[i][cur_match])
                        cur_match += 1
                        if cur_match >= len(ms[i]):
                            raise NoMoreMatchesException
                        lpos, rpos, mlen = ms[i][cur_match]

                    # some overlap at the end of the match
                    if rpos < bpos:
                        newms.append((lpos, rpos, bpos - rpos))

                    # full overlap
                    while rpos + mlen <= bpos + blen:
                        cur_match += 1
                        if cur_match >= len(ms[i]):
                            raise NoMoreMatchesException
                        lpos, rpos, mlen = ms[i][cur_match]

                    # partial overlap, fix it up for the next iteration
                    if rpos < bpos + blen:
                        adj = bpos + blen - rpos
                        m = (lpos + adj, bpos + blen, mlen - adj)
                        ms[i][cur_match] = m
            except NoMoreMatchesException:
                pass

            # add remaining matches at the end, dropping the dummy
            newms.extend(ms[i][cur_match:-1])

            ms[i] = newms

        # reset results
        for (bpos, blen) in breaks:
            result[bpos:bpos + blen + 1] = [None] * (blen + 1)

    # figure out what's not covered by matches
    newlines = []
    pos = 0
    while pos < len(hits):
        if hits[pos]:
            pos += 1
        else:
            n = []
            j = pos
            while j < len(hits) and not hits[j]:
                n.append(resolution[j])
                j += 1
            newlines.append((pos, n))
            pos = j

    return (result, ms, newlines)