| Index: trychange_git.py
|
| diff --git a/trychange.py b/trychange_git.py
|
| similarity index 66%
|
| copy from trychange.py
|
| copy to trychange_git.py
|
| index 719275a12c9e355a44654ec3e90c06a7d0b58731..8b02aaa48fe1affff267a57f1bede0d62e927947 100755
|
| --- a/trychange.py
|
| +++ b/trychange_git.py
|
| @@ -26,12 +26,8 @@ import urllib
|
| import urllib2
|
| import urlparse
|
|
|
| -import breakpad # pylint: disable=W0611
|
| -
|
| -import fix_encoding
|
| -import gcl
|
| import gclient_utils
|
| -import gerrit_util
|
| +import git_cl
|
| import scm
|
| import subprocess2
|
|
|
| @@ -44,8 +40,7 @@ HELP_STRING = "Sorry, Tryserver is not available."
|
| USAGE = r"""%prog [options]
|
|
|
| Client-side script to send a try job to the try server. It communicates to
|
| -the try server by either writting to a svn repository or by directly connecting
|
| -to the server by HTTP."""
|
| +the try server by writting to a svn repository."""
|
|
|
| EPILOG = """
|
| Examples:
|
| @@ -75,7 +70,7 @@ Examples:
|
|
|
| GIT_PATCH_DIR_BASENAME = os.path.join('git-try', 'patches-git')
|
| GIT_BRANCH_FILE = 'ref'
|
| -_GIT_PUSH_ATTEMPTS = 3
|
| +
|
|
|
| def DieWithError(message):
|
| print >> sys.stderr, message
|
| @@ -97,21 +92,19 @@ def RunGit(args, **kwargs):
|
| """Returns stdout."""
|
| return RunCommand(['git'] + args, **kwargs)
|
|
|
| +
|
| class Error(Exception):
|
| """An error during a try job submission.
|
|
|
| For this error, trychange.py does not display stack trace, only message
|
| """
|
|
|
| -class InvalidScript(Error):
|
| - def __str__(self):
|
| - return self.args[0] + '\n' + HELP_STRING
|
| -
|
|
|
| class NoTryServerAccess(Error):
|
| def __str__(self):
|
| return self.args[0] + '\n' + HELP_STRING
|
|
|
| +
|
| def Escape(name):
|
| """Escapes characters that could interfere with the file system or try job
|
| parsing.
|
| @@ -119,8 +112,9 @@ def Escape(name):
|
| return re.sub(r'[^\w#-]', '_', name)
|
|
|
|
|
| -class SCM(object):
|
| - """Simplistic base class to implement one function: ProcessOptions."""
|
| +class GIT(object):
|
| +
|
| + """Gathers the options and diff for a git checkout."""
|
| def __init__(self, options, path, file_list):
|
| items = path.split('@')
|
| assert len(items) <= 2
|
| @@ -138,20 +132,21 @@ class SCM(object):
|
| self.codereview_settings = None
|
| self.codereview_settings_file = 'codereview.settings'
|
| self.toplevel_root = None
|
| -
|
| - def GetFileNames(self):
|
| - """Return the list of files in the diff."""
|
| - return self.files
|
| + self.checkout_root = scm.GIT.GetCheckoutRoot(self.checkout_root)
|
| + if not self.options.name:
|
| + self.options.name = scm.GIT.GetPatchName(self.checkout_root)
|
| + if not self.options.email:
|
| + self.options.email = scm.GIT.GetEmail(self.checkout_root)
|
| + if not self.diff_against:
|
| + self.diff_against = scm.GIT.GetUpstreamBranch(self.checkout_root)
|
| + if not self.diff_against:
|
| + raise NoTryServerAccess(
|
| + "Unable to determine default branch to diff against. "
|
| + "Verify this branch is set up to track another"
|
| + "(via the --track argument to \"git checkout -b ...\"")
|
| + logging.info("GIT(%s)" % self.checkout_root)
|
|
|
| def GetCodeReviewSetting(self, key):
|
| - """Returns a value for the given key for this repository.
|
| -
|
| - Uses gcl-style settings from the repository.
|
| - """
|
| - if gcl:
|
| - gcl_setting = gcl.GetCodeReviewSetting(key)
|
| - if gcl_setting != '':
|
| - return gcl_setting
|
| if self.codereview_settings is None:
|
| self.codereview_settings = {}
|
| settings_file = self.ReadRootFile(self.codereview_settings_file)
|
| @@ -171,11 +166,7 @@ class SCM(object):
|
| settings in codereview.settings).
|
| """
|
| settings = {
|
| - 'port': self.GetCodeReviewSetting('TRYSERVER_HTTP_PORT'),
|
| - 'host': self.GetCodeReviewSetting('TRYSERVER_HTTP_HOST'),
|
| 'svn_repo': self.GetCodeReviewSetting('TRYSERVER_SVN_URL'),
|
| - 'gerrit_url': self.GetCodeReviewSetting('TRYSERVER_GERRIT_URL'),
|
| - 'git_repo': self.GetCodeReviewSetting('TRYSERVER_GIT_URL'),
|
| 'project': self.GetCodeReviewSetting('TRYSERVER_PROJECT'),
|
| # Primarily for revision=auto
|
| 'revision': self.GetCodeReviewSetting('TRYSERVER_REVISION'),
|
| @@ -244,12 +235,6 @@ class SCM(object):
|
| self._file_tuples = [f for f in file_tuples if not Excluded(f)]
|
| self._files = [f[1] for f in self._file_tuples]
|
|
|
| - def CaptureStatus(self):
|
| - """Returns the 'svn status' emulated output as an array of (status, file)
|
| - tuples."""
|
| - raise NotImplementedError(
|
| - "abstract method -- subclass %s must override" % self.__class__)
|
| -
|
| @property
|
| def files(self):
|
| if self._files is None:
|
| @@ -262,60 +247,6 @@ class SCM(object):
|
| self._SetFileTuples(self.CaptureStatus())
|
| return self._file_tuples
|
|
|
| -
|
| -class SVN(SCM):
|
| - """Gathers the options and diff for a subversion checkout."""
|
| - def __init__(self, *args, **kwargs):
|
| - SCM.__init__(self, *args, **kwargs)
|
| - self.checkout_root = scm.SVN.GetCheckoutRoot(self.checkout_root)
|
| - if not self.options.email:
|
| - # Assumes the svn credential is an email address.
|
| - self.options.email = scm.SVN.GetEmail(self.checkout_root)
|
| - logging.info("SVN(%s)" % self.checkout_root)
|
| -
|
| - def ReadRootFile(self, filename):
|
| - data = SCM.ReadRootFile(self, filename)
|
| - if data:
|
| - return data
|
| -
|
| - # Try to search on the subversion repository for the file.
|
| - if not gcl:
|
| - return None
|
| - data = gcl.GetCachedFile(filename)
|
| - logging.debug('%s:\n%s' % (filename, data))
|
| - return data
|
| -
|
| - def CaptureStatus(self):
|
| - return scm.SVN.CaptureStatus(None, self.checkout_root)
|
| -
|
| - def GenerateDiff(self):
|
| - """Returns a string containing the diff for the given file list.
|
| -
|
| - The files in the list should either be absolute paths or relative to the
|
| - given root.
|
| - """
|
| - return scm.SVN.GenerateDiff(self.files, self.checkout_root, full_move=True,
|
| - revision=self.diff_against)
|
| -
|
| -
|
| -class GIT(SCM):
|
| - """Gathers the options and diff for a git checkout."""
|
| - def __init__(self, *args, **kwargs):
|
| - SCM.__init__(self, *args, **kwargs)
|
| - self.checkout_root = scm.GIT.GetCheckoutRoot(self.checkout_root)
|
| - if not self.options.name:
|
| - self.options.name = scm.GIT.GetPatchName(self.checkout_root)
|
| - if not self.options.email:
|
| - self.options.email = scm.GIT.GetEmail(self.checkout_root)
|
| - if not self.diff_against:
|
| - self.diff_against = scm.GIT.GetUpstreamBranch(self.checkout_root)
|
| - if not self.diff_against:
|
| - raise NoTryServerAccess(
|
| - "Unable to determine default branch to diff against. "
|
| - "Verify this branch is set up to track another"
|
| - "(via the --track argument to \"git checkout -b ...\"")
|
| - logging.info("GIT(%s)" % self.checkout_root)
|
| -
|
| def CaptureStatus(self):
|
| return scm.GIT.CaptureStatus(
|
| [],
|
| @@ -392,7 +323,7 @@ def _GenTSBotSpec(checkouts, change, changed_files, options):
|
| options.email)
|
| masters = presubmit_support.DoGetTryMasters(
|
| change,
|
| - checkouts[0].GetFileNames(),
|
| + checkouts[0].files,
|
| checkouts[0].checkout_root,
|
| root_presubmit,
|
| options.project,
|
| @@ -458,48 +389,6 @@ def _ParseSendChangeOptions(bot_spec, options):
|
| return values
|
|
|
|
|
| -def _SendChangeHTTP(bot_spec, options):
|
| - """Send a change to the try server using the HTTP protocol."""
|
| - if not options.host:
|
| - raise NoTryServerAccess('Please use the --host option to specify the try '
|
| - 'server host to connect to.')
|
| - if not options.port:
|
| - raise NoTryServerAccess('Please use the --port option to specify the try '
|
| - 'server port to connect to.')
|
| -
|
| - values = _ParseSendChangeOptions(bot_spec, options)
|
| - values.append(('patch', options.diff))
|
| -
|
| - url = 'http://%s:%s/send_try_patch' % (options.host, options.port)
|
| -
|
| - logging.info('Sending by HTTP')
|
| - logging.info(''.join("%s=%s\n" % (k, v) for k, v in values))
|
| - logging.info(url)
|
| - logging.info(options.diff)
|
| - if options.dry_run:
|
| - return
|
| -
|
| - try:
|
| - logging.info('Opening connection...')
|
| - connection = urllib2.urlopen(url, urllib.urlencode(values))
|
| - logging.info('Done')
|
| - except IOError, e:
|
| - logging.info(str(e))
|
| - if bot_spec and len(e.args) > 2 and e.args[2] == 'got a bad status line':
|
| - raise NoTryServerAccess('%s is unaccessible. Bad --bot argument?' % url)
|
| - else:
|
| - raise NoTryServerAccess('%s is unaccessible. Reason: %s' % (url,
|
| - str(e.args)))
|
| - if not connection:
|
| - raise NoTryServerAccess('%s is unaccessible.' % url)
|
| - logging.info('Reading response...')
|
| - response = connection.read()
|
| - logging.info('Done')
|
| - if response != 'OK':
|
| - raise NoTryServerAccess('%s is unaccessible. Got:\n%s' % (url, response))
|
| -
|
| - PrintSuccess(bot_spec, options)
|
| -
|
| @contextlib.contextmanager
|
| def _TempFilename(name, contents=None):
|
| """Create a temporary directory, append the specified name and yield.
|
| @@ -578,6 +467,7 @@ def _SendChangeSVN(bot_spec, options):
|
|
|
| PrintSuccess(bot_spec, options)
|
|
|
| +
|
| def _GetPatchGitRepo(git_url):
|
| """Gets a path to a Git repo with patches.
|
|
|
| @@ -619,187 +509,6 @@ def _GetPatchGitRepo(git_url):
|
| return os.path.abspath(patch_dir)
|
|
|
|
|
| -def _SendChangeGit(bot_spec, options):
|
| - """Sends a change to the try server by committing a diff file to a GIT repo.
|
| -
|
| - Creates a temp orphan branch, commits patch.diff, creates a ref pointing to
|
| - that commit, deletes the temp branch, checks master out, adds 'ref' file
|
| - containing the name of the new ref, pushes master and the ref to the origin.
|
| -
|
| - TODO: instead of creating a temp branch, use git-commit-tree.
|
| - """
|
| -
|
| - if not options.git_repo:
|
| - raise NoTryServerAccess('Please use the --git_repo option to specify the '
|
| - 'try server git repository to connect to.')
|
| -
|
| - values = _ParseSendChangeOptions(bot_spec, options)
|
| - comment_subject = '%s.%s' % (options.user, options.name)
|
| - comment_body = ''.join("%s=%s\n" % (k, v) for k, v in values)
|
| - description = '%s\n\n%s' % (comment_subject, comment_body)
|
| - logging.info('Sending by GIT')
|
| - logging.info(description)
|
| - logging.info(options.git_repo)
|
| - logging.info(options.diff)
|
| - if options.dry_run:
|
| - return
|
| -
|
| - patch_dir = _GetPatchGitRepo(options.git_repo)
|
| - def patch_git(*args):
|
| - return scm.GIT.Capture(list(args), cwd=patch_dir)
|
| - def add_and_commit(filename, comment_filename):
|
| - patch_git('add', filename)
|
| - patch_git('commit', '-F', comment_filename)
|
| -
|
| - assert scm.GIT.IsInsideWorkTree(patch_dir)
|
| - assert not scm.GIT.IsWorkTreeDirty(patch_dir)
|
| -
|
| - with _PrepareDescriptionAndPatchFiles(description, options) as (
|
| - patch_filename, description_filename):
|
| - logging.info('Committing patch')
|
| -
|
| - temp_branch = 'tmp_patch'
|
| - target_ref = 'refs/patches/%s/%s' % (
|
| - Escape(options.user),
|
| - os.path.basename(patch_filename).replace(' ','_'))
|
| - target_filename = os.path.join(patch_dir, 'patch.diff')
|
| - branch_file = os.path.join(patch_dir, GIT_BRANCH_FILE)
|
| -
|
| - patch_git('checkout', 'master')
|
| - try:
|
| - # Try deleting an existing temp branch, if any.
|
| - try:
|
| - patch_git('branch', '-D', temp_branch)
|
| - logging.debug('Deleted an existing temp branch.')
|
| - except subprocess2.CalledProcessError:
|
| - pass
|
| - # Create a new branch and put the patch there.
|
| - patch_git('checkout', '--orphan', temp_branch)
|
| - patch_git('reset')
|
| - patch_git('clean', '-f')
|
| - shutil.copyfile(patch_filename, target_filename)
|
| - add_and_commit(target_filename, description_filename)
|
| - assert not scm.GIT.IsWorkTreeDirty(patch_dir)
|
| -
|
| - # Create a ref and point it to the commit referenced by temp_branch.
|
| - patch_git('update-ref', target_ref, temp_branch)
|
| -
|
| - # Delete the temp ref.
|
| - patch_git('checkout', 'master')
|
| - patch_git('branch', '-D', temp_branch)
|
| -
|
| - # Update the branch file in the master.
|
| - def update_branch():
|
| - with open(branch_file, 'w') as f:
|
| - f.write(target_ref)
|
| - add_and_commit(branch_file, description_filename)
|
| -
|
| - update_branch()
|
| -
|
| - # Push master and target_ref to origin.
|
| - logging.info('Pushing patch')
|
| - for attempt in xrange(_GIT_PUSH_ATTEMPTS):
|
| - try:
|
| - patch_git('push', 'origin', 'master', target_ref)
|
| - except subprocess2.CalledProcessError as e:
|
| - is_last = attempt == _GIT_PUSH_ATTEMPTS - 1
|
| - if is_last:
|
| - raise NoTryServerAccess(str(e))
|
| - # Fetch, reset, update branch file again.
|
| - patch_git('fetch', 'origin')
|
| - patch_git('reset', '--hard', 'origin/master')
|
| - update_branch()
|
| - except subprocess2.CalledProcessError, e:
|
| - # Restore state.
|
| - patch_git('checkout', 'master')
|
| - patch_git('reset', '--hard', 'origin/master')
|
| - raise
|
| -
|
| - PrintSuccess(bot_spec, options)
|
| -
|
| -def _SendChangeGerrit(bot_spec, options):
|
| - """Posts a try job to a Gerrit change.
|
| -
|
| - Reads Change-Id from the HEAD commit, resolves the current revision, checks
|
| - that local revision matches the uploaded one, posts a try job in form of a
|
| - message, sets Tryjob-Request label to 1.
|
| -
|
| - Gerrit message format: starts with !tryjob, optionally followed by a tryjob
|
| - definition in JSON format:
|
| - buildNames: list of strings specifying build names.
|
| - """
|
| -
|
| - logging.info('Sending by Gerrit')
|
| - if not options.gerrit_url:
|
| - raise NoTryServerAccess('Please use --gerrit_url option to specify the '
|
| - 'Gerrit instance url to connect to')
|
| - gerrit_host = urlparse.urlparse(options.gerrit_url).hostname
|
| - logging.debug('Gerrit host: %s' % gerrit_host)
|
| -
|
| - def GetChangeId(commmitish):
|
| - """Finds Change-ID of the HEAD commit."""
|
| - CHANGE_ID_RGX = '^Change-Id: (I[a-f0-9]{10,})'
|
| - comment = scm.GIT.Capture(['log', '-1', commmitish, '--format=%b'],
|
| - cwd=os.getcwd())
|
| - change_id_match = re.search(CHANGE_ID_RGX, comment, re.I | re.M)
|
| - if not change_id_match:
|
| - raise Error('Change-Id was not found in the HEAD commit. Make sure you '
|
| - 'have a Git hook installed that generates and inserts a '
|
| - 'Change-Id into a commit message automatically.')
|
| - change_id = change_id_match.group(1)
|
| - return change_id
|
| -
|
| - def FormatMessage():
|
| - # Build job definition.
|
| - job_def = {}
|
| - builderNames = [builder for builder, _ in bot_spec]
|
| - if builderNames:
|
| - job_def['builderNames'] = builderNames
|
| -
|
| - # Format message.
|
| - msg = '!tryjob'
|
| - if job_def:
|
| - msg = '%s %s' % (msg, json.dumps(job_def, sort_keys=True))
|
| - return msg
|
| -
|
| - def PostTryjob(message):
|
| - logging.info('Posting gerrit message: %s' % message)
|
| - if not options.dry_run:
|
| - # Post a message and set TryJob=1 label.
|
| - try:
|
| - gerrit_util.SetReview(gerrit_host, change_id, msg=message,
|
| - labels={'Tryjob-Request': 1})
|
| - except gerrit_util.GerritError, e:
|
| - if e.http_status == 400:
|
| - raise Error(e.message)
|
| - else:
|
| - raise
|
| -
|
| - head_sha = scm.GIT.Capture(['log', '-1', '--format=%H'], cwd=os.getcwd())
|
| -
|
| - change_id = GetChangeId(head_sha)
|
| -
|
| - try:
|
| - # Check that the uploaded revision matches the local one.
|
| - changes = gerrit_util.GetChangeCurrentRevision(gerrit_host, change_id)
|
| - except gerrit_util.GerritAuthenticationError, e:
|
| - raise NoTryServerAccess(e.message)
|
| -
|
| - assert len(changes) <= 1, 'Multiple changes with id %s' % change_id
|
| - if not changes:
|
| - raise Error('A change %s was not found on the server. Was it uploaded?' %
|
| - change_id)
|
| - logging.debug('Found Gerrit change: %s' % changes[0])
|
| - if changes[0]['current_revision'] != head_sha:
|
| - raise Error('Please upload your latest local changes to Gerrit.')
|
| -
|
| - # Post a try job.
|
| - message = FormatMessage()
|
| - PostTryjob(message)
|
| - change_url = urlparse.urljoin(options.gerrit_url,
|
| - '/#/c/%s' % changes[0]['_number'])
|
| - print('A tryjob was posted on change %s' % change_url)
|
| -
|
| def PrintSuccess(bot_spec, options):
|
| if not options.dry_run:
|
| text = 'Patch \'%s\' sent to try server' % options.name
|
| @@ -809,25 +518,15 @@ def PrintSuccess(bot_spec, options):
|
| print(text)
|
|
|
|
|
| -def GuessVCS(options, path, file_list):
|
| - """Helper to guess the version control system.
|
| -
|
| - NOTE: Very similar to upload.GuessVCS. Doesn't look for hg since we don't
|
| - support it yet.
|
| -
|
| - This examines the path directory, guesses which SCM we're using, and
|
| - returns an instance of the appropriate class. Exit with an error if we can't
|
| - figure it out.
|
| +def DetectGit(options, path, file_list):
|
| + """Instantiates the GIT class if a git repo is detected.
|
|
|
| Returns:
|
| - A SCM instance. Exits if the SCM can't be guessed.
|
| + A GIT instance. None if repo not found.
|
| """
|
| __pychecker__ = 'no-returnvalues'
|
| real_path = path.split('@')[0]
|
| - logging.info("GuessVCS(%s)" % path)
|
| - # Subversion has a .svn in all working directories.
|
| - if os.path.isdir(os.path.join(real_path, '.svn')):
|
| - return SVN(options, path, file_list)
|
| + logging.info("DetectGit(%s)" % path)
|
|
|
| # Git has a command to test if you're in a git tree.
|
| # Try running it, but don't die if we don't have git installed.
|
| @@ -845,9 +544,7 @@ def GuessVCS(options, path, file_list):
|
| # 128 = git error code when not in a repo.
|
| logging.warning('Unexpected error code: %s' % e.returncode)
|
| raise
|
| - raise NoTryServerAccess(
|
| - ( 'Could not guess version control system for %s.\n'
|
| - 'Are you in a working copy directory?') % path)
|
| + return None
|
|
|
|
|
| def GetMungedDiff(path_diff, diff):
|
| @@ -978,59 +675,17 @@ def gen_parser(prog):
|
| "main checkout")
|
| parser.add_option_group(group)
|
|
|
| - group = optparse.OptionGroup(parser, "Access the try server by HTTP")
|
| - group.add_option("--use_http",
|
| - action="store_const",
|
| - const=_SendChangeHTTP,
|
| - dest="send_patch",
|
| - help="Use HTTP to talk to the try server [default]")
|
| - group.add_option("-H", "--host",
|
| - help="Host address")
|
| - group.add_option("-P", "--port", type="int",
|
| - help="HTTP port")
|
| - parser.add_option_group(group)
|
| -
|
| group = optparse.OptionGroup(parser, "Access the try server with SVN")
|
| - group.add_option("--use_svn",
|
| - action="store_const",
|
| - const=_SendChangeSVN,
|
| - dest="send_patch",
|
| - help="Use SVN to talk to the try server")
|
| group.add_option("-S", "--svn_repo",
|
| metavar="SVN_URL",
|
| help="SVN url to use to write the changes in; --use_svn is "
|
| "implied when using --svn_repo")
|
| parser.add_option_group(group)
|
|
|
| - group = optparse.OptionGroup(parser, "Access the try server with Git")
|
| - group.add_option("--use_git",
|
| - action="store_const",
|
| - const=_SendChangeGit,
|
| - dest="send_patch",
|
| - help="Use GIT to talk to the try server")
|
| - group.add_option("-G", "--git_repo",
|
| - metavar="GIT_URL",
|
| - help="GIT url to use to write the changes in; --use_git is "
|
| - "implied when using --git_repo")
|
| - parser.add_option_group(group)
|
| -
|
| - group = optparse.OptionGroup(parser, "Access the try server with Gerrit")
|
| - group.add_option("--use_gerrit",
|
| - action="store_const",
|
| - const=_SendChangeGerrit,
|
| - dest="send_patch",
|
| - help="Use Gerrit to talk to the try server")
|
| - group.add_option("--gerrit_url",
|
| - metavar="GERRIT_URL",
|
| - help="Gerrit url to post a tryjob to; --use_gerrit is "
|
| - "implied when using --gerrit_url")
|
| - parser.add_option_group(group)
|
| -
|
| return parser
|
|
|
|
|
| -def TryChange(argv,
|
| - change,
|
| +def TryChange_Git(argv,
|
| swallow_exception,
|
| prog=None,
|
| extra_epilog=None):
|
| @@ -1099,7 +754,10 @@ def TryChange(argv,
|
| file_list = []
|
| if options.files:
|
| file_list = options.files
|
| - elif change:
|
| + elif (not options.email or not options.diff or not options.revision
|
| + or options.revision.lower() == 'auto'):
|
| + changelist = git_cl.Changelist()
|
| + change = changelist.GetChange(changelist.GetUpstreamBranch(), None)
|
| file_list = [f.LocalPath() for f in change.AffectedFiles()]
|
|
|
| if options.upstream_branch:
|
| @@ -1108,43 +766,32 @@ def TryChange(argv,
|
| # upstream branch.
|
| file_list = []
|
|
|
| - current_vcs = GuessVCS(options, path, file_list)
|
| - current_vcs.AutomagicalSettings()
|
| - options = current_vcs.options
|
| - vcs_is_git = type(current_vcs) is GIT
|
| -
|
| - # So far, git_repo doesn't work with SVN
|
| - if options.git_repo and not vcs_is_git:
|
| - parser.error('--git_repo option is supported only for GIT repositories')
|
| + detected_git = DetectGit(options, path, file_list)
|
| + if detected_git:
|
| + detected_git.AutomagicalSettings()
|
| + options = detected_git.options
|
|
|
| # If revision==auto, resolve it
|
| if options.revision and options.revision.lower() == 'auto':
|
| - if not vcs_is_git:
|
| - parser.error('--revision=auto is supported only for GIT repositories')
|
| options.revision = scm.GIT.Capture(
|
| - ['rev-parse', current_vcs.diff_against],
|
| + ['rev-parse', detected_git.diff_against],
|
| cwd=path)
|
|
|
| - checkouts = [current_vcs]
|
| + checkouts = []
|
| + if detected_git:
|
| + checkouts.append(detected_git)
|
| for item in options.sub_rep:
|
| # Pass file_list=None because we don't know the sub repo's file list.
|
| - checkout = GuessVCS(options,
|
| - os.path.join(current_vcs.checkout_root, item),
|
| + checkout = DetectGit(options,
|
| + os.path.join(detected_git.checkout_root, item),
|
| None)
|
| if checkout.checkout_root in [c.checkout_root for c in checkouts]:
|
| parser.error('Specified the root %s two times.' %
|
| checkout.checkout_root)
|
| checkouts.append(checkout)
|
|
|
| - can_http = options.port and options.host
|
| - can_svn = options.svn_repo
|
| - can_git = options.git_repo
|
| - can_gerrit = options.gerrit_url
|
| - can_something = can_http or can_svn or can_git or can_gerrit
|
| - # If there was no transport selected yet, now we must have enough data to
|
| - # select one.
|
| - if not options.send_patch and not can_something:
|
| - parser.error('Please specify an access method.')
|
| + if not options.svn_repo:
|
| + parser.error('A SVN repo is required to send the job.')
|
|
|
| # Convert options.diff into the content of the diff.
|
| if options.url:
|
| @@ -1167,7 +814,7 @@ def TryChange(argv,
|
| diff = GetMungedDiff('', urllib2.urlopen(diff_url).readlines())
|
| options.diff = ''.join(diff[0])
|
| changed_files = diff[1]
|
| - else:
|
| + elif checkouts:
|
| # Use this as the base.
|
| root = checkouts[0].checkout_root
|
| diffs = []
|
| @@ -1183,6 +830,8 @@ def TryChange(argv,
|
| logging.error('Empty or non-existant diff, exiting.')
|
| return 1
|
| options.diff = ''.join(diffs)
|
| + else:
|
| + raise RuntimeError('Nothing to send')
|
|
|
| if not options.name:
|
| if options.issue:
|
| @@ -1221,30 +870,7 @@ def TryChange(argv,
|
| print ' %s' % (bot[0])
|
| return 0
|
|
|
| - # Determine sending protocol
|
| - if options.send_patch:
|
| - # If forced.
|
| - senders = [options.send_patch]
|
| - else:
|
| - # Try sending patch using avaialble protocols
|
| - all_senders = [
|
| - (_SendChangeHTTP, can_http),
|
| - (_SendChangeSVN, can_svn),
|
| - (_SendChangeGerrit, can_gerrit),
|
| - (_SendChangeGit, can_git),
|
| - ]
|
| - senders = [sender for sender, can in all_senders if can]
|
| -
|
| - # Send the patch.
|
| - for sender in senders:
|
| - try:
|
| - sender(bot_spec, options)
|
| - return 0
|
| - except NoTryServerAccess:
|
| - is_last = sender == senders[-1]
|
| - if is_last:
|
| - raise
|
| - assert False, "Unreachable code"
|
| + _SendChangeSVN(bot_spec, options)
|
| except Error, e:
|
| if swallow_exception:
|
| return 1
|
| @@ -1254,8 +880,3 @@ def TryChange(argv,
|
| print >> sys.stderr, e
|
| return 1
|
| return 0
|
| -
|
| -
|
| -if __name__ == "__main__":
|
| - fix_encoding.fix_encoding()
|
| - sys.exit(TryChange(None, None, False))
|
|
|