mercurial/revset.py
changeset 23719 34364a4b25eb
parent 23704 c624fb2c4239
child 23720 8ec03e0ef51a
equal deleted inserted replaced
23718:42908c3275c6 23719:34364a4b25eb
   769     result, use ``file()``.
   769     result, use ``file()``.
   770 
   770 
   771     The pattern without explicit kind like ``glob:`` is expected to be
   771     The pattern without explicit kind like ``glob:`` is expected to be
   772     relative to the current directory and match against a file exactly
   772     relative to the current directory and match against a file exactly
   773     for efficiency.
   773     for efficiency.
       
   774 
       
   775     If some linkrev points to revisions filtered by the current repoview, we'll
       
   776     work around it to return a non-filtered value.
   774     """
   777     """
   775 
   778 
   776     # i18n: "filelog" is a keyword
   779     # i18n: "filelog" is a keyword
   777     pat = getstring(x, _("filelog requires a pattern"))
   780     pat = getstring(x, _("filelog requires a pattern"))
   778     s = set()
   781     s = set()
       
   782     cl = repo.changelog
   779 
   783 
   780     if not matchmod.patkind(pat):
   784     if not matchmod.patkind(pat):
   781         f = pathutil.canonpath(repo.root, repo.getcwd(), pat)
   785         f = pathutil.canonpath(repo.root, repo.getcwd(), pat)
   782         fl = repo.file(f)
   786         files = [f]
   783         for fr in fl:
       
   784             s.add(fl.linkrev(fr))
       
   785     else:
   787     else:
   786         m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[None])
   788         m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[None])
   787         for f in repo[None]:
   789         files = (f for f in repo[None] if m(f))
   788             if m(f):
   790 
   789                 fl = repo.file(f)
   791     for f in files:
   790                 for fr in fl:
   792         backrevref = {}  # final value for: changerev -> filerev
   791                     s.add(fl.linkrev(fr))
   793         lowestchild = {} # lowest known filerev child of a filerev
       
   794         delayed = []     # filerev with filtered linkrev, for post-processing
       
   795         fl = repo.file(f)
       
   796         for fr in list(fl):
       
   797             lkr = rev = fl.linkrev(fr)
       
   798             if rev not in cl:
       
   799                 # changerev pointed in linkrev is filtered
       
   800                 # record it for post processing.
       
   801                 delayed.append((fr, rev))
       
   802                 continue
       
   803             for p in fl.parentrevs(fr):
       
   804                 if 0 <= p and p not in lowestchild:
       
   805                     lowestchild[p] = fr
       
   806             backrevref[fr] = rev
       
   807             s.add(rev)
       
   808 
       
   809         # Post-processing of all filerevs we skipped because they were
       
   810         # filtered. If such filerevs have known and unfiltered children, this
       
   811         # means they have an unfiltered appearance out there. We'll use linkrev
       
   812         # adjustment to find one of these appearances. The lowest known child
       
   813         # will be used as a starting point because it is the best upper-bound we
       
   814         # have.
       
   815         #
       
   816         # This approach will fail when an unfiltered but linkrev-shadowed
       
   817         # appearance exists in a head changeset without unfiltered filerev
       
   818         # children anywhere.
       
   819         while delayed:
       
   820             # must be a descending iteration. To slowly fill lowest child
       
   821             # information that is of potential use by the next item.
       
   822             fr, rev = delayed.pop()
       
   823             lkr = rev
       
   824 
       
   825             child = lowestchild.get(fr)
       
   826 
       
   827             if child is None:
       
   828                 # XXX content could be linkrev-shadowed in a head, but lets
       
   829                 # ignore this case for now.
       
   830                 continue
       
   831             else:
       
   832                 # the lowest known child is a good upper bound
       
   833                 childcrev = backrevref[child]
       
   834                 # XXX this does not guarantee returning the lowest
       
   835                 # introduction of this revision, but this gives a
       
   836                 # result which is a good start and will fit in most
       
   837                 # cases. We probably need to fix the multiple
       
   838                 # introductions case properly (report each
       
   839                 # introduction, even for identical file revisions)
       
   840                 # once and for all at some point anyway.
       
   841                 for p in repo[childcrev][f].parents():
       
   842                     if p.filerev() == fr:
       
   843                         rev = p.rev()
       
   844                         break
       
   845                 if rev == lkr:  # no shadowed entry found
       
   846                     # XXX This should never happen unless some manifest points
       
   847                     # to biggish file revisions (like a revision that uses a
       
   848                     # parent that never appears in the manifest ancestors)
       
   849                     continue
       
   850 
       
   851             # Fill the data for the next iteration.
       
   852             for p in fl.parentrevs(fr):
       
   853                 if 0 <= p and p not in lowestchild:
       
   854                     lowestchild[p] = fr
       
   855             backrevref[fr] = rev
       
   856             s.add(rev)
   792 
   857 
   793     return subset & s
   858     return subset & s
   794 
   859 
   795 def first(repo, subset, x):
   860 def first(repo, subset, x):
   796     """``first(set, [n])``
   861     """``first(set, [n])``