Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Unified Diff: checkout.py

Issue 6020010: Destroy svn_utils.py. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/commit-queue
Patch Set: Rebase against trunk and include a fix to import checkout directly Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | svn_utils.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: checkout.py
diff --git a/checkout.py b/checkout.py
index 0ed6050d17dce6db4697187b0dbb0ab9ed332488..8c878db5efea5f696764c6435a08e7ee49807841 100644
--- a/checkout.py
+++ b/checkout.py
@@ -13,9 +13,12 @@ import re
import subprocess
import tempfile
+import find_depot_tools # pylint: disable=W0611
+import gclient_utils
+import scm
+
import patch
import subprocess2
-import svn_utils
def get_code_review_setting(path, key,
@@ -52,7 +55,66 @@ class CheckoutBase(object):
return get_code_review_setting(self.project_path, key)
-class SvnCheckout(CheckoutBase):
+class SvnMixIn(object):
+ """MixIn class to add svn commands common to both svn and git-svn clients."""
+ # These members need to be set by the subclass.
+ commit_user = None
+ commit_pwd = None
+ svn_url = None
+ project_path = None
+
+ def _check_call_svn(self, args, **kwargs):
+ """Runs svn and throws an exception if the command failed."""
+ kwargs.setdefault('cwd', self.project_path)
+ return subprocess2.check_call(
+ ['svn'] + args + ['--no-auth-cache', '--non-interactive'], **kwargs)
+
+ def _capture_svn(self, args, **kwargs):
+ """Runs svn and throws an exception if the command failed.
+
+ Returns the output.
+ """
+ kwargs.setdefault('cwd', self.project_path)
+ if self.commit_user:
+ args = args + [
+ '--username', self.commit_user, '--password', self.commit_pwd]
+ cmd = ['svn'] + args + ['--no-auth-cache', '--non-interactive']
+ return subprocess2.check_capture(cmd, **kwargs)
+
+ @staticmethod
+ def _parse_svn_info(output, key):
+ """Returns value for key from svn info output.
+
+ Case insensitive.
+ """
+ values = {}
+ for line in output.splitlines(False):
+ if not line:
+ continue
+ k, v = line.split(':', 1)
+ k = k.strip().lower()
+ v = v.strip()
+ assert not k in values
+ values[k] = v
+ return values.get(key, None)
+
+ def _update_committer(self, revision, new_author):
+ """Changes the author of a commit a posteriori.
+
+ This is necessary since the actual commit is done with a "commit-bot"
+ credential but the original patch author needs to be assigned authorship
+ of the revision.
+ """
+ self._check_call_svn(
+ ['propset', '--revprop', 'svn:author',
+ '-r', revision,
+ new_author,
+ '--username', self.commit_user,
+ '--password', self.commit_pwd,
+ self.svn_url])
+
+
+class SvnCheckout(CheckoutBase, SvnMixIn):
"""Manages a subversion checkout.
Commit is not fully implemented yet. Reimplementing all the commands is
@@ -73,11 +135,7 @@ class SvnCheckout(CheckoutBase):
# Will checkout if the directory is not present.
logging.info('Checking out %s in %s' %
(self.project_name, self.project_path))
- return svn_utils.revert(
- self.svn_url,
- self.project_path,
- self.commit_user,
- self.commit_pwd)
+ return self._revert()
def apply_patch(self, patch_data):
"""Applies a patch."""
@@ -98,23 +156,65 @@ class SvnCheckout(CheckoutBase):
os.write(handle, commit_message)
os.close(handle)
try:
- output = svn_utils.capture_svn([
- 'commit',
- '--username', self.commit_user,
- '--password', self.commit_pwd,
- '--file', commit_filename],
- cwd=self.project_path)
+ output = self._capture_svn(['commit', '--file', commit_filename])
revision = re.compile(
r'.*?\nCommitted revision (\d+)',
re.DOTALL).match(output).group(1)
# Fix the committer.
- svn_utils.update_committer(
- self.svn_url, revision, self.commit_user, self.commit_pwd, user,
- self.project_path)
+ self._update_committer(revision, user)
finally:
os.remove(commit_filename)
return int(revision)
+ def _revert(self):
+ """Reverts local modifications or checks out if the directory is not
+ present.
+ """
+ flags = ['--ignore-externals']
+ if not os.path.isdir(self.project_path):
+ logging.info('Directory %s is not present, checking it out.' %
+ self.project_path)
+ self._check_call_svn(['checkout', self.svn_url, self.project_path] +
+ flags, cwd=None)
+ else:
+ for file_status in scm.SVN.CaptureStatus(self.project_path):
+ file_path = os.path.join(self.project_path, file_status[1])
+ if file_status[0][0] == 'X':
+ # Ignore externals.
+ logging.info('Ignoring external %s' % file_path)
+ continue
+
+ logging.info('%s%s' % (file_status[0], file_status[1]))
+
+ if file_status[0].isspace():
+ raise EnvironmentError(
+ 'No idea what is the status of %s.\n'
+ 'You just found a bug in gclient, please ping '
+ 'maruel@chromium.org ASAP!' % file_path)
+
+ # svn revert is really stupid. It fails on inconsistent line-endings,
+ # on switched directories, etc. So take no chance and delete everything!
+ try:
+ if not os.path.exists(file_path):
+ pass
+ elif os.path.isfile(file_path) or os.path.islink(file_path):
+ logging.info('os.remove(%s)' % file_path)
+ os.remove(file_path)
+ elif os.path.isdir(file_path):
+ logging.info('gclient_utils.RemoveDirectory(%s)' % file_path)
+ gclient_utils.RemoveDirectory(file_path)
+ else:
+ logging.error('no idea what is %s.\nYou just found a bug in gclient'
+ ', please ping maruel@chromium.org ASAP!' % file_path)
+ except EnvironmentError:
+ logging.error('Failed to remove %s.' % file_path)
+
+ # Revive files that were deleted above.
+ self._check_call_svn(['update', '--force'] + flags)
+
+ out = self._capture_svn(['info', '.'])
+ return int(self._parse_svn_info(out, 'revision'))
+
class GitCheckoutBase(CheckoutBase):
"""Base class for git checkout. Not to be used as-is."""
@@ -157,18 +257,19 @@ class GitCheckoutBase(CheckoutBase):
return subprocess2.check_capture(['git'] + args, **kwargs)
-class GitSvnCheckoutBase(GitCheckoutBase):
+class GitSvnCheckoutBase(GitCheckoutBase, SvnMixIn):
"""Base class for git-svn checkout. Not to be used as-is."""
def __init__(self,
root_dir, project_name, remote_branch,
commit_user, commit_pwd,
- svn_repo, trunk):
+ svn_url, trunk):
"""trunk is optional."""
super(GitSvnCheckoutBase, self).__init__(
root_dir, project_name + '.git', remote_branch)
self.commit_user = commit_user
self.commit_pwd = commit_pwd
- self.svn_repo = svn_repo
+ # svn_url in this case is the root of the svn repository.
+ self.svn_url = svn_url
self.trunk = trunk
def prepare(self):
@@ -179,7 +280,7 @@ class GitSvnCheckoutBase(GitCheckoutBase):
return int(self._git_svn_info('revision'))
def _git_svn_info(self, key):
- return svn_utils.parse_svn_info(
+ return self._parse_svn_info(
self._check_capture_git(['svn', 'info']), key)
def commit(self, commit_message, user):
@@ -192,9 +293,7 @@ class GitSvnCheckoutBase(GitCheckoutBase):
self._check_call_git_svn(['dcommit', '--rmdir', '--find-copies-harder'])
revision = int(self._git_svn_info('revision'))
# Fix the committer.
- svn_utils.update_committer(
- self.svn_repo, revision, self.commit_user, self.commit_pwd, user,
- self.project_path)
+ self._update_committer(revision, user)
return revision
def _cache_svn_auth(self):
@@ -204,7 +303,7 @@ class GitSvnCheckoutBase(GitCheckoutBase):
return
logging.info('Caching svn credentials for %s' % self.commit_user)
subprocess2.check_call(
- ['svn', 'ls', self.svn_repo,
+ ['svn', 'ls', self.svn_url,
'--username', self.commit_user,
'--password', self.commit_pwd,
'--non-interactive'])
@@ -226,11 +325,11 @@ class GitSvnPremadeCheckout(GitSvnCheckoutBase):
def __init__(self,
root_dir, project_name, remote_branch,
commit_user, commit_pwd,
- svn_repo, trunk, git_url):
+ svn_url, trunk, git_url):
super(GitSvnPremadeCheckout, self).__init__(
root_dir, project_name, remote_branch,
commit_user, commit_pwd,
- svn_repo, trunk)
+ svn_url, trunk)
self.git_url = git_url
def prepare(self):
@@ -246,7 +345,7 @@ class GitSvnPremadeCheckout(GitSvnCheckoutBase):
['svn', 'init',
'--prefix', self.remote + '/',
'-T', self.trunk,
- self.svn_repo])
+ self.svn_url])
self._check_call_git_svn(['fetch'])
super(GitSvnPremadeCheckout, self).prepare()
return int(self._git_svn_info('revision'))
@@ -260,11 +359,11 @@ class GitSvnCheckout(GitSvnCheckoutBase):
def __init__(self,
root_dir, project_name,
commit_user, commit_pwd,
- svn_repo, trunk):
+ svn_url, trunk):
super(GitSvnCheckout, self).__init__(
root_dir, project_name, 'trunk',
commit_user, commit_pwd,
- svn_repo, trunk)
+ svn_url, trunk)
def prepare(self):
"""Creates the initial checkout for the repo."""
@@ -276,7 +375,7 @@ class GitSvnCheckout(GitSvnCheckoutBase):
['clone',
'--prefix', self.remote + '/',
'-T', self.trunk,
- self.svn_repo, self.project_path],
+ self.svn_url, self.project_path],
cwd=self.root_dir)
super(GitSvnCheckout, self).prepare()
return int(self._git_svn_info('revision'))
« no previous file with comments | « no previous file | svn_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698