Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/localrepo.py @ 2021:fc22ed56afe3
Fix hg push and hg push -r sometimes creating new heads without --force.
Fixing issue179.
The algorithm checks if there not more new heads on the remote side than heads
which become non-heads due to getting children.
Pushing this repo:
m
/\
3 3a|
|/ /
2 2a
|/
1
to a repo only having 1, 2 and 3 didn't abort requiring --force before.
Added test cases for this and some doc strings for used methods.
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Wed, 29 Mar 2006 22:35:21 +0200 |
parents | 00925397236c |
children | a59da8cc35e4 |
comparison
equal
deleted
inserted
replaced
2020:00925397236c | 2021:fc22ed56afe3 |
---|---|
921 self.ui.debug(_("%d total queries\n") % reqcnt) | 921 self.ui.debug(_("%d total queries\n") % reqcnt) |
922 | 922 |
923 return fetch.keys() | 923 return fetch.keys() |
924 | 924 |
925 def findoutgoing(self, remote, base=None, heads=None, force=False): | 925 def findoutgoing(self, remote, base=None, heads=None, force=False): |
926 """Return list of nodes that are roots of subsets not in remote | |
927 | |
928 If base dict is specified, assume that these nodes and their parents | |
929 exist on the remote side. | |
930 If a list of heads is specified, return only nodes which are heads | |
931 or ancestors of these heads, and return a second element which | |
932 contains all remote heads which get new children. | |
933 """ | |
926 if base == None: | 934 if base == None: |
927 base = {} | 935 base = {} |
928 self.findincoming(remote, base, heads, force=force) | 936 self.findincoming(remote, base, heads, force=force) |
929 | 937 |
930 self.ui.debug(_("common changesets up to ") | 938 self.ui.debug(_("common changesets up to ") |
942 for p in self.changelog.parents(n): | 950 for p in self.changelog.parents(n): |
943 remove.append(p) | 951 remove.append(p) |
944 | 952 |
945 # find every node whose parents have been pruned | 953 # find every node whose parents have been pruned |
946 subset = [] | 954 subset = [] |
955 # find every remote head that will get new children | |
956 updated_heads = {} | |
947 for n in remain: | 957 for n in remain: |
948 p1, p2 = self.changelog.parents(n) | 958 p1, p2 = self.changelog.parents(n) |
949 if p1 not in remain and p2 not in remain: | 959 if p1 not in remain and p2 not in remain: |
950 subset.append(n) | 960 subset.append(n) |
961 if heads: | |
962 if p1 in heads: | |
963 updated_heads[p1] = True | |
964 if p2 in heads: | |
965 updated_heads[p2] = True | |
951 | 966 |
952 # this is the set of all roots we have to push | 967 # this is the set of all roots we have to push |
953 return subset | 968 if heads: |
969 return subset, updated_heads.keys() | |
970 else: | |
971 return subset | |
954 | 972 |
955 def pull(self, remote, heads=None, force=False): | 973 def pull(self, remote, heads=None, force=False): |
956 l = self.lock() | 974 l = self.lock() |
957 | 975 |
958 # if we have an empty repo, fetch everything | 976 # if we have an empty repo, fetch everything |
974 | 992 |
975 def push(self, remote, force=False, revs=None): | 993 def push(self, remote, force=False, revs=None): |
976 lock = remote.lock() | 994 lock = remote.lock() |
977 | 995 |
978 base = {} | 996 base = {} |
979 heads = remote.heads() | 997 remote_heads = remote.heads() |
980 inc = self.findincoming(remote, base, heads, force=force) | 998 inc = self.findincoming(remote, base, remote_heads, force=force) |
981 if not force and inc: | 999 if not force and inc: |
982 self.ui.warn(_("abort: unsynced remote changes!\n")) | 1000 self.ui.warn(_("abort: unsynced remote changes!\n")) |
983 self.ui.status(_("(did you forget to sync? use push -f to force)\n")) | 1001 self.ui.status(_("(did you forget to sync?" |
1002 " use push -f to force)\n")) | |
984 return 1 | 1003 return 1 |
985 | 1004 |
986 update = self.findoutgoing(remote, base) | 1005 update, updated_heads = self.findoutgoing(remote, base, remote_heads) |
987 if revs is not None: | 1006 if revs is not None: |
988 msng_cl, bases, heads = self.changelog.nodesbetween(update, revs) | 1007 msng_cl, bases, heads = self.changelog.nodesbetween(update, revs) |
989 else: | 1008 else: |
990 bases, heads = update, self.changelog.heads() | 1009 bases, heads = update, self.changelog.heads() |
991 | 1010 |
992 if not bases: | 1011 if not bases: |
993 self.ui.status(_("no changes found\n")) | 1012 self.ui.status(_("no changes found\n")) |
994 return 1 | 1013 return 1 |
995 elif not force: | 1014 elif not force: |
996 if len(bases) < len(heads): | 1015 if revs is not None: |
1016 updated_heads = {} | |
1017 for base in msng_cl: | |
1018 for parent in self.changelog.parents(base): | |
1019 if parent in remote_heads: | |
1020 updated_heads[parent] = True | |
1021 updated_heads = updated_heads.keys() | |
1022 if len(updated_heads) < len(heads): | |
997 self.ui.warn(_("abort: push creates new remote branches!\n")) | 1023 self.ui.warn(_("abort: push creates new remote branches!\n")) |
998 self.ui.status(_("(did you forget to merge?" | 1024 self.ui.status(_("(did you forget to merge?" |
999 " use push -f to force)\n")) | 1025 " use push -f to force)\n")) |
1000 return 1 | 1026 return 1 |
1001 | 1027 |