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
Exemple #11
0
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))