mirror of
https://gerrit.googlesource.com/git-repo
synced 2025-06-19 12:34:17 +00:00
Merge "Support smart-sync through persistent-http[s]"
This commit is contained in:
105
subcmds/sync.py
105
subcmds/sync.py
@ -23,18 +23,26 @@ import shutil
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
from pyversion import is_python3
|
||||
if is_python3():
|
||||
import http.cookiejar as cookielib
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
import xmlrpc.client
|
||||
else:
|
||||
import cookielib
|
||||
import imp
|
||||
import urllib2
|
||||
import urlparse
|
||||
import xmlrpclib
|
||||
urllib = imp.new_module('urllib')
|
||||
urllib.error = urllib2
|
||||
urllib.parse = urlparse
|
||||
urllib.request = urllib2
|
||||
xmlrpc = imp.new_module('xmlrpc')
|
||||
xmlrpc.client = xmlrpclib
|
||||
|
||||
@ -57,6 +65,7 @@ except ImportError:
|
||||
multiprocessing = None
|
||||
|
||||
from git_command import GIT, git_require
|
||||
from git_config import GetSchemeFromUrl, GetUrlCookieFile
|
||||
from git_refs import R_HEADS, HEAD
|
||||
import gitc_utils
|
||||
from project import Project
|
||||
@ -598,8 +607,12 @@ later is required to fix a server side protocol bug.
|
||||
(username, password),
|
||||
1)
|
||||
|
||||
transport = PersistentTransport(manifest_server)
|
||||
if manifest_server.startswith('persistent-'):
|
||||
manifest_server = manifest_server[len('persistent-'):]
|
||||
|
||||
try:
|
||||
server = xmlrpc.client.Server(manifest_server)
|
||||
server = xmlrpc.client.Server(manifest_server, transport=transport)
|
||||
if opt.smart_sync:
|
||||
p = self.manifest.manifestProject
|
||||
b = p.GetBranch(p.CurrentBranch)
|
||||
@ -879,3 +892,93 @@ class _FetchTimes(object):
|
||||
os.remove(self._path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# This is a replacement for xmlrpc.client.Transport using urllib2
|
||||
# and supporting persistent-http[s]. It cannot change hosts from
|
||||
# request to request like the normal transport, the real url
|
||||
# is passed during initialization.
|
||||
class PersistentTransport(xmlrpc.client.Transport):
|
||||
def __init__(self, orig_host):
|
||||
self.orig_host = orig_host
|
||||
|
||||
def request(self, host, handler, request_body, verbose=False):
|
||||
with GetUrlCookieFile(self.orig_host, not verbose) as (cookiefile, proxy):
|
||||
# Python doesn't understand cookies with the #HttpOnly_ prefix
|
||||
# Since we're only using them for HTTP, copy the file temporarily,
|
||||
# stripping those prefixes away.
|
||||
tmpcookiefile = tempfile.NamedTemporaryFile()
|
||||
try:
|
||||
with open(cookiefile) as f:
|
||||
for line in f:
|
||||
if line.startswith("#HttpOnly_"):
|
||||
line = line[len("#HttpOnly_"):]
|
||||
tmpcookiefile.write(line)
|
||||
tmpcookiefile.flush()
|
||||
|
||||
cookiejar = cookielib.MozillaCookieJar(tmpcookiefile.name)
|
||||
cookiejar.load()
|
||||
finally:
|
||||
tmpcookiefile.close()
|
||||
|
||||
proxyhandler = urllib.request.ProxyHandler
|
||||
if proxy:
|
||||
proxyhandler = urllib.request.ProxyHandler({
|
||||
"http": proxy,
|
||||
"https": proxy })
|
||||
|
||||
opener = urllib.request.build_opener(
|
||||
urllib.request.HTTPCookieProcessor(cookiejar),
|
||||
proxyhandler)
|
||||
|
||||
url = urllib.parse.urljoin(self.orig_host, handler)
|
||||
parse_results = urllib.parse.urlparse(url)
|
||||
|
||||
scheme = parse_results.scheme
|
||||
if scheme == 'persistent-http':
|
||||
scheme = 'http'
|
||||
if scheme == 'persistent-https':
|
||||
# If we're proxying through persistent-https, use http. The
|
||||
# proxy itself will do the https.
|
||||
if proxy:
|
||||
scheme = 'http'
|
||||
else:
|
||||
scheme = 'https'
|
||||
|
||||
# Parse out any authentication information using the base class
|
||||
host, extra_headers, _ = self.get_host_info(parse_results.netloc)
|
||||
|
||||
url = urllib.parse.urlunparse((
|
||||
scheme,
|
||||
host,
|
||||
parse_results.path,
|
||||
parse_results.params,
|
||||
parse_results.query,
|
||||
parse_results.fragment))
|
||||
|
||||
request = urllib.request.Request(url, request_body)
|
||||
if extra_headers is not None:
|
||||
for (name, header) in extra_headers:
|
||||
request.add_header(name, header)
|
||||
request.add_header('Content-Type', 'text/xml')
|
||||
try:
|
||||
response = opener.open(request)
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code == 501:
|
||||
# We may have been redirected through a login process
|
||||
# but our POST turned into a GET. Retry.
|
||||
response = opener.open(request)
|
||||
else:
|
||||
raise
|
||||
|
||||
p, u = xmlrpc.client.getparser()
|
||||
while 1:
|
||||
data = response.read(1024)
|
||||
if not data:
|
||||
break
|
||||
p.feed(data)
|
||||
p.close()
|
||||
return u.close()
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
|
Reference in New Issue
Block a user