Merge "Fix a few issues with dest-branch and multiples"
diff --git a/manifest_xml.py b/manifest_xml.py
index 817a1c8..b6f7547 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -27,7 +27,7 @@
   import imp
   import urlparse
   urllib = imp.new_module('urllib')
-  urllib.parse = urlparse
+  urllib.parse = urlparse.urlparse
 
 from git_config import GitConfig
 from git_refs import R_HEADS, HEAD
diff --git a/project.py b/project.py
index 5a7a6ca..679dccc 100644
--- a/project.py
+++ b/project.py
@@ -1728,9 +1728,8 @@
     remote = self.GetRemote(self.remote.name)
     bundle_url = remote.url + '/clone.bundle'
     bundle_url = GitConfig.ForUser().UrlInsteadOf(bundle_url)
-    if GetSchemeFromUrl(bundle_url) in ('persistent-http', 'persistent-https'):
-      bundle_url = bundle_url[len('persistent-'):]
-    if GetSchemeFromUrl(bundle_url) not in ('http', 'https'):
+    if GetSchemeFromUrl(bundle_url) not in (
+        'http', 'https', 'persistent-http', 'persistent-https'):
       return False
 
     bundle_dst = os.path.join(self.gitdir, 'clone.bundle')
@@ -1779,9 +1778,11 @@
         os.remove(tmpPath)
     if 'http_proxy' in os.environ and 'darwin' == sys.platform:
       cmd += ['--proxy', os.environ['http_proxy']]
-    cookiefile = GitConfig.ForUser().GetString('http.cookiefile')
+    cookiefile = self._GetBundleCookieFile(srcUrl)
     if cookiefile:
       cmd += ['--cookie', cookiefile]
+    if srcUrl.startswith('persistent-'):
+      srcUrl = srcUrl[len('persistent-'):]
     cmd += [srcUrl]
 
     if IsTrace():
@@ -1804,7 +1805,7 @@
       return False
 
     if os.path.exists(tmpPath):
-      if curlret == 0 and os.stat(tmpPath).st_size > 16:
+      if curlret == 0 and self._IsValidBundle(tmpPath):
         os.rename(tmpPath, dstPath)
         return True
       else:
@@ -1813,6 +1814,41 @@
     else:
       return False
 
+  def _IsValidBundle(self, path):
+    try:
+      with open(path) as f:
+        if f.read(16) == '# v2 git bundle\n':
+          return True
+        else:
+          print("Invalid clone.bundle file; ignoring.", file=sys.stderr)
+          return False
+    except OSError:
+      return False
+
+  def _GetBundleCookieFile(self, url):
+    if url.startswith('persistent-'):
+      try:
+        p = subprocess.Popen(
+            ['git-remote-persistent-https', '-print_config', url],
+            stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE)
+        prefix = 'http.cookiefile='
+        for line in p.stdout:
+          line = line.strip()
+          if line.startswith(prefix):
+            return line[len(prefix):]
+        if p.wait():
+          line = iter(p.stderr).next()
+          if ' -print_config' in line:
+            pass  # Persistent proxy doesn't support -print_config.
+          else:
+            print(line + p.stderr.read(), file=sys.stderr)
+      except OSError as e:
+        if e.errno == errno.ENOENT:
+          pass  # No persistent proxy.
+        raise
+    return GitConfig.ForUser().GetString('http.cookiefile')
+
   def _Checkout(self, rev, quiet=False):
     cmd = ['checkout']
     if quiet:
diff --git a/subcmds/forall.py b/subcmds/forall.py
index 7d5f779..e2a420a 100644
--- a/subcmds/forall.py
+++ b/subcmds/forall.py
@@ -260,7 +260,12 @@
                 first = False
               else:
                 out.nl()
-              out.project('project %s/', project.relpath)
+
+              if mirror:
+                project_header_path = project.name
+              else:
+                project_header_path = project.relpath
+              out.project('project %s/', project_header_path)
               out.nl()
               out.flush()
               if errbuf:
diff --git a/subcmds/sync.py b/subcmds/sync.py
index b34787d..930211c 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -34,7 +34,7 @@
   import urlparse
   import xmlrpclib
   urllib = imp.new_module('urllib')
-  urllib.parse = urlparse
+  urllib.parse = urlparse.urlparse
   xmlrpc = imp.new_module('xmlrpc')
   xmlrpc.client = xmlrpclib
 
@@ -526,6 +526,7 @@
                                                     (username, password),
                                                     1)
 
+      manifest_name = opt.manifest_name
       try:
         server = xmlrpc.client.Server(manifest_server)
         if opt.smart_sync:
@@ -560,7 +561,7 @@
             print('error: cannot write manifest to %s' % manifest_path,
                   file=sys.stderr)
             sys.exit(1)
-          self.manifest.Override(manifest_name)
+          self._ReloadManifest(manifest_name)
         else:
           print('error: %s' % manifest_str, file=sys.stderr)
           sys.exit(1)
@@ -593,7 +594,7 @@
       mp.Sync_LocalHalf(syncbuf)
       if not syncbuf.Finish():
         sys.exit(1)
-      self._ReloadManifest(opt.manifest_name)
+      self._ReloadManifest(manifest_name)
       if opt.jobs is None:
         self.jobs = self.manifest.default.sync_j
     all_projects = self.GetProjects(args,
@@ -618,7 +619,7 @@
       # Iteratively fetch missing and/or nested unregistered submodules
       previously_missing_set = set()
       while True:
-        self._ReloadManifest(opt.manifest_name)
+        self._ReloadManifest(manifest_name)
         all_projects = self.GetProjects(args,
                                         missing_ok=True,
                                         submodules_ok=opt.fetch_submodules)
diff --git a/subcmds/upload.py b/subcmds/upload.py
index 0c74738..fc17670 100644
--- a/subcmds/upload.py
+++ b/subcmds/upload.py
@@ -224,6 +224,8 @@
 
       b = {}
       for branch in avail:
+        if branch is None:
+          continue
         name = branch.name
         date = branch.date
         commit_list = branch.commits