#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Execute buildsteps on the slave.

This is the buildrunner, a script designed to run builds on the slave. It works
by mocking out the structures of a Buildbot master, then running a slave under
that 'fake' master. There are several benefits to this approach, the main one
being that build code can be changed and reloaded without a master restart.

Usage is detailed with -h.
"""

# pylint: disable=C0323

import optparse
import re
import os
import sys
import time

# Bootstrap PYTHONPATH from runit
SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir))
import common.env
common.env.Install()

from common import master_cfg_utils
from common import chromium_utils
from slave import builder_utils
from slave import runbuild_utils

REVISION_RE = re.compile(r'[0-9a-f]{5,40}|[1-9][0-9]{0,8}')


def get_args():
  """Process command-line arguments."""

  prog_desc = 'Executes a Buildbot build locally, without a master.'
  usage = '%prog [options] <master directory> [builder or slave hostname]'
  parser = optparse.OptionParser(usage=(usage + '\n\n' + prog_desc))
  parser.add_option('--list-masters', action='store_true',
                    help='list masters in search path')
  parser.add_option('--master-dir', help='specify a master directory '
                    'instead of a mastername')
  parser.add_option('--list-builders', help='list all available builders for '
                    'this master', action='store_true')
  parser.add_option('-s', '--slavehost', metavar='slavehost',
                    help='specify a slavehost to operate as')
  parser.add_option('-b', '--builder', metavar='builder',
                    help='string specified is a builder name')
  parser.add_option('--list-steps', action='store_true',
                    help='list steps in factory, but don\'t execute them')
  parser.add_option('--show-commands', action='store_true',
                    help='when listing steps, also show the generated output'
                         ' command. Also enables --list-steps and '
                         '--override-brdostep.')
  parser.add_option('--override-brdostep', action='store_true',
                    help='process all steps, even those with '
                         'brDoStepIf=False or None.')
  parser.add_option('--stepfilter', help='only run steps that match the '
                    'stepfilter regex')
  parser.add_option('--stepreject', help='reject any steps that match the '
                    'stepfilter regex')
  parser.add_option('--logfile', default='build_runner.log',
                    help='log build runner output to file (use - for stdout). '
                    'default: %default')
  parser.add_option('--hide-header', help='don\'t log environment information'
                    ' to logfile', action='store_true')
  parser.add_option('--slave-dir', help='location of the slave dir',
                    default=None)
  parser.add_option('--svn-rev', help='revision to check out, default: '
                    'LKGR')
  parser.add_option('--master-cfg', default='master.cfg',
                    help='filename of the master config. default: %default')
  parser.add_option('--builderpath',
                    help='directory to build results in. default: safe '
                    'transformation of builder name')
  parser.add_option('--build-properties', action='callback',
                    callback=chromium_utils.convert_json, type='string',
                    nargs=1, default={},
                    help='build properties in JSON format')
  parser.add_option('--factory-properties', action='callback',
                    callback=chromium_utils.convert_json, type='string',
                    nargs=1, default={},
                    help='factory properties in JSON format')
  parser.add_option('--output-build-properties', action='store_true',
                    help='output JSON-encoded build properties extracted from'
                    ' the build')
  parser.add_option('--output-factory-properties', action='store_true',
                    help='output JSON-encoded build properties extracted from'
                    'the build factory')
  parser.add_option('--annotate', action='store_true',
                    help='format output to work with the Buildbot annotator')
  parser.add_option('--test-config', action='store_true',
                    help='Attempt to parse all builders and steps without '
                    'executing them. Returns 0 on success.')
  parser.add_option('--fail-fast', action='store_true',
                    help='Exit on first step error instead of continuing.')

  return parser.parse_args()


def args_ok(inoptions, pos_args):
  """Verify arguments are correct and prepare args dictionary."""

  if inoptions.factory_properties:
    for key in inoptions.factory_properties:
      setattr(inoptions, key, inoptions.factory_properties[key])

  if inoptions.list_masters:
    return True

  if inoptions.build_properties and not inoptions.master_dir:
    if inoptions.build_properties['mastername']:
      inoptions.mastername = inoptions.build_properties['mastername']
    else:
      print >>sys.stderr, 'Error: build properties did not specify a ',
      print >>sys.stderr, 'mastername.'
      return False
  else:
    if not (inoptions.master_dir or pos_args):
      print >>sys.stderr, 'Error: you must provide a mastername or ',
      print >>sys.stderr, 'directory.'
      return False
    else:
      if not inoptions.master_dir:
        inoptions.mastername = pos_args.pop(0)

  inoptions.step_regex = None
  inoptions.stepreject_regex = None
  if inoptions.stepfilter:
    if inoptions.stepreject:
      print >>sys.stderr, ('Error: can\'t specify both stepfilter and '
                           'stepreject at the same time.')
      return False

    try:
      inoptions.step_regex = re.compile(inoptions.stepfilter)
    except re.error as e:
      print >>sys.stderr, 'Error compiling stepfilter regex \'%s\': %s' % (
          inoptions.stepfilter, e)
      return False
  if inoptions.stepreject:
    if inoptions.stepfilter:
      print >>sys.stderr, ('Error: can\'t specify both stepfilter and '
                           'stepreject at the same time.')
      return False
    try:
      inoptions.stepreject_regex = re.compile(inoptions.stepreject)
    except re.error as e:
      print >>sys.stderr, 'Error compiling stepreject regex \'%s\': %s' % (
          inoptions.stepreject, e)
      return False

  if inoptions.list_builders:
    return True

  if inoptions.show_commands:
    inoptions.override_brdostep = True
    inoptions.list_steps = True

  if inoptions.test_config:
    inoptions.spec = {}
    inoptions.revision = 12345
    inoptions.build_properties['got_revision'] = 12345
    inoptions.build_properties['revision'] = 12345
    return True

  if inoptions.build_properties and not (inoptions.slavehost or
                                         inoptions.builder):
    if inoptions.build_properties['buildername']:
      inoptions.builder = inoptions.build_properties['buildername']
    else:
      print >>sys.stderr, 'Error: build properties did not specify a '
      print >>sys.stderr, 'buildername.'
      return False
  else:
    if not (pos_args or inoptions.slavehost or inoptions.builder):
      print >>sys.stderr, 'Error: you must provide a builder or slave hostname.'
      return False

  # buildbot expects a list here, not a comma-delimited string
  if 'blamelist' in inoptions.build_properties:
    inoptions.build_properties['blamelist'] = (
        inoptions.build_properties['blamelist'].split(','))

  inoptions.spec = {}
  if inoptions.builder:
    inoptions.spec['builder'] = inoptions.builder
  elif inoptions.slavehost:
    inoptions.spec['hostname'] = inoptions.slavehost
  else:
    inoptions.spec['either'] = pos_args.pop(0)

  if inoptions.logfile == '-' or inoptions.annotate:
    inoptions.log = sys.stdout
  else:
    try:
      inoptions.log = open(inoptions.logfile, 'w')
    except IOError as err:
      errno, strerror = err
      print >>sys.stderr, 'Error %d opening logfile %s: %s' % (
          inoptions.logfile, errno, strerror)
      return False
    print >>sys.stderr, 'Writing to logfile', inoptions.logfile

  inoptions.revision = None
  if inoptions.build_properties and not inoptions.svn_rev:
    if inoptions.build_properties.get('revision'):
      inoptions.revision = inoptions.build_properties['revision']

    # got_revision will supersede revision if present.
    if inoptions.build_properties.get('got_revision'):
      inoptions.revision = inoptions.build_properties['got_revision']

    if not inoptions.revision:
      print >>sys.stderr, ('Error: build properties did not specify '
                           'valid revision.')
      return False

    if not REVISION_RE.match(inoptions.revision):
      print >>sys.stderr, 'Error: revision must be hash-like or revision-like.'
      return False

    print >>sys.stderr, 'using revision: %s' % inoptions.revision
    inoptions.build_properties['revision'] = '%s' % inoptions.revision
  else:
    if inoptions.svn_rev:
      try:
        inoptions.revision = int(inoptions.svn_rev)
      except ValueError:
        inoptions.revision = None

      if not inoptions.revision or inoptions.revision < 1:
        print >>sys.stderr, 'Error: svn rev must be a non-negative integer.'
        return False

      if not inoptions.annotate:
        print >>sys.stderr, 'using revision: %d' % inoptions.revision
    else:  # nothing specified on command line, let's check LKGR
      inoptions.revision, errmsg = chromium_utils.GetLKGR()
      if not inoptions.revision:
        print >>sys.stderr, errmsg
        return False
      if not inoptions.annotate:
        print >>sys.stderr, 'using LKGR: %d' % inoptions.revision

  return True


def execute(options):
  if options.list_masters:
    masterpairs = master_cfg_utils.GetMasters()
    master_cfg_utils.PrettyPrintMasters(masterpairs)
    return 0

  if options.master_dir:
    config = master_cfg_utils.LoadConfig(options.master_dir, options.master_cfg)
  else:
    path = master_cfg_utils.ChooseMaster(options.mastername)
    if not path:
      return 2

    config = master_cfg_utils.LoadConfig(path, config_file=options.master_cfg)

  if not config:
    return 2

  mastername = config['BuildmasterConfig']['properties']['mastername']
  builders = config['BuildmasterConfig']['builders']
  options.build_properties.update(config['BuildmasterConfig'].get(
      'properties', {}))

  if options.list_builders:
    master_cfg_utils.PrettyPrintBuilders(builders, mastername)
    return 0

  if options.test_config:
    for builder in builders:
      # We need to provide a slavename, so just pick the first one
      # the builder has.
      builder['slavename'] = builder['slavenames'][0]
      execute_builder(builder, mastername, options)
    return 0

  my_builder = master_cfg_utils.ChooseBuilder(builders, options.spec)
  return execute_builder(my_builder, mastername, options)

def execute_builder(my_builder, mastername, options):
  if options.spec and 'hostname' in options.spec:
    slavename = options.spec['hostname']
  elif (options.spec and 'either' in options.spec) and (
      options.spec['either'] != my_builder['name']):
    slavename = options.spec['either']
  else:
    slavename = my_builder['slavename']

  if not my_builder:
    return 2

  buildsetup = options.build_properties
  if 'revision' not in buildsetup:
    buildsetup['revision'] = '%s' % options.revision
  if 'branch' not in buildsetup:
    buildsetup['branch'] = 'src'

  steplist, build = builder_utils.MockBuild(my_builder, buildsetup, mastername,
      slavename, basepath=options.builderpath,
      build_properties=options.build_properties,
      slavedir=options.slave_dir)

  if options.output_build_properties:
    print
    print 'build properties:'
    print runbuild_utils.PropertiesToJSON(build.getProperties())

  if options.output_factory_properties:
    print
    print 'factory properties:'
    print runbuild_utils.PropertiesToJSON(my_builder['factory'].properties)

  if options.output_build_properties or options.output_factory_properties:
    return 0

  commands = builder_utils.GetCommands(steplist)
  if options.test_config:
    return 0

  if options.override_brdostep:
    for command in commands:
      command['doStep'] = True

  filtered_commands = runbuild_utils.FilterCommands(commands,
                                                    options.step_regex,
                                                    options.stepreject_regex)

  if options.list_steps:
    print
    print 'listing steps in %s/%s:' % (mastername, my_builder['name'])
    print
    for skip, cmd in filtered_commands:
      if 'command' not in cmd:
        print '-', cmd['name'], '[skipped] (custom step type: %s)' % (
            cmd['stepclass'])
      elif skip:
        print '-', cmd['name'], '[skipped]'
      elif skip is None:
        print '-', cmd['name'], '[skipped] (not under buildrunner)'
      else:
        print '*', cmd['name'],
        if options.show_commands:
          print '(in %s): %s' % (cmd['quoted_workdir'], cmd['quoted_command'])
        print
    return 0

  # Only execute commands that can be executed.
  filtered_commands = [(s, c) for s, c in filtered_commands if 'command' in c]

  if not options.annotate:
    print >>sys.stderr, 'using %s builder \'%s\'' % (mastername,
        my_builder['name'])

  start_time = time.time()
  commands_executed, err = runbuild_utils.Execute(filtered_commands,
      options.annotate, options.log, fail_fast=options.fail_fast)
  end_time = time.time()

  if err:
    print >>sys.stderr, ('error occurred in previous step, aborting! (%0.2fs'
                         ' since start).' % (end_time - start_time))
    return 2

  if not options.annotate:
    print >>sys.stderr, '%d commands completed (%0.2fs).' % (
        commands_executed, end_time - start_time)
  else:
    if commands_executed < 1:
      print '0 commands executed.'
  return 0


def main():
  opts, args = get_args()
  if not args_ok(opts, args):
    print
    print 'run with --help for usage info'
    return 1

  retcode = execute(opts)

  if retcode == 0:
    if not (opts.annotate or opts.list_masters or opts.list_builders
            or opts.list_steps or opts.test_config):
      print >>sys.stderr, 'build completed successfully'
  else:
    if not opts.annotate:
      print >>sys.stderr, 'build error encountered! aborting build'

  return retcode


if __name__ == '__main__':
  sys.exit(main())
