Mercurial > hg
comparison mercurial/obsolete.py @ 33143:d09ae850296d
obsutil: move 'exclusivemarkers' to the new modules
We have a new 'obsutil' module now. We move the high level utility there to
bring 'obsolete.py' back to a more reasonable size.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 27 Jun 2017 01:11:56 +0200 |
parents | 4f49810a1011 |
children | d0e5bf12f314 |
comparison
equal
deleted
inserted
replaced
33142:4f49810a1011 | 33143:d09ae850296d |
---|---|
769 if store and readonly: | 769 if store and readonly: |
770 ui.warn(_('obsolete feature not enabled but %i markers found!\n') | 770 ui.warn(_('obsolete feature not enabled but %i markers found!\n') |
771 % len(list(store))) | 771 % len(list(store))) |
772 return store | 772 return store |
773 | 773 |
774 def _filterprunes(markers): | |
775 """return a set with no prune markers""" | |
776 return set(m for m in markers if m[1]) | |
777 | |
778 def exclusivemarkers(repo, nodes): | |
779 """set of markers relevant to "nodes" but no other locally-known nodes | |
780 | |
781 This function compute the set of markers "exclusive" to a locally-known | |
782 node. This means we walk the markers starting from <nodes> until we reach a | |
783 locally-known precursors outside of <nodes>. Element of <nodes> with | |
784 locally-known successors outside of <nodes> are ignored (since their | |
785 precursors markers are also relevant to these successors). | |
786 | |
787 For example: | |
788 | |
789 # (A0 rewritten as A1) | |
790 # | |
791 # A0 <-1- A1 # Marker "1" is exclusive to A1 | |
792 | |
793 or | |
794 | |
795 # (A0 rewritten as AX; AX rewritten as A1; AX is unkown locally) | |
796 # | |
797 # <-1- A0 <-2- AX <-3- A1 # Marker "2,3" are exclusive to A1 | |
798 | |
799 or | |
800 | |
801 # (A0 has unknown precursors, A0 rewritten as A1 and A2 (divergence)) | |
802 # | |
803 # <-2- A1 # Marker "2" is exclusive to A0,A1 | |
804 # / | |
805 # <-1- A0 | |
806 # \ | |
807 # <-3- A2 # Marker "3" is exclusive to A0,A2 | |
808 # | |
809 # in addition: | |
810 # | |
811 # Markers "2,3" are exclusive to A1,A2 | |
812 # Markers "1,2,3" are exclusive to A0,A1,A2 | |
813 | |
814 See test/test-obsolete-bundle-strip.t for more examples. | |
815 | |
816 An example usage is strip. When stripping a changeset, we also want to | |
817 strip the markers exclusive to this changeset. Otherwise we would have | |
818 "dangling"" obsolescence markers from its precursors: Obsolescence markers | |
819 marking a node as obsolete without any successors available locally. | |
820 | |
821 As for relevant markers, the prune markers for children will be followed. | |
822 Of course, they will only be followed if the pruned children is | |
823 locally-known. Since the prune markers are relevant to the pruned node. | |
824 However, while prune markers are considered relevant to the parent of the | |
825 pruned changesets, prune markers for locally-known changeset (with no | |
826 successors) are considered exclusive to the pruned nodes. This allows | |
827 to strip the prune markers (with the rest of the exclusive chain) alongside | |
828 the pruned changesets. | |
829 """ | |
830 # running on a filtered repository would be dangerous as markers could be | |
831 # reported as exclusive when they are relevant for other filtered nodes. | |
832 unfi = repo.unfiltered() | |
833 | |
834 # shortcut to various useful item | |
835 nm = unfi.changelog.nodemap | |
836 precursorsmarkers = unfi.obsstore.precursors | |
837 successormarkers = unfi.obsstore.successors | |
838 childrenmarkers = unfi.obsstore.children | |
839 | |
840 # exclusive markers (return of the function) | |
841 exclmarkers = set() | |
842 # we need fast membership testing | |
843 nodes = set(nodes) | |
844 # looking for head in the obshistory | |
845 # | |
846 # XXX we are ignoring all issues in regard with cycle for now. | |
847 stack = [n for n in nodes if not _filterprunes(successormarkers.get(n, ()))] | |
848 stack.sort() | |
849 # nodes already stacked | |
850 seennodes = set(stack) | |
851 while stack: | |
852 current = stack.pop() | |
853 # fetch precursors markers | |
854 markers = list(precursorsmarkers.get(current, ())) | |
855 # extend the list with prune markers | |
856 for mark in successormarkers.get(current, ()): | |
857 if not mark[1]: | |
858 markers.append(mark) | |
859 # and markers from children (looking for prune) | |
860 for mark in childrenmarkers.get(current, ()): | |
861 if not mark[1]: | |
862 markers.append(mark) | |
863 # traverse the markers | |
864 for mark in markers: | |
865 if mark in exclmarkers: | |
866 # markers already selected | |
867 continue | |
868 | |
869 # If the markers is about the current node, select it | |
870 # | |
871 # (this delay the addition of markers from children) | |
872 if mark[1] or mark[0] == current: | |
873 exclmarkers.add(mark) | |
874 | |
875 # should we keep traversing through the precursors? | |
876 prec = mark[0] | |
877 | |
878 # nodes in the stack or already processed | |
879 if prec in seennodes: | |
880 continue | |
881 | |
882 # is this a locally known node ? | |
883 known = prec in nm | |
884 # if locally-known and not in the <nodes> set the traversal | |
885 # stop here. | |
886 if known and prec not in nodes: | |
887 continue | |
888 | |
889 # do not keep going if there are unselected markers pointing to this | |
890 # nodes. If we end up traversing these unselected markers later the | |
891 # node will be taken care of at that point. | |
892 precmarkers = _filterprunes(successormarkers.get(prec)) | |
893 if precmarkers.issubset(exclmarkers): | |
894 seennodes.add(prec) | |
895 stack.append(prec) | |
896 | |
897 return exclmarkers | |
898 | |
899 def commonversion(versions): | 774 def commonversion(versions): |
900 """Return the newest version listed in both versions and our local formats. | 775 """Return the newest version listed in both versions and our local formats. |
901 | 776 |
902 Returns None if no common version exists. | 777 Returns None if no common version exists. |
903 """ | 778 """ |
969 If <nodes> is specified, only markers "relevant" to those nodes are are | 844 If <nodes> is specified, only markers "relevant" to those nodes are are |
970 returned""" | 845 returned""" |
971 if nodes is None: | 846 if nodes is None: |
972 rawmarkers = repo.obsstore | 847 rawmarkers = repo.obsstore |
973 elif exclusive: | 848 elif exclusive: |
974 rawmarkers = exclusivemarkers(repo, nodes) | 849 rawmarkers = obsutil.exclusivemarkers(repo, nodes) |
975 else: | 850 else: |
976 rawmarkers = repo.obsstore.relevantmarkers(nodes) | 851 rawmarkers = repo.obsstore.relevantmarkers(nodes) |
977 | 852 |
978 for markerdata in rawmarkers: | 853 for markerdata in rawmarkers: |
979 yield marker(repo, markerdata) | 854 yield marker(repo, markerdata) |
1060 mutable = [c.node() for c in foreground if c.mutable()] | 935 mutable = [c.node() for c in foreground if c.mutable()] |
1061 succs.update(allsuccessors(repo.obsstore, mutable)) | 936 succs.update(allsuccessors(repo.obsstore, mutable)) |
1062 known = (n for n in succs if n in nm) | 937 known = (n for n in succs if n in nm) |
1063 foreground = set(repo.set('%ln::', known)) | 938 foreground = set(repo.set('%ln::', known)) |
1064 return set(c.node() for c in foreground) | 939 return set(c.node() for c in foreground) |
940 | |
941 def exclusivemarkers(repo, nodes): | |
942 movemsg = 'obsolete.exclusivemarkers moved to obsutil.exclusivemarkers' | |
943 repo.ui.deprecwarn(movemsg, '4.3') | |
944 return obsutil.exclusivemarkers(repo, nodes) | |
1065 | 945 |
1066 def successorssets(repo, initialnode, cache=None): | 946 def successorssets(repo, initialnode, cache=None): |
1067 movemsg = 'obsolete.successorssets moved to obsutil.successorssets' | 947 movemsg = 'obsolete.successorssets moved to obsutil.successorssets' |
1068 repo.ui.deprecwarn(movemsg, '4.3') | 948 repo.ui.deprecwarn(movemsg, '4.3') |
1069 return obsutil.successorssets(repo, initialnode, cache=cache) | 949 return obsutil.successorssets(repo, initialnode, cache=cache) |