Merge with Matt.
--- a/mercurial/commands.py Wed Aug 03 09:10:48 2005 -0800
+++ b/mercurial/commands.py Thu Aug 04 05:14:59 2005 -0800
@@ -839,13 +839,13 @@
return r
-def push(ui, repo, dest="default-push"):
+def push(ui, repo, dest="default-push", force=False):
"""push changes to the specified destination"""
dest = ui.expandpath(dest)
ui.status('pushing to %s\n' % (dest))
other = hg.repository(ui, dest)
- r = repo.push(other)
+ r = repo.push(other, force)
return r
def rawcommit(ui, repo, *flist, **rc):
@@ -1228,7 +1228,10 @@
(pull,
[('u', 'update', None, 'update working directory')],
'hg pull [-u] [SOURCE]'),
- "^push": (push, [], 'hg push [DEST]'),
+ "^push":
+ (push,
+ [('f', 'force', None, 'force push')],
+ 'hg push [DEST]'),
"rawcommit":
(rawcommit,
[('p', 'parent', [], 'parent'),
--- a/mercurial/hg.py Wed Aug 03 09:10:48 2005 -0800
+++ b/mercurial/hg.py Thu Aug 04 05:14:59 2005 -0800
@@ -1059,17 +1059,22 @@
return nl
- def findincoming(self, remote, base={}):
+ def findincoming(self, remote, base=None, heads=None):
m = self.changelog.nodemap
search = []
fetch = []
seen = {}
seenbranch = {}
+ if base == None:
+ base = {}
# assume we're closer to the tip than the root
# and start by examining the heads
self.ui.status("searching for changes\n")
- heads = remote.heads()
+
+ if not heads:
+ heads = remote.heads()
+
unknown = []
for h in heads:
if h not in m:
@@ -1171,9 +1176,11 @@
return fetch
- def findoutgoing(self, remote):
- base = {}
- self.findincoming(remote, base)
+ def findoutgoing(self, remote, base=None, heads=None):
+ if base == None:
+ base = {}
+ self.findincoming(remote, base, heads)
+
remain = dict.fromkeys(self.changelog.nodemap)
# prune everything remote has from the tree
@@ -1213,12 +1220,27 @@
cg = remote.changegroup(fetch)
return self.addchangegroup(cg)
- def push(self, remote):
+ def push(self, remote, force=False):
lock = remote.lock()
- update = self.findoutgoing(remote)
+
+ base = {}
+ heads = remote.heads()
+ inc = self.findincoming(remote, base, heads)
+ if not force and inc:
+ self.ui.warn("abort: unsynced remote changes!\n")
+ self.ui.status("(did you forget to sync? use push -f to force)\n")
+ return 1
+
+ update = self.findoutgoing(remote, base)
if not update:
self.ui.status("no changes found\n")
return 1
+ elif not force:
+ if len(heads) < len(self.changelog.heads()):
+ self.ui.warn("abort: push creates new remote branches!\n")
+ self.ui.status("(did you forget to merge?" +
+ " use push -f to force)\n")
+ return 1
cg = self.changegroup(update)
return remote.addchangegroup(cg)
@@ -1868,9 +1890,9 @@
self.url = path
self.ui = ui
- m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', path)
+ m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))', path)
if not m:
- raise RepoError("couldn't parse destination %s\n" % path)
+ raise RepoError("couldn't parse destination %s" % path)
self.user = m.group(2)
self.host = m.group(3)
@@ -1881,6 +1903,9 @@
args = self.port and ("%s -p %s") % (args, self.port) or args
path = self.path or ""
+ if not path:
+ raise RepoError("no remote repository path specified")
+
cmd = "ssh %s 'hg -R %s serve --stdio'"
cmd = cmd % (args, path)
@@ -1895,11 +1920,14 @@
self.ui.status("remote: ", l)
def __del__(self):
- self.pipeo.close()
- self.pipei.close()
- for l in self.pipee:
- self.ui.status("remote: ", l)
- self.pipee.close()
+ try:
+ self.pipeo.close()
+ self.pipei.close()
+ for l in self.pipee:
+ self.ui.status("remote: ", l)
+ self.pipee.close()
+ except:
+ pass
def dev(self):
return -1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-push-warn Thu Aug 04 05:14:59 2005 -0800
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+mkdir a
+cd a
+hg init
+echo foo > t1
+hg add t1
+hg commit -m "1" -d "0 0"
+
+cd ..
+hg clone a b
+
+cd a
+echo foo > t2
+hg add t2
+hg commit -m "2" -d "0 0"
+
+cd ../b
+echo foo > t3
+hg add t3
+hg commit -m "3" -d "0 0"
+
+hg push ../a
+hg pull ../a
+hg push ../a
+hg up -m
+hg commit -m "4" -d "0 0"
+hg push ../a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-push-warn.out Thu Aug 04 05:14:59 2005 -0800
@@ -0,0 +1,35 @@
++ hg init
++ hg add t1
++ hg commit -m 1 -d 0 0
++ hg clone a b
++ hg add t2
++ hg commit -m 2 -d 0 0
++ hg add t3
++ hg commit -m 3 -d 0 0
++ hg push ../a
+pushing to ../a
+searching for changes
+abort: unsynced remote changes!
+(did you forget to sync? use push -f to force)
++ hg pull ../a
+pulling from ../a
+searching for changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 1 changes to 1 files
+(run 'hg update' to get a working copy)
++ hg push ../a
+pushing to ../a
+searching for changes
+abort: push creates new remote branches!
+(did you forget to merge? use push -f to force)
++ hg up -m
++ hg commit -m 4 -d 0 0
++ hg push ../a
+pushing to ../a
+searching for changes
+adding changesets
+adding manifests
+adding file changes
+added 2 changesets with 2 changes to 2 files