Merge with Matt.
authorBryan O'Sullivan <bos@serpentine.com>
Thu, 04 Aug 2005 05:14:59 -0800
changeset 838 0fc4b1ab57e3
parent 837 a95c9b3fc3bf (current diff)
parent 818 eef752151556 (diff)
child 839 9c918287d10b
Merge with Matt.
mercurial/commands.py
mercurial/hg.py
mercurial/util.py
tests/test-merge5.out
tests/test-push-warn
tests/test-push-warn.out
--- 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