Show More
@@ -22,6 +22,40 b' propertycache = util.propertycache' | |||
|
22 | 22 | # dirty in the working copy. |
|
23 | 23 | _newnode = '!' * 21 |
|
24 | 24 | |
|
25 | def _adjustlinkrev(repo, path, filelog, fnode, srcrev): | |
|
26 | """return the first ancestor of <srcrev> introducting <fnode> | |
|
27 | ||
|
28 | If the linkrev of the file revision does not point to an ancestor of | |
|
29 | srcrev, we'll walk down the ancestors until we find one introducing this | |
|
30 | file revision. | |
|
31 | ||
|
32 | :repo: a localrepository object (used to access changelog and manifest) | |
|
33 | :path: the file path | |
|
34 | :fnode: the nodeid of the file revision | |
|
35 | :filelog: the filelog of this path | |
|
36 | :srcrev: the changeset revision we search ancestors from | |
|
37 | """ | |
|
38 | cl = repo.unfiltered().changelog | |
|
39 | ma = repo.manifest | |
|
40 | # fetch the linkrev | |
|
41 | fr = filelog.rev(fnode) | |
|
42 | lkr = filelog.linkrev(fr) | |
|
43 | # check if this linkrev is an ancestor of srcrev | |
|
44 | anc = cl.ancestors([srcrev], lkr) | |
|
45 | if lkr not in anc: | |
|
46 | for a in anc: | |
|
47 | ac = cl.read(a) # get changeset data (we avoid object creation). | |
|
48 | if path in ac[3]: # checking the 'files' field. | |
|
49 | # The file has been touched, check if the content is similar | |
|
50 | # to the one we search for. | |
|
51 | if fnode == ma.readdelta(ac[0]).get(path): | |
|
52 | return a | |
|
53 | # In theory, we should never get out of that loop without a result. But | |
|
54 | # if manifest uses a buggy file revision (not children of the one it | |
|
55 | # replaces) we could. Such a buggy situation will likely result is crash | |
|
56 | # somewhere else at to some point. | |
|
57 | return lkr | |
|
58 | ||
|
25 | 59 | class basectx(object): |
|
26 | 60 | """A basectx object represents the common logic for its children: |
|
27 | 61 | changectx: read-only context that is already present in the repo, |
@@ -739,7 +773,7 b' class basefilectx(object):' | |||
|
739 | 773 | parents = self._filelog.parents(self._filenode) |
|
740 | 774 | pl = [(_path, node, fl) for node in parents if node != nullid] |
|
741 | 775 | |
|
742 |
r = |
|
|
776 | r = fl.renamed(self._filenode) | |
|
743 | 777 | if r: |
|
744 | 778 | # - In the simple rename case, both parent are nullid, pl is empty. |
|
745 | 779 | # - In case of merge, only one of the parent is null id and should |
@@ -751,7 +785,19 b' class basefilectx(object):' | |||
|
751 | 785 | # first nullid parent with rename information. |
|
752 | 786 | pl.insert(0, (r[0], r[1], self._repo.file(r[0]))) |
|
753 | 787 | |
|
754 | return [filectx(self._repo, p, fileid=n, filelog=l) for p, n, l in pl] | |
|
788 | ret = [] | |
|
789 | for path, fnode, l in pl: | |
|
790 | if '_changeid' in vars(self) or '_changectx' in vars(self): | |
|
791 | # If self is associated with a changeset (probably explicitly | |
|
792 | # fed), ensure the created filectx is associated with a | |
|
793 | # changeset that is an ancestor of self.changectx. | |
|
794 | rev = _adjustlinkrev(self._repo, path, l, fnode, self.rev()) | |
|
795 | fctx = filectx(self._repo, path, fileid=fnode, filelog=l, | |
|
796 | changeid=rev) | |
|
797 | else: | |
|
798 | fctx = filectx(self._repo, path, fileid=fnode, filelog=l) | |
|
799 | ret.append(fctx) | |
|
800 | return ret | |
|
755 | 801 | |
|
756 | 802 | def p1(self): |
|
757 | 803 | return self.parents()[0] |
@@ -451,3 +451,63 b' Annotate with --ignore-blank-lines (simi' | |||
|
451 | 451 | 1: b b |
|
452 | 452 | |
|
453 | 453 | $ cd .. |
|
454 | ||
|
455 | Annotate with linkrev pointing to another branch | |
|
456 | ------------------------------------------------ | |
|
457 | ||
|
458 | create history with a filerev whose linkrev points to another branch | |
|
459 | ||
|
460 | $ hg init branchedlinkrev | |
|
461 | $ cd branchedlinkrev | |
|
462 | $ echo A > a | |
|
463 | $ hg commit -Am 'contentA' | |
|
464 | adding a | |
|
465 | $ echo B >> a | |
|
466 | $ hg commit -m 'contentB' | |
|
467 | $ hg up --rev 'desc(contentA)' | |
|
468 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
469 | $ echo unrelated > unrelated | |
|
470 | $ hg commit -Am 'unrelated' | |
|
471 | adding unrelated | |
|
472 | created new head | |
|
473 | $ hg graft -r 'desc(contentB)' | |
|
474 | grafting 1:fd27c222e3e6 "contentB" | |
|
475 | $ echo C >> a | |
|
476 | $ hg commit -m 'contentC' | |
|
477 | $ hg log -G | |
|
478 | @ changeset: 4:072f1e8df249 | |
|
479 | | tag: tip | |
|
480 | | user: test | |
|
481 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
482 | | summary: contentC | |
|
483 | | | |
|
484 | o changeset: 3:ff38df03cc4b | |
|
485 | | user: test | |
|
486 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
487 | | summary: contentB | |
|
488 | | | |
|
489 | o changeset: 2:62aaf3f6fc06 | |
|
490 | | parent: 0:f0932f74827e | |
|
491 | | user: test | |
|
492 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
493 | | summary: unrelated | |
|
494 | | | |
|
495 | | o changeset: 1:fd27c222e3e6 | |
|
496 | |/ user: test | |
|
497 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
498 | | summary: contentB | |
|
499 | | | |
|
500 | o changeset: 0:f0932f74827e | |
|
501 | user: test | |
|
502 | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
503 | summary: contentA | |
|
504 | ||
|
505 | ||
|
506 | Annotate should list ancestor of starting revision only | |
|
507 | ||
|
508 | $ hg annotate a | |
|
509 | 0: A | |
|
510 | 3: B | |
|
511 | 4: C | |
|
512 | ||
|
513 | $ cd .. |
@@ -1564,3 +1564,96 b' hg log -f dir across branches' | |||
|
1564 | 1564 | o a |
|
1565 | 1565 | |
|
1566 | 1566 | $ cd .. |
|
1567 | ||
|
1568 | hg log -f with linkrev pointing to another branch | |
|
1569 | ------------------------------------------------- | |
|
1570 | ||
|
1571 | create history with a filerev whose linkrev points to another branch | |
|
1572 | ||
|
1573 | $ hg init branchedlinkrev | |
|
1574 | $ cd branchedlinkrev | |
|
1575 | $ echo 1 > a | |
|
1576 | $ hg commit -Am 'content1' | |
|
1577 | adding a | |
|
1578 | $ echo 2 > a | |
|
1579 | $ hg commit -m 'content2' | |
|
1580 | $ hg up --rev 'desc(content1)' | |
|
1581 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
1582 | $ echo unrelated > unrelated | |
|
1583 | $ hg commit -Am 'unrelated' | |
|
1584 | adding unrelated | |
|
1585 | created new head | |
|
1586 | $ hg graft -r 'desc(content2)' | |
|
1587 | grafting 1:2294ae80ad84 "content2" | |
|
1588 | $ echo 3 > a | |
|
1589 | $ hg commit -m 'content3' | |
|
1590 | $ hg log -G | |
|
1591 | @ changeset: 4:50b9b36e9c5d | |
|
1592 | | tag: tip | |
|
1593 | | user: test | |
|
1594 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
1595 | | summary: content3 | |
|
1596 | | | |
|
1597 | o changeset: 3:15b2327059e5 | |
|
1598 | | user: test | |
|
1599 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
1600 | | summary: content2 | |
|
1601 | | | |
|
1602 | o changeset: 2:2029acd1168c | |
|
1603 | | parent: 0:ae0a3c9f9e95 | |
|
1604 | | user: test | |
|
1605 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
1606 | | summary: unrelated | |
|
1607 | | | |
|
1608 | | o changeset: 1:2294ae80ad84 | |
|
1609 | |/ user: test | |
|
1610 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
1611 | | summary: content2 | |
|
1612 | | | |
|
1613 | o changeset: 0:ae0a3c9f9e95 | |
|
1614 | user: test | |
|
1615 | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
1616 | summary: content1 | |
|
1617 | ||
|
1618 | ||
|
1619 | log -f on the file should list the graft result. | |
|
1620 | ||
|
1621 | $ hg log -Gf a | |
|
1622 | @ changeset: 4:50b9b36e9c5d | |
|
1623 | | tag: tip | |
|
1624 | | user: test | |
|
1625 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
1626 | | summary: content3 | |
|
1627 | | | |
|
1628 | o changeset: 3:15b2327059e5 | |
|
1629 | | user: test | |
|
1630 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
1631 | | summary: content2 | |
|
1632 | | | |
|
1633 | o changeset: 0:ae0a3c9f9e95 | |
|
1634 | user: test | |
|
1635 | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
1636 | summary: content1 | |
|
1637 | ||
|
1638 | ||
|
1639 | plain log lists the original version | |
|
1640 | (XXX we should probably list both) | |
|
1641 | ||
|
1642 | $ hg log -G a | |
|
1643 | @ changeset: 4:50b9b36e9c5d | |
|
1644 | | tag: tip | |
|
1645 | | user: test | |
|
1646 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
1647 | | summary: content3 | |
|
1648 | | | |
|
1649 | | o changeset: 1:2294ae80ad84 | |
|
1650 | |/ user: test | |
|
1651 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
1652 | | summary: content2 | |
|
1653 | | | |
|
1654 | o changeset: 0:ae0a3c9f9e95 | |
|
1655 | user: test | |
|
1656 | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
1657 | summary: content1 | |
|
1658 | ||
|
1659 | $ cd .. |
@@ -1605,3 +1605,65 b" test for case where we didn't look suffi" | |||
|
1605 | 1605 | - |
|
1606 | 1606 | +f |
|
1607 | 1607 | $ cd .. |
|
1608 | ||
|
1609 | Additional tricky linkrev case | |
|
1610 | ------------------------------ | |
|
1611 | ||
|
1612 | If the first file revision after the diff base has a linkrev pointing to a | |
|
1613 | changeset on another branch with a revision lower that the diff base, we can | |
|
1614 | jump past the copy detection limit and fail to detect the rename. | |
|
1615 | ||
|
1616 | $ hg init diffstoplinkrev | |
|
1617 | $ cd diffstoplinkrev | |
|
1618 | ||
|
1619 | $ touch f | |
|
1620 | $ hg ci -Aqm 'empty f' | |
|
1621 | ||
|
1622 | Make a simple change | |
|
1623 | ||
|
1624 | $ echo change > f | |
|
1625 | $ hg ci -m 'change f' | |
|
1626 | ||
|
1627 | Make a second branch, we use a named branch to create a simple commit | |
|
1628 | that does not touch f. | |
|
1629 | ||
|
1630 | $ hg up -qr 'desc(empty)' | |
|
1631 | $ hg branch -q dev | |
|
1632 | $ hg ci -Aqm dev | |
|
1633 | ||
|
1634 | Graft the initial change, as f was untouched, we reuse the same entry and the | |
|
1635 | linkrev point to the older branch. | |
|
1636 | ||
|
1637 | $ hg graft -q 'desc(change)' | |
|
1638 | ||
|
1639 | Make a rename because we want to track renames. It is also important that the | |
|
1640 | faulty linkrev is not the "start" commit to ensure the linkrev will be used. | |
|
1641 | ||
|
1642 | $ hg mv f renamed | |
|
1643 | $ hg ci -m renamed | |
|
1644 | ||
|
1645 | $ hg log -G -T '{rev} {desc}' | |
|
1646 | @ 4 renamed | |
|
1647 | | | |
|
1648 | o 3 change f | |
|
1649 | | | |
|
1650 | o 2 dev | |
|
1651 | | | |
|
1652 | | o 1 change f | |
|
1653 | |/ | |
|
1654 | o 0 empty f | |
|
1655 | ||
|
1656 | ||
|
1657 | The copy tracking should still reach rev 2 (branch creation). | |
|
1658 | accessing the parent of 4 (renamed) should not jump use to revision 1. | |
|
1659 | ||
|
1660 | $ hg diff --git -r 'desc(dev)' -r . | |
|
1661 | diff --git a/f b/renamed | |
|
1662 | rename from f | |
|
1663 | rename to renamed | |
|
1664 | --- a/f | |
|
1665 | +++ b/renamed | |
|
1666 | @@ -0,0 +1,1 @@ | |
|
1667 | +change | |
|
1668 | ||
|
1669 | $ cd .. |
General Comments 0
You need to be logged in to leave comments.
Login now