Show More
@@ -22,6 +22,40 b' propertycache = util.propertycache' | |||||
22 | # dirty in the working copy. |
|
22 | # dirty in the working copy. | |
23 | _newnode = '!' * 21 |
|
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 | class basectx(object): |
|
59 | class basectx(object): | |
26 | """A basectx object represents the common logic for its children: |
|
60 | """A basectx object represents the common logic for its children: | |
27 | changectx: read-only context that is already present in the repo, |
|
61 | changectx: read-only context that is already present in the repo, | |
@@ -739,7 +773,7 b' class basefilectx(object):' | |||||
739 | parents = self._filelog.parents(self._filenode) |
|
773 | parents = self._filelog.parents(self._filenode) | |
740 | pl = [(_path, node, fl) for node in parents if node != nullid] |
|
774 | pl = [(_path, node, fl) for node in parents if node != nullid] | |
741 |
|
775 | |||
742 |
r = |
|
776 | r = fl.renamed(self._filenode) | |
743 | if r: |
|
777 | if r: | |
744 | # - In the simple rename case, both parent are nullid, pl is empty. |
|
778 | # - In the simple rename case, both parent are nullid, pl is empty. | |
745 | # - In case of merge, only one of the parent is null id and should |
|
779 | # - In case of merge, only one of the parent is null id and should | |
@@ -751,7 +785,19 b' class basefilectx(object):' | |||||
751 | # first nullid parent with rename information. |
|
785 | # first nullid parent with rename information. | |
752 | pl.insert(0, (r[0], r[1], self._repo.file(r[0]))) |
|
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 | def p1(self): |
|
802 | def p1(self): | |
757 | return self.parents()[0] |
|
803 | return self.parents()[0] |
@@ -451,3 +451,63 b' Annotate with --ignore-blank-lines (simi' | |||||
451 | 1: b b |
|
451 | 1: b b | |
452 |
|
452 | |||
453 | $ cd .. |
|
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 | o a |
|
1564 | o a | |
1565 |
|
1565 | |||
1566 | $ cd .. |
|
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 | +f |
|
1606 | +f | |
1607 | $ cd .. |
|
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