summaryrefslogtreecommitdiffstats
path: root/subcmds
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2015-08-17 13:41:45 -0700
committerDan Willemsen <dwillemsen@google.com>2015-08-19 10:22:11 -0700
commit0745bb26571e0cf097baebd48761b8cd743ec7fc (patch)
treeb8d83d1ec06cd3d430dfc2f5447276e38e2f86f7 /subcmds
parent5d0c3a614edc3f3d5967cfc07c7981da7013ea91 (diff)
downloadgit-repo-0745bb26571e0cf097baebd48761b8cd743ec7fc.tar.gz
Support smart-sync through persistent-http[s]
Use the same cookies and proxy that git traffic goes through for persistent-http[s] to support authentication for smart-sync. Change-Id: I20f4a281c259053a5a4fdbc48b1bca48e781c692
Diffstat (limited to 'subcmds')
-rw-r--r--subcmds/sync.py105
1 files changed, 104 insertions, 1 deletions
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 43d450be..ed8622c1 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -23,18 +23,26 @@ import shutil
23import socket 23import socket
24import subprocess 24import subprocess
25import sys 25import sys
26import tempfile
26import time 27import time
27 28
28from pyversion import is_python3 29from pyversion import is_python3
29if is_python3(): 30if is_python3():
31 import http.cookiejar as cookielib
32 import urllib.error
30 import urllib.parse 33 import urllib.parse
34 import urllib.request
31 import xmlrpc.client 35 import xmlrpc.client
32else: 36else:
37 import cookielib
33 import imp 38 import imp
39 import urllib2
34 import urlparse 40 import urlparse
35 import xmlrpclib 41 import xmlrpclib
36 urllib = imp.new_module('urllib') 42 urllib = imp.new_module('urllib')
43 urllib.error = urllib2
37 urllib.parse = urlparse 44 urllib.parse = urlparse
45 urllib.request = urllib2
38 xmlrpc = imp.new_module('xmlrpc') 46 xmlrpc = imp.new_module('xmlrpc')
39 xmlrpc.client = xmlrpclib 47 xmlrpc.client = xmlrpclib
40 48
@@ -57,6 +65,7 @@ except ImportError:
57 multiprocessing = None 65 multiprocessing = None
58 66
59from git_command import GIT, git_require 67from git_command import GIT, git_require
68from git_config import GetSchemeFromUrl, GetUrlCookieFile
60from git_refs import R_HEADS, HEAD 69from git_refs import R_HEADS, HEAD
61from project import Project 70from project import Project
62from project import RemoteSpec 71from project import RemoteSpec
@@ -575,8 +584,12 @@ later is required to fix a server side protocol bug.
575 (username, password), 584 (username, password),
576 1) 585 1)
577 586
587 transport = PersistentTransport(manifest_server)
588 if manifest_server.startswith('persistent-'):
589 manifest_server = manifest_server[len('persistent-'):]
590
578 try: 591 try:
579 server = xmlrpc.client.Server(manifest_server) 592 server = xmlrpc.client.Server(manifest_server, transport=transport)
580 if opt.smart_sync: 593 if opt.smart_sync:
581 p = self.manifest.manifestProject 594 p = self.manifest.manifestProject
582 b = p.GetBranch(p.CurrentBranch) 595 b = p.GetBranch(p.CurrentBranch)
@@ -850,3 +863,93 @@ class _FetchTimes(object):
850 os.remove(self._path) 863 os.remove(self._path)
851 except OSError: 864 except OSError:
852 pass 865 pass
866
867# This is a replacement for xmlrpc.client.Transport using urllib2
868# and supporting persistent-http[s]. It cannot change hosts from
869# request to request like the normal transport, the real url
870# is passed during initialization.
871class PersistentTransport(xmlrpc.client.Transport):
872 def __init__(self, orig_host):
873 self.orig_host = orig_host
874
875 def request(self, host, handler, request_body, verbose=False):
876 with GetUrlCookieFile(self.orig_host, not verbose) as (cookiefile, proxy):
877 # Python doesn't understand cookies with the #HttpOnly_ prefix
878 # Since we're only using them for HTTP, copy the file temporarily,
879 # stripping those prefixes away.
880 tmpcookiefile = tempfile.NamedTemporaryFile()
881 try:
882 with open(cookiefile) as f:
883 for line in f:
884 if line.startswith("#HttpOnly_"):
885 line = line[len("#HttpOnly_"):]
886 tmpcookiefile.write(line)
887 tmpcookiefile.flush()
888
889 cookiejar = cookielib.MozillaCookieJar(tmpcookiefile.name)
890 cookiejar.load()
891 finally:
892 tmpcookiefile.close()
893
894 proxyhandler = urllib.request.ProxyHandler
895 if proxy:
896 proxyhandler = urllib.request.ProxyHandler({
897 "http": proxy,
898 "https": proxy })
899
900 opener = urllib.request.build_opener(
901 urllib.request.HTTPCookieProcessor(cookiejar),
902 proxyhandler)
903
904 url = urllib.parse.urljoin(self.orig_host, handler)
905 parse_results = urllib.parse.urlparse(url)
906
907 scheme = parse_results.scheme
908 if scheme == 'persistent-http':
909 scheme = 'http'
910 if scheme == 'persistent-https':
911 # If we're proxying through persistent-https, use http. The
912 # proxy itself will do the https.
913 if proxy:
914 scheme = 'http'
915 else:
916 scheme = 'https'
917
918 # Parse out any authentication information using the base class
919 host, extra_headers, _ = self.get_host_info(parse_results.netloc)
920
921 url = urllib.parse.urlunparse((
922 scheme,
923 host,
924 parse_results.path,
925 parse_results.params,
926 parse_results.query,
927 parse_results.fragment))
928
929 request = urllib.request.Request(url, request_body)
930 if extra_headers is not None:
931 for (name, header) in extra_headers:
932 request.add_header(name, header)
933 request.add_header('Content-Type', 'text/xml')
934 try:
935 response = opener.open(request)
936 except urllib.error.HTTPError as e:
937 if e.code == 501:
938 # We may have been redirected through a login process
939 # but our POST turned into a GET. Retry.
940 response = opener.open(request)
941 else:
942 raise
943
944 p, u = xmlrpc.client.getparser()
945 while 1:
946 data = response.read(1024)
947 if not data:
948 break
949 p.feed(data)
950 p.close()
951 return u.close()
952
953 def close(self):
954 pass
955