| #!/usr/bin/env python |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| from __future__ import print_function |
| |
| import argparse |
| import time |
| from threading import Thread |
| import os.path |
| import collections |
| import re |
| import os |
| |
| import Report |
| import config |
| |
| # WARNING |
| # |
| # If you are editing this code, please be aware that commands passed to `run` |
| # should not use single quotes, this will break and end badly as the final |
| # command looks like `ssh 'host' 'some command - single quote will break it'`. |
| # Also please be aware that `run` uses `.format` to change `{host}` in commands |
| # into actual host name it is running on, running `.format` on strings using |
| # `{host}`, for example including `host_code_path` will not work. |
| # |
| # Also this code assumes master_base_path is available to all testing machines |
| # and is mounted in the same place on all of them. |
| # |
| # Getting rid of this restrictions without making the code much more complicated |
| # is very welcome. |
| |
| # This is configured in user configuration file. |
| |
| local = None |
| qfile_set = None |
| other_set = None |
| remote_set = None |
| all_set = None |
| |
| master_base_path = None |
| host_base_path = None |
| runtest_dir = os.getcwd() |
| |
| # End of user configurated things. |
| |
| ant_path = None |
| arc_path = None |
| phutil_path = None |
| code_path = None |
| report_path = None |
| host_code_path = None |
| ivy_path = None |
| |
| def read_conf(config_file): |
| global local, qfile_set, other_set, remote_set, all_set |
| global master_base_path, host_base_path |
| global ant_path, arc_path, phutil_path, code_path, report_path, host_code_path, ivy_path |
| |
| if config_file is not None: |
| config.load(config_file) |
| else: |
| config.load() |
| |
| local = config.local |
| qfile_set = config.qfile_set |
| other_set = config.other_set |
| remote_set = config.remote_set |
| all_set = config.all_set |
| |
| master_base_path = config.master_base_path |
| host_base_path = config.host_base_path |
| |
| if 'HIVE_PTEST_SUFFIX' in os.environ: |
| suffix = os.environ['HIVE_PTEST_SUFFIX'] |
| master_base_path += '-' + suffix |
| host_base_path += '-' + suffix |
| |
| ant_path = master_base_path + '/apache-ant-1.8.4' |
| arc_path = master_base_path + '/arcanist' |
| phutil_path = master_base_path + '/libphutil' |
| code_path = master_base_path + '/trunk' |
| report_path = master_base_path + '/report/' + time.strftime('%m.%d.%Y_%H:%M:%S') |
| host_code_path = host_base_path + '/trunk-{host}' |
| ivy_path = master_base_path + '/.ivy2' |
| |
| # Setup of needed environmental variables and paths |
| |
| # Proxy |
| if args.http_proxy is not None: |
| all_set.export('http_proxy', args.http_proxy + ':' + args.http_proxy_port) |
| all_set.export('https_proxy', args.http_proxy + ':' + args.http_proxy_port) |
| all_set.export('ANT_OPTS', get_ant_opts_proxy()) |
| |
| # Ant |
| all_set.export('ANT_HOME', ant_path) |
| all_set.add_path(ant_path + '/bin') |
| |
| # Arcanist |
| all_set.add_path(arc_path + '/bin') |
| |
| # Java |
| all_set.export('JAVA_HOME', config.java_home) |
| all_set.add_path(config.java_home + '/bin') |
| |
| # Hive |
| remote_set.export('HIVE_HOME', host_code_path + '/build/dist') |
| remote_set.add_path(host_code_path + '/build/dist/bin') |
| |
| def get_ant_opts_proxy(): |
| cmd = ' -Dhttp.proxyHost=' + args.http_proxy |
| cmd += ' -Dhttp.proxyPort=' + args.http_proxy_port |
| cmd += ' -Dhttps.proxyHost=' + args.http_proxy |
| cmd += ' -Dhttps.proxyPort=' + args.http_proxy_port |
| return cmd |
| |
| def get_ant(): |
| # Gets Ant 1.8.4 from one of Apache mirrors. |
| print('\n-- Installing Ant 1.8.4\n') |
| |
| if local.run('test -d "{0}"'.format(ant_path), warn_only = True, |
| abandon_output = False) is None: |
| local.run('mkdir -p "{0}"'.format(master_base_path)) |
| local.cd(master_base_path) |
| local.run('curl "http://apache.osuosl.org//ant/binaries/apache-ant-1.8.4-bin.tar.gz" | tar xz') |
| else: |
| print('\n Ant 1.8.4 already installed\n') |
| |
| def get_arc(): |
| # Gets latest Arcanist and libphtuil from their Git repositories. |
| print('\n-- Updating Arcanist installation\n') |
| |
| if local.run('test -d "{0}"'.format(arc_path), warn_only = True, |
| abandon_output = False) is None: |
| local.run('mkdir -p "{0}"'.format(os.path.dirname(arc_path))) |
| local.run('git clone https://github.com/facebook/arcanist.git "{0}"' |
| .format(arc_path)) |
| |
| if local.run('test -d "{0}"'.format(phutil_path), warn_only = True, |
| abandon_output = False) is None: |
| local.run('mkdir -p "{0}"'.format(os.path.dirname(phutil_path))) |
| local.run('git clone https://github.com/facebook/libphutil.git "{0}"' |
| .format(phutil_path)) |
| |
| local.cd(arc_path) |
| local.run('git pull https://github.com/facebook/arcanist.git') |
| local.cd(phutil_path) |
| local.run('git pull https://github.com/facebook/libphutil.git') |
| |
| def get_clean_hive(): |
| # Gets latest Hive from Apache Git repository and cleans the repository |
| # (undo of any changes and removal of all generated files). Also runs |
| # `arc-setup` so the repo is ready to be used. |
| print('\n-- Updating Hive repo\n') |
| |
| local.cd(code_path) |
| if local.run('test -d "{0}"'.format(code_path), warn_only = True, |
| abandon_output = False) is None: |
| local.run('mkdir -p "{0}"'.format(os.path.dirname(code_path))) |
| local.run('git clone http://git.apache.org/hive.git "{0}"'.format(code_path)) |
| else: |
| # Clean repo and checkout to t he last revision |
| local.run('git reset --hard HEAD') |
| local.run('git clean -dffx') |
| local.run('git pull') |
| |
| local.run('ant arc-setup') |
| |
| def copy_local_hive(): |
| # Copy local repo to the destination path instead of using git clone |
| if local.run('test -d "{0}"'.format(code_path), warn_only = True, |
| abandon_output = False) is None: |
| local.run('mkdir -p "{0}"'.format(os.path.dirname(code_path))) |
| local.run('rm -rf "{0}"'.format(code_path), warn_only = True) |
| local.run('mkdir -p "{0}"'.format(code_path)) |
| local.run('echo "{0}"'.format(runtest_dir)) |
| local.cd(runtest_dir) |
| local.run('cp -rf * "{0}"'.format(code_path)) |
| local.cd(code_path) |
| local.run('ant arc-setup') |
| |
| def prepare_for_reports(): |
| # Generates directories for test reports. All test nodes will copy results |
| # to this directories. |
| print('\n-- Creating a directory for JUnit reports\n') |
| # Remove previous reports that might be there. |
| local.run('rm -rf "{0}"'.format(report_path), warn_only = True) |
| local.run('mkdir -p "{0}/logs"'.format(report_path)) |
| local.run('mkdir -p "{0}/out/clientpositive"'.format(report_path)) |
| local.run('mkdir -p "{0}/out/clientnegative"'.format(report_path)) |
| |
| def patch_hive(patches = [], revision = None): |
| # Applies given patches to the Hive repo. Revision means a Differential |
| # revision, patches list is a list of paths to patches on local file system. |
| # |
| # Allowing multiple revisions and patches would complicate things a little |
| # (order of applied patches should be preserved, but argparse will split |
| # them into two lists) so only multiple local patches are allowed. |
| # Shouldn't be a big problem as you can use `arc export` to get the patches |
| # locally. |
| local.cd(code_path) |
| if revision is not None: |
| print('\n-- Patching Hive repo using a Differential revision\n') |
| revision = revision.upper() |
| if not revision.startswith('D'): |
| revision = 'D' + revision |
| local.run('arc patch "{0}"'.format(revision)) |
| if patches: |
| print('\n-- Patching Hive repo using a patch from local file system\n') |
| for patch in patches: |
| local.run('patch -rf -p0 < "{0}"'.format(patch)) |
| |
| def build_hive(): |
| print('\n-- Building Hive\n') |
| local.cd(code_path) |
| cmd = 'ant -Divy.default.ivy.user.dir={0} '.format(ivy_path) |
| if args.very_clean: |
| cmd += 'very-clean ' |
| else: |
| cmd += 'clean ' |
| cmd += 'package' |
| local.run(cmd) |
| |
| def propagate_hive(): |
| # Expects master_base_path to be available on all test nodes in the same |
| # place (for example using NFS). |
| print('\n-- Propagating Hive repo to all hosts\n') |
| print(host_code_path) |
| print(code_path) |
| |
| remote_set.run('rm -rf "{0}"'.format(host_code_path)) |
| remote_set.run('mkdir -p "{0}"'.format(host_code_path)) |
| remote_set.run('cp -r "{0}/*" "{1}"'.format( |
| code_path, host_code_path)) |
| |
| # It should avoid issues with 'ivy publish' exceptions during testing phase. |
| remote_set.run('cp -r "{0}" "{1}"'.format(ivy_path, host_code_path)) |
| |
| |
| def segment_tests(path): |
| # Removes `.q` files that should not be run on this host. The huge shell |
| # command is slow (not really suprising considering amount of forking it has |
| # to do), you are welcome to make it better=). |
| local.cd(code_path + path) |
| tests = local.run('ls -1', quiet = True, abandon_output = False).strip().split('\n') |
| |
| qfile_set.cd(host_code_path + path) |
| test_splits = [[] for i in range(len(qfile_set))] |
| i = 0 |
| for test in tests: |
| test_splits[i].append(test) |
| i = (i + 1) % len(qfile_set) |
| cmd = [] |
| for i in range(len(qfile_set)): |
| host = qfile_set.conn[i].hostname |
| cmd.append('if [[ "{host}" != "' + host + '" ]]; then rm -f ' + ' '.join(test_splits[i]) + '; fi') |
| cmd = ' && '.join(cmd) |
| # The command is huge and printing it out is not very useful, using wabbit |
| # hunting mode. |
| qfile_set.run(cmd, vewy_quiet = True) |
| |
| def prepare_tests(): |
| print('\n-- Preparing test sets on all hosts\n') |
| segment_tests('/ql/src/test/queries/clientpositive') |
| segment_tests('/ql/src/test/queries/clientnegative') |
| |
| def collect_log(name): |
| # Moves JUnit log to the global logs directory. |
| # |
| # This has the same restriction on master_base_path as propagate_hive. |
| new_name = name.split('.') |
| new_name[-2] += '-{host}' |
| new_name = '.'.join(new_name) |
| qfile_set.cd(host_code_path + '/build/ql/test') |
| # If tests failed there may be no file, so warn only if `cp` is having |
| # problems. |
| qfile_set.run( |
| 'cp "' + name + '" "' + report_path + '/logs/' + new_name + '" || ' + |
| 'touch "' + report_path + '/logs/{host}-' + name + '.fail"' |
| ) |
| # Get the hive.log too. |
| qfile_set.cd(host_code_path + '/build/ql/tmp') |
| qfile_set.run('cp "hive.log" "' + report_path + '/logs/hive-{host}-' + name + '.log"', |
| warn_only = True) |
| |
| def collect_out(name, desc_name): |
| # Moves `.out` file (test output) to the global logs directory. |
| # |
| # This has the same restriction on master_base_path as propagate_hive. |
| qfile_set.cd(host_code_path + '/' + name) |
| # Warn only if no files are found. |
| qfile_set.run('mkdir -p "' + report_path + '/' + desc_name + '/out/' + '"', warn_only = True) |
| qfile_set.run('cp * "' + report_path + '/' + desc_name + '/out/' + '"', warn_only = True) |
| |
| def run_tests(): |
| # Runs TestCliDriver and TestNegativeCliDriver testcases. |
| print('\n-- Running .q file tests on all hosts\n') |
| |
| # Using `quiet` because output of `ant test` is not very useful when we are |
| # running on many hosts and it all gets mixed up. In case of an error |
| # you'll get last lines generated by `ant test` anyway (might be totally |
| # irrelevant if one of the first tests fails and Ant reports a failure after |
| # running all the other test, fortunately JUnit report saves the Ant output |
| # if you need it for some reason). |
| |
| remote_ivy_path = '$(pwd)/.ivy2' |
| |
| qfile_set.cd(host_code_path) |
| qfile_set.run('ant -Divy.default.ivy.user.dir={0} -Dtestcase=TestCliDriver test'.format(remote_ivy_path), quiet = True, warn_only = True) |
| collect_log('TEST-org.apache.hadoop.hive.cli.TestCliDriver.xml') |
| collect_out('build/ql/test/logs/clientpositive', 'TestCliDriver') |
| |
| qfile_set.cd(host_code_path) |
| qfile_set.run('ant -Divy.default.ivy.user.dir={0} -Dtestcase=TestNegativeCliDriver test'.format(remote_ivy_path), quiet = True, warn_only = True) |
| collect_log('TEST-org.apache.hadoop.hive.cli.TestNegativeCliDriver.xml') |
| collect_out('build/ql/test/logs/clientnegative', 'TestNegativeCliDriver') |
| |
| def run_other_tests(): |
| # Runs all other tests that run_test doesn't run. |
| |
| def get_other_list(): |
| local.cd(code_path) |
| # Generate test classes in build. |
| local.run('ant -Dtestcase=nothing test') |
| |
| if (args.singlehost): |
| tests = local.run(' | '.join([ |
| 'find build/*/test/classes -name "Test*.class"', |
| 'sed -e "s:[^/]*/::g"', |
| 'grep -v TestSerDe.class', |
| 'grep -v TestHiveMetaStore.class', |
| 'grep -v TestBeeLineDriver.class', |
| 'grep -v TestHiveServer2Concurrency.class', |
| 'grep -v TestCliDriver.class', |
| 'grep -v TestNegativeCliDriver.class', |
| 'grep -v ".*\$.*\.class"', |
| 'sed -e "s:\.class::"' |
| ]), abandon_output = False) |
| return tests.split() |
| else: |
| tests = local.run(' | '.join([ |
| 'find build/*/test/classes -name "Test*.class"', |
| 'sed -e "s:[^/]*/::g"', |
| 'grep -v TestSerDe.class', |
| 'grep -v TestHiveMetaStore.class', |
| 'grep -v TestBeeLineDriver.class', |
| 'grep -v TestHiveServer2Concurrency.class', |
| 'grep -v TestCliDriver.class', |
| 'grep -v TestNegativeCliDriver.class', |
| 'grep -v ".*\$.*\.class"', |
| 'grep -v TestSetUGIOnBothClientServer.class', |
| 'grep -v TestSetUGIOnOnlyClient.class', |
| 'grep -v TestSetUGIOnOnlyServer.class', |
| 'grep -v TestRemoteHiveMetaStore', |
| 'grep -v TestEmbeddedHiveMetaStore', |
| 'sed -e "s:\.class::"' |
| ]), abandon_output = False) |
| return tests.split() |
| |
| def segment_other(): |
| other_set.run('mkdir -p ' + report_path + '/TestContribCliDriver', warn_only = True) |
| other_set.run('mkdir -p ' + report_path + '/TestContribCliDriver/positive', warn_only = True) |
| other_set.run('mkdir -p ' + report_path + '/TestContribCliDriver/negative', warn_only = True) |
| other_set.run('mkdir -p ' + report_path + '/TestHBaseCliDriver', warn_only = True) |
| |
| # Split all test cases between hosts. |
| def get_command(test): |
| return '; '.join([ |
| 'ant -Divy.default.ivy.user.dir=$(pwd)/.ivy2 -Dtestcase=' + test + ' test', |
| |
| 'cp "`find . -name "TEST-*.xml"`" "' + report_path + '/logs/" || ' + |
| 'touch "' + report_path + '/logs/{host}-' + test + '.fail"', |
| |
| 'cp "build/ql/tmp/hive.log" "' + report_path + '/logs/hive-{host}-' + test + '.log"', |
| |
| 'cp "build/contrib/test/logs/contribclientnegative/*" "' + report_path + '/TestContribCliDriver/negative 2>/dev/null"', |
| |
| 'cp "build/contrib/test/logs/contribclientpositive/*" "' + report_path + '/TestContribCliDriver/positive 2>/dev/null"', |
| |
| 'cp "build/hbase-handler/test/logs/hbase-handler/*" "' + report_path + '/TestHBaseCliDriver/ 2>/dev/null"' |
| ]) |
| |
| cmd = [] |
| i = 0 |
| for test in get_other_list(): |
| # Special case, don't run minimr tests in parallel. They will run |
| # on the first host, and no other tests will run there (unless we |
| # have a single host). |
| # |
| # TODO: Real fix would be to allow parallel runs of minimr tests. |
| if len(other_set) > 1: |
| if re.match('.*minimr.*', test.lower()): |
| host = other_set.conn[0].hostname |
| else: |
| i = (i + 1) % len(other_set) |
| if i == 0: |
| i = 1 |
| host = other_set.conn[i].hostname |
| else: |
| # We are running on single host. |
| host = other_set.conn[0].hostname |
| cmd.append( |
| 'if [[ "{host}" == "' + host + '" ]]; then ' + |
| get_command(test) + |
| '; fi' |
| ) |
| return ' ; '.join(cmd) |
| |
| command = segment_other() |
| other_set.cd(host_code_path) |
| # See comment about quiet option in run_tests. |
| other_set.run(command, quiet = True, warn_only = True) |
| |
| def generate_report(one_file_report = False): |
| # Uses `Report.py` to create a HTML report. |
| print('\n-- Generating a test report\n') |
| local.run('cp "' + master_base_path + '/templogs/* " "'+ report_path + '/logs/" ', warn_only = True) |
| |
| # Call format to remove '{{' and '}}'. |
| path = os.path.expandvars(report_path.format()) |
| CmdArgs = collections.namedtuple('CmdArgs', ['one_file', 'log_dir', 'report_dir']) |
| args = CmdArgs( |
| one_file = one_file_report, |
| log_dir = '{0}/logs'.format(path), |
| report_dir = path |
| ) |
| Report.make_report(args) |
| |
| print('\n-- Test report has been generated and is available here:') |
| print('-- "{0}/report.html"'.format(path)) |
| print() |
| |
| def stop_tests(): |
| # Brutally stops tests on all hosts, something more subtle would be nice and |
| # would allow the same user to run this script multiple times |
| # simultaneously. |
| print('\n-- Stopping tests on all hosts\n') |
| remote_set.run('killall -9 java', warn_only = True) |
| |
| def remove_code(): |
| # Running this only on one connection per host so there are no conflicts |
| # between several `rm` calls. This removes all repositories, it would have |
| # to be changed if we were to allow multiple simultaneous runs of this |
| # script. |
| |
| print('\n-- Removing Hive code from all hosts\n') |
| # We could remove only `host_code_path`, but then we would have abandoned |
| # directories after lowering number of processes running on one host. |
| cmd = 'rm -rf "' + host_base_path + '"' |
| cmd = 'if [[ `echo "{host}" | grep -q -- "-0$"; echo "$?"` -eq "0" ]]; then ' + \ |
| cmd + '; fi' |
| remote_set.run(cmd) |
| |
| def overwrite_results(): |
| # Copy generated `.q.out` files to master repo. |
| |
| local.cd(code_path) |
| expanded_path = local.run('pwd', abandon_output = False) |
| print('\n-- Copying generated `.q.out` files to master repository: ' + |
| expanded_path) |
| |
| for name in ['clientpositive', 'clientnegative']: |
| local.cd(report_path + '/out/' + name) |
| # Don't panic if no files are found. |
| local.run('cp * "' + code_path + '/ql/src/test/results/' + name + '"', |
| warn_only = True) |
| |
| def save_svn_info(): |
| if args.svn_info: |
| local.cd(master_base_path + '/trunk') |
| local.run('git show --summary > "{0}"'.format(report_path + '/svn-info')) |
| |
| def save_patch(): |
| if args.save_patch: |
| local.cd(code_path) |
| local.run('git add --all') |
| local.run('git diff --no-prefix HEAD > "{0}"'.format(report_path + '/patch')) |
| |
| # -- Tasks that can be called from command line start here. |
| |
| def cmd_prepare(patches = [], revision = None): |
| get_ant() |
| get_arc() |
| if (args.copylocal): |
| copy_local_hive() |
| else : |
| get_clean_hive() |
| patch_hive(patches, revision) |
| |
| build_hive() |
| propagate_hive() |
| prepare_tests() |
| |
| def cmd_run_tests(one_file_report = False): |
| prepare_for_reports() |
| save_svn_info() |
| save_patch() |
| |
| t = Thread(target = run_other_tests) |
| t.start() |
| run_tests() |
| t.join() |
| |
| if args.overwrite: |
| overwrite_results() |
| |
| generate_report(one_file_report) |
| |
| def cmd_test(patches = [], revision = None, one_file_report = False): |
| cmd_prepare(patches, revision) |
| |
| if args.singlehost==False: |
| local.cd(master_base_path + '/trunk') |
| local.run('chmod -R 777 *'); |
| local.run('rm -rf "' + master_base_path + '/templogs/"') |
| local.run('mkdir -p "' + master_base_path + '/templogs/"') |
| tests = ['TestRemoteHiveMetaStore','TestEmbeddedHiveMetaStore','TestSetUGIOnBothClientServer','TestSetUGIOnOnlyClient','TestSetUGIOnOnlyServer'] |
| |
| for test in tests: |
| local.run('sudo -u root ant -Divy.default.ivy.user.dir={0} '.format(ivy_path) + ' -Dtestcase=' + test + ' test') |
| local.run('cp "`find . -name "TEST-*.xml"`" "' + master_base_path + '/templogs/"') |
| |
| cmd_run_tests(one_file_report) |
| |
| def cmd_stop(): |
| stop_tests() |
| |
| def cmd_remove(): |
| remove_code() |
| |
| parser = argparse.ArgumentParser(description = |
| 'Hive test farm controller.') |
| parser.add_argument('--config', dest = 'config', |
| help = 'Path to configuration file') |
| parser.add_argument('--prepare', action = 'store_true', dest = 'prepare', |
| help = 'Builds Hive and propagates it to all test machines') |
| parser.add_argument('--run-tests', action = 'store_true', dest = 'run_tests', |
| help = 'Runs tests on all test machines') |
| parser.add_argument('--test', action = 'store_true', dest = 'test', |
| help = 'Same as running `prepare` and then `run-tests`') |
| parser.add_argument('--report-name', dest = 'report_name', |
| help = 'Store report and logs directory called `REPORT_NAME`') |
| parser.add_argument('--stop', action = 'store_true', dest = 'stop', |
| help = 'Kill misbehaving tests on all machines') |
| parser.add_argument('--remove', action = 'store_true', dest = 'remove', |
| help = 'Remove Hive trunk copies from test machines') |
| parser.add_argument('--revision', dest = 'revision', |
| help = 'Differential revision to test') |
| parser.add_argument('--patch', dest = 'patch', nargs = '*', |
| help = 'Patches from local file system to test') |
| parser.add_argument('--one-file-report', dest = 'one_file_report', |
| action = 'store_true', |
| help = 'Generate one (huge) report file instead of multiple small ones') |
| parser.add_argument('--overwrite', dest = 'overwrite', action = 'store_true', |
| help = 'Overwrite result files in master repo') |
| parser.add_argument('--copylocal', dest = 'copylocal', action = 'store_true', |
| help = 'Copy local repo instead of using git clone and git hub') |
| parser.add_argument('--singlehost', dest = 'singlehost', action = 'store_true', |
| help = 'Only run the test on single host, It is the users ' |
| 'responsibility to make sure that the conf. file does not ' |
| 'contain multiple hosts. ' |
| 'The script is not doing any validation. When --singlehost is set ' |
| 'the script should not be run using sudo.') |
| parser.add_argument('--very-clean', action = 'store_true', dest = 'very_clean', |
| help = 'Build hive with `very-clean` option') |
| parser.add_argument('--svn-info', dest = 'svn_info', action = 'store_true', |
| help = 'Save result of `svn info` into ${report_path}/svn-info') |
| parser.add_argument('--save-patch', dest = 'save_patch', action = 'store_true', |
| help = 'Save applied patch into ${report_path}/patch') |
| parser.add_argument('--http-proxy', dest = 'http_proxy', |
| help = 'Proxy host') |
| parser.add_argument('--http-proxy-port', dest = 'http_proxy_port', |
| help = 'Proxy port') |
| |
| args = parser.parse_args() |
| |
| read_conf(args.config) |
| |
| if args.report_name: |
| report_path = '/'.join(report_path.split('/')[:-1] + [args.report_name]) |
| |
| if args.prepare: |
| cmd_prepare(args.patch, args.revision) |
| elif args.run_tests: |
| cmd_run_tests(args.one_file_report) |
| elif args.test: |
| cmd_test(args.patch, args.revision, args.one_file_report) |
| elif args.stop: |
| cmd_stop() |
| elif args.remove: |
| cmd_remove() |
| else: |
| parser.print_help() |
| |