def main_wrapper(module, args): """This wraps the main method of an action so that: - backtrace is not printed by default - backtrace is printed is --backtrace was given - a pdb session is run if --pdb was given """ try: module.do(args) except Exception as e: if args.pdb: traceback = sys.exc_info()[2] print "" print "### Exception:", e print "### Starting a debugger" try: import ipdb ipdb.post_mortem(traceback) sys.exit(0) except ImportError: import pdb pdb.post_mortem(traceback) sys.exit(0) if args.backtrace: raise ui.error(e) sys.exit(2)
def do(args): """ Main entry point """ git_path = qisrc.worktree.git_project_path_from_cwd() git = qisrc.git.Git(git_path) current_branch = git.get_current_branch() if not current_branch: ui.error("Not currently on any branch") sys.exit(2) qisrc.review.push(git_path, current_branch, review=args.review, dry_run=args.dry_run, reviewers=args.reviewers)
def main(): ui.info(ui.red, "This is a an error message\n", ui.reset, "And here are the details") ui.error("could not build") ui.warning("-j ignored for this generator") ui.info("building foo") ui.debug("debug message") ui.info(ui.brown, "this is brown") ui.info(ui.bold, ui.brown, "this is bold brown") ui.info(ui.red, "red is dead") ui.info(ui.darkred, "darkred is really dead") ui.info(ui.yellow, "this is yellow")
def do(args): """Main entry point""" worktree = args.worktree if not worktree: worktree = os.getcwd() if args.config: # Just make sure the user choose a valid default toolchain qitoolchain.get_toolchain(args.config) worktree = qibuild.sh.to_native_path(worktree) parent_worktree = qisrc.worktree.guess_worktree(worktree) if parent_worktree: if parent_worktree != worktree: # Refuse to create nested worktrees ui.error("""A qi worktree already exists in {parent_worktree} Refusing to create a nested worktree in {worktree} Use: qibuild init -f -w {parent_worktree} If you want to re-initialize the worktree in {parent_worktree} """.format(worktree=worktree, parent_worktree=parent_worktree)) sys.exit(1) else: # Refuse to re-initalize the worktree unless "-f" is given if not args.force: ui.warning("There is already a worktree in", worktree, "\n" "Use --force if you want to re-initialize this worktree") return qibuild.toc.create(worktree, force=args.force) # User maybe re-running qibuild init because it has a # bad default exception ... try: toc = qibuild.toc.toc_open(worktree) except qibuild.toc.WrongDefaultException: pass toc_cfg_path = os.path.join(worktree, ".qi", "qibuild.xml") qibuild_cfg = qibuild.config.QiBuildConfig() qibuild_cfg.read() qibuild_cfg.read_local_config(toc_cfg_path) qibuild_cfg.local.defaults.config = args.config qibuild_cfg.write_local_config(toc_cfg_path) # Safe to be called now that we've created it # and that we know we don't have a wrong defaut config: toc = qibuild.toc.toc_open(worktree) if not args.interactive: return qibuild.wizard.run_config_wizard(toc)
def do(args): """Main entry point""" worktree = qisrc.open_worktree(args.worktree) projects = qisrc.cmdparse.projects_from_args(args) should_fetch_first = True if len(projects) == len(worktree.projects): sync_all(worktree, args) should_fetch_first = False git_projects = set() for project in projects: if project.git_project and not project.manifest: git_projects.add(project.git_project) ui.info(ui.green, "Synchronizing projects ...") git_projects = list(git_projects) git_projects.sort(key = operator.attrgetter("src")) errors = list() project_count = len(git_projects) for i, project in enumerate(git_projects): if project_count != 1: ui.info( ui.green, "*", ui.reset, "(%2i/%2i)" % (i+1, project_count), ui.blue, project.src) else: ui.info(ui.bold, "Pulling", ui.blue, project.src) git = qisrc.git.open(project.path) error = git.update_branch(project.branch, project.remote, fetch_first=True) if error: errors.append((project.src, error)) if not errors: return print ui.error("Fail to sync some projects") for (src, err) in errors: ui.info(ui.blue, src) print "-" * len(src) print indent(err, 2) sys.exit(1)
def tree_from_feed(feed_location): """ Returns an ElementTree object from an feed location """ fp = None tree = None try: if os.path.exists(feed_location): fp = open(feed_location, "r") else: fp = qitoolchain.remote.open_remote_location(feed_location) tree = ElementTree.ElementTree() tree.parse(fp) except Exception: ui.error("Could not parser", feed_location) raise finally: if fp: fp.close() return tree
def ask_program(message): """Ask the user to enter a path to a program. Look for it in PATH. If not found, ask the user to enter the full path. If still not found, give up ... """ keep_going = True while keep_going: full_path = ask_string(message) if not full_path: break full_path = qibuild.sh.to_native_path(full_path) if not os.path.exists(full_path): ui.error("%s does not exists!" % full_path) keep_going = ask_yes_no("continue") continue if not os.access(full_path, os.X_OK): ui.error("%s is not a valid executable!" % full_path) keep_going = ask_yes_no("continue") continue return full_path
def do(args): """Main entry point""" qiwt = qisrc.open_worktree(args.worktree) errors = list() ui.info(ui.green, "Running `%s` on every project" % " ".join(args.command)) c = 0 count = len(qiwt.git_projects) for project in qiwt.git_projects: c += 1 command = args.command[:] ui.info(ui.green, "*", ui.reset, "(%d/%d)" % (c, count), ui.blue, project.src) try: qibuild.command.call(command, cwd=project.path) except qibuild.command.CommandFailedException: if args.ignore_errors: errors.append(project) continue else: raise if not errors: return ui.error("Command failed on the following projects:") for project in errors: ui.info(ui.bold, " - ", project.src)
def do(args): """Main entry point """ toc = qibuild.toc.toc_open(args.worktree, args) if not args.project: project_name = qibuild.project.project_from_cwd() else: project_name = args.project project = toc.get_project(project_name) if not os.path.exists(project.build_directory): ui.error("""It looks like your project has not been configured yet (The build directory: '%s' does not exists)""" % project.build_directory) answer = qibuild.interact.ask_yes_no( "Do you want me to run qibuild configure for you", default=True) if not answer: sys.exit(2) else: qibuild.run_action("qibuild.actions.configure", [project.name, "--config", toc.active_config]) error_message = "Could not open project %s\n" % project_name qibuild_cfg = qibuild.config.QiBuildConfig(user_config=toc.active_config) qibuild_cfg.read() qibuild_cfg.read_local_config(toc.config_path) ide = get_ide(qibuild_cfg) if not ide: return if ide.name == "Visual Studio": sln_files = glob.glob(project.build_directory + "/*.sln") if len(sln_files) != 1: raise Exception(error_message + "Expecting only one sln, got %s" % sln_files) print "starting VisualStudio:" print "%s %s" % ("start", sln_files[0]) subprocess.Popen(["start", sln_files[0]], shell=True) return if ide.name == "Xcode": projs = glob.glob(project.build_directory + "/*.xcodeproj") if len(projs) == 0: raise Exception(error_message + "Do you have called qibuild configure with --cmake-generator=Xcode?") if len(projs) > 1: raise Exception(error_message + "Expecting only one xcode project file, got %s" % projs) print "starting Xcode:" print "%s %s" % ("open", projs[0]) subprocess.Popen(["open", projs[0]]) return if ide.name == "QtCreator": ide_path = ide.path if not ide_path: ide_path = 'qtcreator' cmake_list = os.path.join(project.directory, "CMakeLists.txt") if not os.access(ide_path, os.X_OK): mess = "Invalid configuration dectected!\n" mess += "QtCreator path (%s) is not a valid path\n" % ide_path mess += "Please run `qibuild config --wizard\n" raise Exception(mess) print "starting QtCreator:" print ide_path, cmake_list subprocess.Popen([ide_path, cmake_list]) return # Not supported (yet) IDE: mess = "Invalid ide: %s\n" % ide.name mess += "Supported IDES are: %s" % ", ".join(SUPPORTED_IDES) raise Exception(mess)
def run_tests(project, build_env, pattern=None, verbose=False, slow=False, dry_run=False, valgrind=False): """ Called by :py:meth:`qibuild.toc.Toc.test_project` :param test_name: If given, only run this test Always write some XML files in build-<config>/test-results (even if they were no tests to run at all) :return: a boolean to indicate if test was sucessful """ build_dir = project.build_directory results_dir = os.path.join(project.build_directory, "test-results") all_tests = parse_ctest_test_files(build_dir) tests = list() slow_tests = list() if pattern: tests = [x for x in all_tests if re.search(pattern, x[0])] if not tests: mess = "No tests matching %s\n" % pattern mess += "Known tests are:\n" for x in all_tests: mess += " * " + x[0] + "\n" raise Exception(mess) else: for test in all_tests: (name, cmd_, properties) = test cost = properties.get("COST") if not slow and cost and float(cost) > 50: ui.debug("Skipping test", name, "because cost", "(%s)"% cost, "is greater than 50") slow_tests.append(name) continue tests.append(test) if not tests: # Create a fake test result to keep CI jobs happy: fake_test_res = TestResult("compilation") fake_test_res.ok = True xml_out = os.path.join(results_dir, "compilation.xml") write_xml(xml_out, fake_test_res) ui.warning("No tests found for project", project.name) return if dry_run: ui.info(ui.green, "List of tests for", project.name) for (test_name, _, _) in tests: ui.info(ui.green, " * ", ui.reset, test_name) return ui.info(ui.green, "Testing", project.name, "...") ok = True fail_tests = list() for (i, test) in enumerate(tests): (test_name, cmd, properties) = test ui.info(ui.green, " * ", ui.reset, ui.bold, "(%2i/%2i)" % (i+1, len(tests)), ui.blue, test_name.ljust(25), end="") if verbose: print sys.stdout.flush() test_res = run_test(build_dir, test_name, cmd, properties, build_env, valgrind=valgrind, verbose=verbose) if test_res.ok: ui.info(ui.green, "[OK]") else: ok = False ui.info(ui.red, "[FAIL]") if not verbose: print test_res.out fail_tests.append(test_name) xml_out = os.path.join(results_dir, test_name + ".xml") if not os.path.exists(xml_out): write_xml(xml_out, test_res) if ok: ui.info("Ran %i tests" % len(tests)) if slow_tests and not slow: ui.info("Note: %i" % len(slow_tests), "slow tests did not run, use --slow to run them") ui.info("All pass. Congrats!") return True ui.error("Ran %i tests, %i failures" % (len(tests), len(fail_tests))) for fail_test in fail_tests: ui.info(ui.bold, " -", ui.blue, fail_test) return False
def split_debug(base_dir, objcopy=None): """ Split the debug information out of all the binaries in lib/ and bin/ The debug information will be put in a .debug directory next to the executable <base_dir>/bin/foo <base_dir>/bin/.debug/foo Also uses objcopy so that the binaries and libraries still remain usable with gdb :param: the objcopy executable to use. (defaults to the first objcopy executable found in PATH) """ if objcopy is None: objcopy = "objcopy" def _get_binaries(path): res = list() for root, _, filenames in os.walk(path): if os.path.basename(root) == ".debug": continue for filename in filenames: full_path = os.path.join(root, filename) if qibuild.sh.is_binary(full_path): res.append(full_path) return res binaries = list() bin_dir = os.path.join(base_dir, "bin") lib_dir = os.path.join(base_dir, "lib") binaries.extend(_get_binaries(bin_dir)) binaries.extend(_get_binaries(lib_dir)) for src in binaries: dirname, basename = os.path.split(src) debug_dir = os.path.join(dirname, ".debug") qibuild.sh.mkdir(debug_dir) dest = os.path.join(src, debug_dir, basename) to_run = list() to_run.append([objcopy, "--only-keep-debug", src, dest]) to_run.append([objcopy, "--strip-debug", "--strip-unneeded", "--add-gnu-debuglink=%s" % dest, src]) retcode = 0 #check if we need to do something #if mtime of src and dest are the same continue, else do the work and set #the mtime of dest to the one of src. stsrc = os.stat(src) stdst = None if os.path.exists(dest): stdst = os.stat(dest) if stdst and stsrc.st_mtime == stdst.st_mtime: ui.info("Debug info up-to-date for %s" % os.path.relpath(src, base_dir)) continue for cmd in to_run: retcode = 0 # FIXME: we should of course not try to split debug info twice, but # that's a hard problem retcode += qibuild.command.call(cmd, ignore_ret_code=True, quiet=True) if retcode == 0: os.utime(dest, (stsrc.st_atime, stsrc.st_mtime)) ui.info("Debug info extracted for %s" % os.path.relpath(src, base_dir)) else: ui.error("Error while extracting debug for %s" % os.path.relpath(src, base_dir))