Strip netrc hack, rewrite file.
Strip the netrc hack; apparently it only works on some versions of
Python, and the bots have many different versions.
Instead, we will actually emit the modified netrc as a new file without
comments or newlines, then read that directly from the vanilla netrc
module.
BUG=chromium:664664
TEST=None
Change-Id: I245759e2eae4e6ddcdffa0aaef59866a62bd0240
Reviewed-on: https://chromium-review.googlesource.com/411416
Commit-Queue: Daniel Jacques <dnj@chromium.org>
Reviewed-by: Ryan Tseng <hinoka@chromium.org>
Reviewed-by: Michael Moss <mmoss@chromium.org>
diff --git a/gerrit_util.py b/gerrit_util.py
index ff37858..eff98e3 100755
--- a/gerrit_util.py
+++ b/gerrit_util.py
@@ -9,6 +9,7 @@
"""
import base64
+import contextlib
import cookielib
import httplib
import json
@@ -16,14 +17,17 @@
import netrc
import os
import re
+import shutil
import socket
import stat
import sys
+import tempfile
import time
import urllib
import urlparse
from cStringIO import StringIO
+import gclient_utils
LOGGER = logging.getLogger()
TRY_LIMIT = 5
@@ -34,21 +38,6 @@
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):
"""Exception class for errors commuicating with the gerrit-on-borg service."""
@@ -129,27 +118,41 @@
@classmethod
def _get_netrc(cls):
+ # Buffer the '.netrc' path. Use an empty file if it doesn't exist.
path = cls.get_netrc_path()
- if not os.path.exists(path):
- return safeNetrc(os.devnull)
-
- try:
- return safeNetrc(path)
- except IOError:
- print >> sys.stderr, 'WARNING: Could not read netrc file %s' % path
- return safeNetrc(os.devnull)
- except netrc.NetrcParseError:
+ content = ''
+ if os.path.exists(path):
st = os.stat(path)
if st.st_mode & (stat.S_IRWXG | stat.S_IRWXO):
print >> sys.stderr, (
'WARNING: netrc file %s cannot be used because its file '
'permissions are insecure. netrc file permissions should be '
'600.' % path)
- else:
- print >> sys.stderr, ('ERROR: Cannot use netrc file %s due to a '
- 'parsing error.' % path)
- raise
- return safeNetrc(os.devnull)
+ with open(path) as fd:
+ content = fd.read()
+
+ # Load the '.netrc' file. We strip comments from it because processing them
+ # 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
def get_gitcookies_path(cls):
@@ -749,3 +752,14 @@
elif jmsg[0]['current_revision'] != revision:
raise GerritError(200, 'While resetting labels on change "%s", '
'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)