@ -9,6 +9,7 @@ https://gerrit-review.googlesource.com/Documentation/rest-api.html
"""
"""
import base64
import base64
import contextlib
import cookielib
import cookielib
import httplib
import httplib
import json
import json
@ -16,14 +17,17 @@ import logging
import netrc
import netrc
import os
import os
import re
import re
import shutil
import socket
import socket
import stat
import stat
import sys
import sys
import tempfile
import time
import time
import urllib
import urllib
import urlparse
import urlparse
from cStringIO import StringIO
from cStringIO import StringIO
import gclient_utils
LOGGER = logging . getLogger ( )
LOGGER = logging . getLogger ( )
TRY_LIMIT = 5
TRY_LIMIT = 5
@ -34,21 +38,6 @@ TRY_LIMIT = 5
GERRIT_PROTOCOL = ' https '
GERRIT_PROTOCOL = ' https '
# Processing comments in "netrc" can trigger a bug in Windows.
# See crbug.com/664664
class safeNetrc ( netrc . netrc ) :
# pylint: disable=redefined-builtin
def __init__ ( self , file = None ) :
self . _orig_parse , self . _parse = self . _parse , self . _safe_parse
netrc . netrc . __init__ ( self , file = file )
# pylint: disable=redefined-builtin
def _safe_parse ( self , file , fp , default_netrc ) :
# Buffer the file.
sio = StringIO ( ' ' . join ( l for l in fp
if l . strip ( ) and not l . strip ( ) . startswith ( ' # ' ) ) )
return self . _orig_parse ( file , sio , default_netrc )
class GerritError ( Exception ) :
class GerritError ( Exception ) :
""" Exception class for errors commuicating with the gerrit-on-borg service. """
""" Exception class for errors commuicating with the gerrit-on-borg service. """
@ -129,27 +118,41 @@ class CookiesAuthenticator(Authenticator):
@classmethod
@classmethod
def _get_netrc ( cls ) :
def _get_netrc ( cls ) :
# Buffer the '.netrc' path. Use an empty file if it doesn't exist.
path = cls . get_netrc_path ( )
path = cls . get_netrc_path ( )
if not os . path . exists ( path ) :
content = ' '
return safeNetrc ( os . devnull )
if os . path . exists ( path ) :
try :
return safeNetrc ( path )
except IOError :
print >> sys . stderr , ' WARNING: Could not read netrc file %s ' % path
return safeNetrc ( os . devnull )
except netrc . NetrcParseError :
st = os . stat ( path )
st = os . stat ( path )
if st . st_mode & ( stat . S_IRWXG | stat . S_IRWXO ) :
if st . st_mode & ( stat . S_IRWXG | stat . S_IRWXO ) :
print >> sys . stderr , (
print >> sys . stderr , (
' WARNING: netrc file %s cannot be used because its file '
' WARNING: netrc file %s cannot be used because its file '
' permissions are insecure. netrc file permissions should be '
' permissions are insecure. netrc file permissions should be '
' 600. ' % path )
' 600. ' % path )
else :
with open ( path ) as fd :
print >> sys . stderr , ( ' ERROR: Cannot use netrc file %s due to a '
content = fd . read ( )
' parsing error. ' % path )
raise
# Load the '.netrc' file. We strip comments from it because processing them
return safeNetrc ( os . devnull )
# can trigger a bug in Windows. See crbug.com/664664.
content = ' \n ' . join ( l for l in content . splitlines ( )
if l . strip ( ) and not l . strip ( ) . startswith ( ' # ' ) )
with tempdir ( ) as tdir :
netrc_path = os . path . join ( tdir , ' netrc ' )
with open ( netrc_path , ' w ' ) as fd :
fd . write ( content )
os . chmod ( netrc_path , ( stat . S_IRUSR | stat . S_IWUSR ) )
return cls . _get_netrc_from_path ( netrc_path )
@classmethod
def _get_netrc_from_path ( cls , path ) :
try :
return netrc . netrc ( path )
except IOError :
print >> sys . stderr , ' WARNING: Could not read netrc file %s ' % path
return netrc . netrc ( os . devnull )
except netrc . NetrcParseError as e :
print >> sys . stderr , ( ' ERROR: Cannot use netrc file %s due to a '
' parsing error: %s ' % ( path , e ) )
return netrc . netrc ( os . devnull )
@classmethod
@classmethod
def get_gitcookies_path ( cls ) :
def get_gitcookies_path ( cls ) :
@ -749,3 +752,14 @@ def ResetReviewLabels(host, change, label, value='0', message=None,
elif jmsg [ 0 ] [ ' current_revision ' ] != revision :
elif jmsg [ 0 ] [ ' current_revision ' ] != revision :
raise GerritError ( 200 , ' While resetting labels on change " %s " , '
raise GerritError ( 200 , ' While resetting labels on change " %s " , '
' a new patchset was uploaded. ' % change )
' a new patchset was uploaded. ' % change )
@contextlib.contextmanager
def tempdir ( ) :
tdir = None
try :
tdir = tempfile . mkdtemp ( suffix = ' gerrit_util ' )
yield tdir
finally :
if tdir :
gclient_utils . rmtree ( tdir )