Exemple #1
0
def maybe_continue(default='y'):
    """Prompts the user for continuation"""
    default = default.lower()
    msg = "{0}Continue ".format(ansi('boldon'))
    if default == 'y':
        msg += "{0}[Y/n]? {1}".format(ansi('yellowf'), ansi('reset'))
    else:
        msg += "{0}[y/N]? {1}".format(ansi('yellowf'), ansi('reset'))

    while True:
        response = raw_input(msg)
        if not response:
            response = default

        response = response.lower()
        if response not in ['y', 'n', 'q']:
            error_msg = 'Reponse `' + response + '` was not recognized, ' \
                        'please use one of y, Y, n, N.'
            error(error_msg)
        else:
            break

    if response in ['n', 'q']:
        return False
    return True
Exemple #2
0
def summarize_arguments(upstream_repo, upstream_repo_type,
                        upstream_repo_branch):
    # Summarize the requested operation
    summary_msg = "Upstream " + ansi('boldon') + upstream_repo
    summary_msg += ansi('boldoff') + " type: " + ansi('boldon')
    summary_msg += upstream_repo_type + ansi('boldoff')
    info(summary_msg)
Exemple #3
0
def execute_command(cmd, shell=True, autofail=True, silent=True,
                    silent_error=False, cwd=None, return_io=False):
    """
    Executes a given command using vcstools' run_shell_command function.
    """
    io_type = None
    result = 0
    if silent:
        io_type = PIPE
    debug(((cwd) if cwd else os.getcwd()) + ":$ " + str(cmd))
    p = Popen(cmd, shell=True, cwd=cwd, stdout=io_type, stderr=io_type)
    out, err = p.communicate()
    result = p.returncode
    if result != 0:
        if not silent_error:
            error("'execute_command' failed to call '{0}'".format(cmd) + \
                  " which had a return code ({0}):".format(result))
            if out:
                error("    stdout:\n" + ansi('reset') + str(out))
                error("end stdout")
            if err:
                error("    stderr:\n" + ansi('reset') + str(err))
                error("end stderr")
        if autofail:
            raise CalledProcessError(cmd=cmd, output=out, returncode=result)
    if return_io:
        return result, out, err
    else:
        return result
Exemple #4
0
    def pre_modify(self):
        info("\nPre-verifying RPM dependency keys...")
        # Run rosdep update is needed
        if not self.has_run_rosdep:
            self.update_rosdep()

        peer_packages = [p.name for p in self.packages.values()]

        while not self._check_all_keys_are_valid(peer_packages, self.rosdistro):
            error("Some of the dependencies for packages in this repository could not be resolved by rosdep.")
            if not self.interactive:
                sys.exit(code.GENERATOR_NO_ROSDEP_KEY_FOR_DISTRO)
            error("You can try to address the issues which appear above and try again if you wish, "
                  "or continue without releasing into RPM-based distributions (e.g. Fedora 24).")
            try:
                if not maybe_continue(msg="Would you like to try again?"):
                    error("User aborted after rosdep keys were not resolved.")
                    sys.exit(code.GENERATOR_NO_ROSDEP_KEY_FOR_DISTRO)
            except (KeyboardInterrupt, EOFError):
                error("\nUser quit.", exit=True)
            update_rosdep()
            invalidate_view_cache()

        info("All keys are " + ansi('greenf') + "OK" + ansi('reset') + "\n")

        for package in self.packages.values():
            if not package.licenses or not package.licenses[0]:
                error("No license set for package '{0}', aborting.".format(package.name), exit=True)
Exemple #5
0
    def pre_modify(self):
        info("\nPre-verifying Debian dependency keys...")
        # Run rosdep update is needed
        if not self.has_run_rosdep:
            self.update_rosdep()

        peer_packages = [p.name for p in self.packages.values()]

        while not self._check_all_keys_are_valid(peer_packages):
            error(
                "Some of the dependencies for packages in this repository could not be resolved by rosdep."
            )
            error(
                "You can try to address the issues which appear above and try again if you wish."
            )
            try:
                if not maybe_continue(msg="Would you like to try again?"):
                    error("User aborted after rosdep keys were not resolved.")
                    sys.exit(code.GENERATOR_NO_ROSDEP_KEY_FOR_DISTRO)
            except (KeyboardInterrupt, EOFError):
                error("\nUser quit.", exit=True)
            update_rosdep()
            invalidate_view_cache()

        info("All keys are " + ansi('greenf') + "OK" + ansi('reset') + "\n")
Exemple #6
0
    def pre_modify(self):
        info("\nPre-verifying RPM dependency keys...")
        # Run rosdep update is needed
        if not self.has_run_rosdep:
            self.update_rosdep()

        peer_packages = [p.name for p in self.packages.values()]

        while not self._check_all_keys_are_valid(peer_packages, self.rosdistro):
            error("Some of the dependencies for packages in this repository could not be resolved by rosdep.")
            error("You can try to address the issues which appear above and try again if you wish, "
                  "or continue without releasing into RPM-based distributions (e.g. Fedora 24).")
            try:
                if not maybe_continue(msg="Would you like to try again?"):
                    error("User aborted after rosdep keys were not resolved.")
                    sys.exit(code.GENERATOR_NO_ROSDEP_KEY_FOR_DISTRO)
            except (KeyboardInterrupt, EOFError):
                error("\nUser quit.", exit=True)
            update_rosdep()
            invalidate_view_cache()

        info("All keys are " + ansi('greenf') + "OK" + ansi('reset') + "\n")

        for package in self.packages.values():
            if not package.licenses or not package.licenses[0]:
                error("No license set for package '{0}', aborting.".format(package.name), exit=True)
Exemple #7
0
def maybe_continue(default='y'):
    """Prompts the user for continuation"""
    default = default.lower()
    msg = "{0}Continue ".format(ansi('boldon'))
    if default == 'y':
        msg += "{0}[Y/n]? {1}".format(ansi('yellowf'), ansi('reset'))
    else:
        msg += "{0}[y/N]? {1}".format(ansi('yellowf'), ansi('reset'))

    while True:
        response = raw_input(msg)
        if not response:
            response = default

        response = response.lower()
        if response not in ['y', 'n', 'q']:
            error_msg = 'Reponse `' + response + '` was not recognized, ' \
                        'please use one of y, Y, n, N.'
            error(error_msg)
        else:
            break

    if response in ['n', 'q']:
        return False
    return True
Exemple #8
0
def get_package_data(branch_name=None, directory=None, quiet=True, fuerte=False):
    """
    Gets package data about the package(s) in the current branch.

    :param branch_name: name of the branch you are searching on (log use only)
    """
    log = debug if quiet else info
    repo_dir = directory if directory else os.getcwd()
    stack_path = os.path.join(repo_dir, 'stack.xml')
    if os.path.exists(stack_path) and not fuerte:
            warning("stack.xml is present but going to be ignored because this is not a release for Fuerte.")
    if branch_name:
        log("Looking for packages in '{0}' branch... ".format(branch_name), end='')
    else:
        log("Looking for packages in '{0}'... ".format(directory or os.getcwd()), end='')
    ## Check for package.xml(s)
    if not fuerte:
        packages = find_packages(repo_dir)
    else:
        packages = {}
    if type(packages) == dict and packages != {}:
        if len(packages) > 1:
            log("found " + str(len(packages)) + " packages.",
                use_prefix=False)
        else:
            log("found '" + packages.values()[0].name + "'.",
                use_prefix=False)
        version = verify_equal_package_versions(packages.values())
        return [p.name for p in packages.values()], version, packages
    ## Check for stack.xml
    has_rospkg = False
    try:
        import rospkg
        has_rospkg = True
    except ImportError:
        log(ansi('redf') + "failed." + ansi('reset'), use_prefix=False)
        warning("rospkg was not detected, stack.xml discovery is disabled",
                file=sys.stderr)
    if not has_rospkg:
        error("no package.xml(s) found, and no name specified with "
              "'--package-name', aborting.", use_prefix=False, exit=True)
    if os.path.exists(stack_path):
        log("found stack.xml.", use_prefix=False)
        stack = rospkg.stack.parse_stack_file(stack_path)
        return stack.name, stack.version, stack
    # Otherwise we have a problem
    log("failed.", use_prefix=False)
    error("no package.xml(s) or stack.xml found, and no name "
          "specified with '--package-name', aborting.",
          use_prefix=False, exit=True)
Exemple #9
0
    def pre_modify(self):
        info("\nPre-verifying Debian dependency keys...")
        # Run rosdep update is needed
        if not self.has_run_rosdep:
            self.update_rosdep()

        peer_packages = [p.name for p in self.packages.values()]

        for package in self.packages.values():
            depends = package.run_depends + package.buildtool_export_depends
            build_depends = package.build_depends + package.buildtool_depends + package.test_depends
            unresolved_keys = depends + build_depends + package.replaces + package.conflicts
            for os_version in self.distros:
                resolve_dependencies(unresolved_keys, self.os_name,
                                     os_version, self.rosdistro,
                                     peer_packages, fallback_resolver=missing_dep_resolver)

        info("All keys are " + ansi('greenf') + "OK" + ansi('reset') + "\n")
Exemple #10
0
def get_package_data(branch_name, directory=None):
    """
    Gets package data about the package(s) in the current branch.

    :param branch_name: name of the branch you are searching on (log use only)
    """
    debug("Looking for packages in '{0}'... ".format(branch_name), end='')
    ## Check for package.xml(s)
    repo_dir = directory if directory else os.getcwd()
    packages = find_packages(repo_dir)
    if type(packages) == dict and packages != {}:
        if len(packages) > 1:
            debug("found " + str(len(packages)) + " packages.",
                 use_prefix=False)
        else:
            debug("found '" + packages.values()[0].name + "'.",
                 use_prefix=False)
        version = verify_equal_package_versions(packages.values())
        return [p.name for p in packages.values()], version, packages
    ## Check for stack.xml
    has_rospkg = False
    try:
        import rospkg
        has_rospkg = True
    except ImportError:
        debug(ansi('redf') + "failed." + ansi('reset'), use_prefix=False)
        warning("rospkg was not detected, stack.xml discovery is disabled",
                file=sys.stderr)
    if not has_rospkg:
        error("no package.xml(s) found, and no name specified with "
              "'--package-name', aborting.", use_prefix=False)
        return code.NO_PACKAGE_XML_FOUND
    stack_path = os.path.join(repo_dir, 'stack.xml')
    if os.path.exists(stack_path):
        debug("found stack.xml.", use_prefix=False)
        stack = rospkg.stack.parse_stack_file(stack_path)
        return stack.name, stack.version, stack
    # Otherwise we have a problem
    debug("failed.", use_prefix=False)
    error("no package.xml(s) or stack.xml found, and not name "
          "specified with '--package-name', aborting.", use_prefix=False)
    return code.NO_PACKAGE_XML_FOUND
Exemple #11
0
def get_parser():
    """Returns a parser.ArgumentParser with all arguments defined"""
    parser = argparse.ArgumentParser(
        description="""\
This command sets the contents of the current branch to the contents of
the parent (upstream) branch.

It does this by replacing the current branch contents with parent contents:
    - delete current branch contents, copy over upstream branch contents
    - clear trim flag (so it can be reapplied)
    - update patches.conf

{0}\
WARNING: make sure to export patches and commit local changes before rebasing\
{1}

""".format(ansi('yellowf'), ansi('reset')),
        formatter_class=argparse.RawTextHelpFormatter
    )
    return parser
Exemple #12
0
    def pre_modify(self):
        info("\nPre-verifying Debian dependency keys...")
        # Run rosdep update is needed
        if not self.has_run_rosdep:
            self.update_rosdep()

        peer_packages = [p.name for p in self.packages.values()]

        while not self._check_all_keys_are_valid(peer_packages):
            error("Some of the dependencies for packages in this repository could not be resolved by rosdep.")
            error("You can try to address the issues which appear above and try again if you wish.")
            try:
                if not maybe_continue(msg="Would you like to try again?"):
                    error("User aborted after rosdep keys were not resolved.")
                    sys.exit(code.GENERATOR_NO_ROSDEP_KEY_FOR_DISTRO)
            except (KeyboardInterrupt, EOFError):
                error("\nUser quit.", exit=True)
            update_rosdep()
            invalidate_view_cache()

        info("All keys are " + ansi('greenf') + "OK" + ansi('reset') + "\n")
Exemple #13
0
def add_parser(subparsers):
    parser = subparsers.add_parser(
        'rebase',
        description="""\
This command sets the contents of the current branch to the contents of
the parent (upstream) branch.

It does this by replacing the current branch contents with parent contents:
    - delete current branch contents, copy over upstream branch contents
    - clear trim flag (so it can be reapplied)
    - update patches.conf

{0}\
WARNING: make sure to export patches and commit local changes before rebasing\
{1}

""".format(ansi('yellowf'), ansi('reset')),
        formatter_class=argparse.RawTextHelpFormatter)
    parser.set_defaults(func=main)
    add_global_arguments(parser)
    return parser
Exemple #14
0
def add_parser(subparsers):
    parser = subparsers.add_parser(
        'rebase',
        description="""\
This command sets the contents of the current branch to the contents of
the parent (upstream) branch.

It does this by replacing the current branch contents with parent contents:
    - delete current branch contents, copy over upstream branch contents
    - clear trim flag (so it can be reapplied)
    - update patches.conf

{0}\
WARNING: make sure to export patches and commit local changes before rebasing\
{1}

""".format(ansi('yellowf'), ansi('reset')),
        formatter_class=argparse.RawTextHelpFormatter
    )
    parser.set_defaults(func=main)
    add_global_arguments(parser)
    return parser
def auto_upstream_checkout(upstream_repo, upstream_url, devel_branch):
    info("Searching in upstream development branch for the name and version")
    info("  Upstream url: " + upstream_url)
    info("  Upstream type: " + upstream_repo.get_vcs_type_name())
    if devel_branch:
        info("  Upstream branch: " + str(devel_branch))
    # Handle special svn cases
    if upstream_repo.get_vcs_type_name() == 'svn':
        if devel_branch == '':
            upstream_url += '/trunk'
        else:
            upstream_url += '/branches/' + str(devel_branch)
        devel_branch = ''
    # Checkout to the upstream development branch
    retcode = try_vcstools_checkout(upstream_repo, upstream_url, devel_branch)
    if retcode != 0:
        return retcode
    # Look into the upstream devel branch for the version
    meta = get_upstream_meta(upstream_repo.get_path())
    if meta is None or None in meta.values():
        error("Failed to get the upstream meta data.")
        return 1
    # Summarize the package.xml/stack.xml contents
    info("Found upstream with version: " + ansi('boldon') + meta['version'] + \
         ansi('reset'))
    if meta['type'] == 'stack.xml':
        info("Upstream contains a stack called: " + ansi('boldon') + \
             meta['name'][0] + ansi('reset'))
    else:
        info("Upstream contains package" + \
             ('s: ' if len(meta['name']) > 1 else ': ') + ansi('boldon') + \
             ', '.join(meta['name']) + ansi('reset'))
    # If svn recreate upstream_repo and checkout to the tag
    if upstream_repo.get_vcs_type_name() == 'svn':
        # Remove the /trunk from the url
        upstream_url = '/'.join(upstream_url.split('/')[:-1])
        upstream_dir = upstream_repo.get_path()
        shutil.rmtree(upstream_dir)  # Delete old upstream
        upstream_repo = get_vcs_client('svn', upstream_dir)
        checkout_url = upstream_url + '/tags/' + meta['version']
        if not upstream_repo.checkout(checkout_url):
            got_it = False
            for name in meta['name']:
                warning("Didn't find the tagged version at " + checkout_url)
                checkout_url = upstream_url + '/tags/' + name + \
                               '-' + meta['version']
                warning("Trying " + checkout_url)
                if upstream_repo.checkout(checkout_url):
                    got_it = True
                    break
            if not got_it:
                error("Could not checkout upstream version")
                return 1
    # Return the meta data
    return meta
Exemple #16
0
def summarize_dependency_mapping(data, deps, build_deps, resolved_deps):
    if len(deps) == 0 and len(build_deps) == 0:
        return
    info("Package '" + data['Package'] + "' has dependencies:")
    header = "  " + ansi('boldoff') + ansi('ulon') + \
             "rosdep key           => " + data['Distribution'] + \
             " key" + ansi('reset')
    template = "  " + ansi('cyanf') + "{0:<20} " + ansi('purplef') + \
               "=> " + ansi('cyanf') + "{1}" + ansi('reset')
    if len(deps) != 0:
        info(ansi('purplef') + "Run Dependencies:" + ansi('reset'))
        info(header)
        for key in [d.name for d in deps]:
            info(template.format(key, resolved_deps[key]))
    if len(build_deps) != 0:
        info(
            ansi('purplef') + "Build and Build Tool Dependencies:" +
            ansi('reset'))
        info(header)
        for key in [d.name for d in build_deps]:
            info(template.format(key, resolved_deps[key]))
Exemple #17
0
 def summarize_package(self, package, distro, color='bluef'):
     info(ansi(color) + "\n####" + ansi('reset'), use_prefix=False)
     info(
         ansi(color) + "#### Generating '" + ansi('boldon') + distro +
         ansi('boldoff') + "' RPM for package"
         " '" + ansi('boldon') + package.name + ansi('boldoff') + "'" +
         " at version '" + ansi('boldon') + package.version +
         "-" + str(self.rpm_inc) + ansi('boldoff') + "'" +
         ansi('reset'),
         use_prefix=False
     )
     info(ansi(color) + "####" + ansi('reset'), use_prefix=False)
Exemple #18
0
 def post_patch(self, destination, color='bluef'):
     if destination in self.rpm_branches:
         return
     # Tag after patches have been applied
     with inbranch(destination):
         # Tag
         tag_name = self.tag_names[destination]
         if tag_exists(tag_name):
             if self.interactive:
                 warning("Tag exists: " + tag_name)
                 warning("Do you wish to overwrite it?")
                 if not maybe_continue('y'):
                     error("Answered no to continue, aborting.", exit=True)
             else:
                 warning("Overwriting tag: " + tag_name)
         else:
             info("Creating tag: " + tag_name)
         execute_command('git tag -f ' + tag_name)
     # Report of success
     name = destination.split('/')[-1]
     package = self.packages[name]
     distro = destination.split('/')[-2]
     info(ansi(color) + "####" + ansi('reset'), use_prefix=False)
     info(
         ansi(color) + "#### " + ansi('greenf') + "Successfully" +
         ansi(color) + " generated '" + ansi('boldon') + distro +
         ansi('boldoff') + "' RPM for package"
         " '" + ansi('boldon') + package.name + ansi('boldoff') + "'" +
         " at version '" + ansi('boldon') + package.version +
         "-" + str(self.rpm_inc) + ansi('boldoff') + "'" +
         ansi('reset'),
         use_prefix=False
     )
     info(ansi(color) + "####\n" + ansi('reset'), use_prefix=False)
Exemple #19
0
def summarize_dependency_mapping(data, deps, build_deps, resolved_deps):
    if len(deps) == 0 and len(build_deps) == 0:
        return
    info("Package '" + data['Package'] + "' has dependencies:")
    header = "  " + ansi('boldoff') + ansi('ulon') + \
             "rosdep key           => " + data['Distribution'] + \
             " key" + ansi('reset')
    template = "  " + ansi('cyanf') + "{0:<20} " + ansi('purplef') + \
               "=> " + ansi('cyanf') + "{1}" + ansi('reset')
    if len(deps) != 0:
        info(ansi('purplef') + "Run Dependencies:" +
             ansi('reset'))
        info(header)
        for key in [d.name for d in deps]:
            info(template.format(key, resolved_deps[key]))
    if len(build_deps) != 0:
        info(ansi('purplef') +
             "Build and Build Tool Dependencies:" + ansi('reset'))
        info(header)
        for key in [d.name for d in build_deps]:
            info(template.format(key, resolved_deps[key]))
Exemple #20
0
 def summarize_package(self, stackage, kind, distro, color='bluef'):
     info(ansi(color) + "\n####" + ansi('reset'), use_prefix=False)
     info(
         ansi(color) + "#### Generating '" + ansi('boldon') + distro + \
         ansi('boldoff') + "' debian for " + kind + \
         " '" + ansi('boldon') + stackage.name + ansi('boldoff') + "'" + \
         " at version '" + ansi('boldon') + stackage.version + \
         "-" + str(self.debian_inc) + ansi('boldoff') + "'" + \
         ansi('reset'),
         use_prefix=False
     )
     info(ansi(color) + "####" + ansi('reset'), use_prefix=False)
Exemple #21
0
 def post_patch(self, destination, color='bluef'):
     # Tag after patches have been applied
     with inbranch(destination):
         # Tag
         tag_name = self.tag_names[destination]
         if tag_exists(tag_name):
             if self.interactive:
                 warning("Tag exists: " + tag_name)
                 warning("Do you wish to overwrite it?")
                 if not maybe_continue('y'):
                     error("Answered no to continue, aborting.")
                     return code.ANSWERED_NO_TO_CONTINUE
             else:
                 warning("Overwriting tag: " + tag_name)
         else:
             info("Creating tag: " + tag_name)
         execute_command('git tag -f ' + tag_name)
     # Report of success
     name = destination.split('/')[-1]
     stackage, kind = self.packages[name]
     distro = destination.split('/')[-2]
     info(ansi(color) + "####" + ansi('reset'), use_prefix=False)
     info(
         ansi(color) + "#### " + ansi('greenf') + "Successfully" + \
         ansi(color) + " generated '" + ansi('boldon') + distro + \
         ansi('boldoff') + "' debian for " + kind + \
         " '" + ansi('boldon') + stackage.name + ansi('boldoff') + "'" + \
         " at version '" + ansi('boldon') + stackage.version + \
         "-" + str(self.debian_inc) + ansi('boldoff') + "'" + \
         ansi('reset'),
         use_prefix=False
     )
     info(ansi(color) + "####\n" + ansi('reset'), use_prefix=False)
def import_upstream(cwd, tmp_dir, args):
    # Ensure the bloom and upstream branches are tracked locally
    track_branches(['bloom', 'upstream'])

    # Create a clone of the bloom_repo to help isolate the activity
    bloom_repo_clone_dir = os.path.join(tmp_dir, 'bloom_clone')
    os.makedirs(bloom_repo_clone_dir)
    os.chdir(bloom_repo_clone_dir)
    bloom_repo = get_vcs_client('git', bloom_repo_clone_dir)
    bloom_repo.checkout('file://{0}'.format(cwd))

    # Ensure the bloom and upstream branches are tracked from the original
    track_branches(['bloom', 'upstream'])

    ### Fetch the upstream tag
    upstream_repo = None
    upstream_repo_dir = os.path.join(tmp_dir, 'upstream_repo')
    # If explicit svn url just export and git-import-orig
    if args.explicit_svn_url is not None:
        if args.upstream_version is None:
            error("'--explicit-svn-url' must be specified with "
                  "'--upstream-version'")
            return 1
        info("Checking out upstream at version " + ansi('boldon') + \
             str(args.upstream_version) + ansi('reset') + \
             " from repository at " + ansi('boldon') + \
             str(args.explicit_svn_url) + ansi('reset'))
        upstream_repo = get_vcs_client('svn', upstream_repo_dir)
        retcode = try_vcstools_checkout(upstream_repo, args.explicit_svn_url)
        if retcode != 0:
            return retcode
        meta = {
            'name': None,
            'version': args.upstream_version,
            'type': 'manual'
        }
    # Else fetching from bloom configs
    else:
        # Check for a bloom branch
        check_for_bloom()
        # Parse the bloom config file
        upstream_url, upstream_type, upstream_branch = parse_bloom_conf()
        # If the upstream_tag is specified, don't search just fetch
        upstream_repo = get_vcs_client(upstream_type, upstream_repo_dir)
        if args.upstream_tag is not None:
            warning("Using specified upstream tag '" + args.upstream_tag + "'")
            if upstream_type == 'svn':
                upstream_url += '/tags/' + args.upstream_tag
                upstream_tag = ''
            else:
                upstream_tag = args.upstream_tag
            retcode = try_vcstools_checkout(upstream_repo,
                                            upstream_url,
                                            upstream_tag)
            if retcode != 0:
                return retcode
            meta = {
                'name': None,
                'version': args.upstream_tag,
                'type': 'manual'
            }
        # We have to search for the upstream tag
        else:
            if args.upstream_devel is not None:
                warning("Overriding the bloom.conf upstream branch with " +
                        args.upstream_devel)
                devel_branch = args.upstream_devel
            else:
                devel_branch = upstream_branch
            if args.upstream_version is None:
                meta = auto_upstream_checkout(
                    upstream_repo, upstream_url, devel_branch
                )
            else:
                meta = {
                    'version': args.upstream_version
                }
            if type(meta) not in [dict] and meta != 0:
                return meta

    ### Export the repository
    version = meta['version']

    # Export the repository to a tar ball
    tarball_prefix = 'upstream-' + str(version)
    info('Exporting version {0}'.format(version))
    tarball_path = os.path.join(tmp_dir, tarball_prefix)
    if upstream_repo.get_vcs_type_name() == 'svn':
        upstream_repo.export_repository('', tarball_path)
    else:
        if args.upstream_tag is not None:
            upstream_repo.export_repository(args.upstream_tag, tarball_path)
        else:
            upstream_repo.export_repository(version, tarball_path)

    # Get the gbp version elements from either the last tag or the default
    last_tag = get_last_tag_by_version()
    if last_tag == '':
        gbp_major, gbp_minor, gbp_patch = segment_version(version)
    else:
        gbp_major, gbp_minor, gbp_patch = \
            get_versions_from_upstream_tag(last_tag)
        info("The latest upstream tag in the release repository is "
              + ansi('boldon') + last_tag + ansi('reset'))
        # Ensure the new version is greater than the last tag
        last_tag_version = '.'.join([gbp_major, gbp_minor, gbp_patch])
        if parse_version(version) < parse_version(last_tag_version):
            warning("""\
Version discrepancy:
    The upstream version, {0}, is not newer than the previous \
release version, {1}.
""".format(version, last_tag_version))
        if parse_version(version) <= parse_version(last_tag_version):
            if args.replace:
                # Remove the conflicting tag first
                warning("""\
The upstream version, {0}, is equal to or less than a previous \
import version.
    Removing conflicting tag before continuing \
because the '--replace' options was specified.\
""".format(version))
            else:
                warning("""\
The upstream version, {0}, is equal to a previous import version. \
git-buildpackage will fail, if you want to replace the existing \
upstream import use the '--replace' option.\
""".format(version))
    if args.replace:
        if tag_exists('upstream/' + version):
            execute_command('git tag -d {0}'.format('upstream/' + version))
            execute_command('git push origin :refs/tags/'
                            '{0}'.format('upstream/' + version))

    # Look for upstream branch
    if not branch_exists('upstream', local_only=True):
        create_branch('upstream', orphaned=True, changeto=True)

    # Go to the bloom branch during import
    bloom_repo.update('bloom')

    # Detect if git-import-orig is installed
    tarball_path += '.tar.gz'
    import_orig(tarball_path, 'upstream', upstream_repo.get_url(), version)

    # Push changes back to the original bloom repo
    execute_command('git push --all -f')
    execute_command('git push --tags')
Exemple #23
0
def execute_branch(src, dst, interactive, directory=None):
    """
    Changes to the destination branch, creates branch and patches/branch
    if they do not exist.

    If the dst branch does not exist yet, then it is created by branching the
    current working branch or the specified SRC_BRANCH.

    If the patches/dst branch branch does not exist yet then it is created.

    If the branches are created successful, then the working branch will be
    set to the dst branch, otherwise the working branch will remain unchanged.

    :param src: source branch from which to copy
    :param dst: destination branch
    :param interactive: if True actions are summarized before committing
    :param directory: directory in which to preform this action

    :raises: subprocess.CalledProcessError if any git calls fail
    """
    # Determine if the srouce branch exists
    if src is None:
        error("No source specified and/or not a branch currently", exit=True)
    if branch_exists(src, local_only=False, directory=directory):
        if not branch_exists(src, local_only=True, directory=directory):
            debug("Tracking source branch: {0}".format(src))
            track_branches(src, directory)
    elif tag_exists(src):
        pass
    else:
        error("Specified source branch does not exist: {0}".format(src),
              exit=True)

    # Determine if the destination branch needs to be created
    create_dst_branch = False
    if branch_exists(dst, local_only=False, directory=directory):
        if not branch_exists(dst, local_only=True, directory=directory):
            debug("Tracking destination branch: {0}".format(dst))
            track_branches(dst, directory)
    else:
        create_dst_branch = True

    # Determine if the destination patches branch needs to be created
    create_dst_patches_branch = False
    dst_patches = 'patches/' + dst
    if branch_exists(dst_patches, False, directory=directory):
        if not branch_exists(dst_patches, True, directory=directory):
            track_branches(dst_patches, directory)
    else:
        create_dst_patches_branch = True

    # Summarize
    if interactive:
        info("Summary of changes:")
        if create_dst_branch:
            info(" " * 22 + "- The specified destination branch, " +
                 ansi('boldon') + dst + ansi('reset') +
                 ", does not exist; it will be created from the source "
                 "branch " + ansi('boldon') + src + ansi('reset'))
        if create_dst_patches_branch:
            info(" " * 22 + "- The destination patches branch, " +
                 ansi('boldon') + dst_patches + ansi('reset') +
                 ", does not exist; it will be created")
        info(" " * 22 + "- The working branch will be set to " +
             ansi('boldon') + dst + ansi('reset'))
        if not maybe_continue():
            error("Answered no to continue, aborting.", exit=True)

    # Make changes to the layout
    current_branch = get_current_branch(directory)
    try:
        # Change to the src branch
        checkout(src, directory=directory)
        # Create the dst branch if needed
        if create_dst_branch:
            create_branch(dst, changeto=True, directory=directory)
        else:
            checkout(dst, directory=directory)
        # Create the dst patches branch if needed
        if create_dst_patches_branch:
            create_branch(dst_patches, orphaned=True, directory=directory)
        # Create the starting config data if it does not exist
        patches_ls = ls_tree(dst_patches, directory=directory)
        if 'patches.conf' not in patches_ls:
            # Patches config not setup, set it up
            config = {
                'parent': src,
                'previous': '',
                'base': get_commit_hash(dst, directory=directory),
                'trim': '',
                'trimbase': ''
            }
            set_patch_config(dst_patches, config, directory=directory)
        else:
            config = get_patch_config(dst_patches, directory=directory)
            if config['parent'] != src:
                warning("Updated parent to '{0}' from '{1}'".format(
                    src, config['parent']))
                config['parent'] = src
                config['base'] = get_commit_hash(dst, directory=directory)
            set_patch_config(dst_patches, config, directory=directory)
        # Command successful, do not switch back to previous branch
        current_branch = None
    finally:
        if current_branch is not None:
            checkout(current_branch, directory=directory)
Exemple #24
0
def main(sysargs=None):
    # Do argparse stuff
    parser = get_argument_parser()
    parser = add_global_arguments(parser)

    # List the generators
    generator_names = list_generators()

    # Create the generators
    generators = create_generators(generator_names)

    # Setup a subparser for each generator
    create_subparsers(parser, generators.values())

    # Inject into sys.argv
    if '--prefix' not in sys.argv:
        sys.argv.extend(['--prefix', 'release'])
    args = parser.parse_args(sysargs)
    handle_global_arguments(args)

    # Set logging prefix
    push_log_prefix('[git-bloom-release]: ')

    # Run import upstream
    info("###")
    msg = "### Running 'git bloom-import-upstream --replace'... "
    info(msg)
    info("###")
    iu_args = ['--replace']
    if args.debug:
        iu_args.append('-d')
    ret = iu_main(iu_args)
    msg += "returned (" + str(ret) + ")"
    if ret > 0:
        error(msg)
        return 0
    if ret < 0:
        warning(msg)
    else:
        info(msg)
    print('\n')

    # Run release generator
    info("###")
    msg = "### Running 'git bloom-generate -y release --src upstream'... "
    info(msg)
    info("###")
    generator = generators['release']
    args.interactive = False
    release_args = copy.deepcopy(args)
    release_args.src = 'upstream'
    release_args.name = None
    ret = execute_generator(generator, release_args)
    msg += "returned (" + str(ret) + ")"
    if ret > 0:
        error(msg)
        return 0
    if ret < 0:
        warning(msg)
    else:
        info(msg)
    print('\n')

    # Run given generator
    info("###")
    msg = "### Running 'git bloom-generate -y {0}'... ".format(args.generator)
    info(msg)
    info("###")
    generator = generators[args.generator]
    ret = execute_generator(generator, args)
    msg += "returned (" + str(ret) + ")"
    if ret > 0:
        error(msg)
        return 0
    if ret < 0:
        warning(msg)
    else:
        info(msg)
    print('\n')

    # Undo log prefix
    pop_log_prefix()

    # Notify the user of success and next action suggestions
    print('\n\n')
    warning("Tip: Check to ensure that the debian tags created have the same "
            "version as the upstream version you are releasing.")
    info(ansi('greenf') + ansi('boldon') + "Everything went as expected, "
         "you should check that the new tags match your expectations, and "
         "then push to the release repo with:" + ansi('reset'))
    info("  git push --all && git push --tags  # You might have to add --force to the second command if you are over-writing existing flags")
    return 0
Exemple #25
0
def execute_branch(src, dst, interactive, directory=None):
    """
    Changes to the destination branch, creates branch and patches/branch
    if they do not exist.

    If the dst branch does not exist yet, then it is created by branching the
    current working branch or the specified SRC_BRANCH.

    If the patches/dst branch branch does not exist yet then it is created.

    If the branches are created successful, then the working branch will be
    set to the dst branch, otherwise the working branch will remain unchanged.

    :param src: source branch from which to copy
    :param dst: destination branch
    :param interactive: if True actions are summarized before committing
    :param directory: directory in which to preform this action

    :raises: subprocess.CalledProcessError if any git calls fail
    """
    # Determine if the srouce branch exists
    if src is None:
        error("No source specified and/or not a branch currently", exit=True)
    if branch_exists(src, local_only=False, directory=directory):
        if not branch_exists(src, local_only=True, directory=directory):
            debug("Tracking source branch: {0}".format(src))
            track_branches(src, directory)
    elif tag_exists(src):
        pass
    else:
        error("Specified source branch does not exist: {0}".format(src), exit=True)

    # Determine if the destination branch needs to be created
    create_dst_branch = False
    if branch_exists(dst, local_only=False, directory=directory):
        if not branch_exists(dst, local_only=True, directory=directory):
            debug("Tracking destination branch: {0}".format(dst))
            track_branches(dst, directory)
    else:
        create_dst_branch = True

    # Determine if the destination patches branch needs to be created
    create_dst_patches_branch = False
    dst_patches = "patches/" + dst
    if branch_exists(dst_patches, False, directory=directory):
        if not branch_exists(dst_patches, True, directory=directory):
            track_branches(dst_patches, directory)
    else:
        create_dst_patches_branch = True

    # Summarize
    if interactive:
        info("Summary of changes:")
        if create_dst_branch:
            info(
                " " * 22
                + "- The specified destination branch, "
                + ansi("boldon")
                + dst
                + ansi("reset")
                + ", does not exist; it will be created from the source "
                "branch " + ansi("boldon") + src + ansi("reset")
            )
        if create_dst_patches_branch:
            info(
                " " * 22
                + "- The destination patches branch, "
                + ansi("boldon")
                + dst_patches
                + ansi("reset")
                + ", does not exist; it will be created"
            )
        info(" " * 22 + "- The working branch will be set to " + ansi("boldon") + dst + ansi("reset"))
        if not maybe_continue():
            error("Answered no to continue, aborting.", exit=True)

    # Make changes to the layout
    current_branch = get_current_branch(directory)
    try:
        # Change to the src branch
        checkout(src, directory=directory)
        # Create the dst branch if needed
        if create_dst_branch:
            create_branch(dst, changeto=True, directory=directory)
        else:
            checkout(dst, directory=directory)
        # Create the dst patches branch if needed
        if create_dst_patches_branch:
            create_branch(dst_patches, orphaned=True, directory=directory)
        # Create the starting config data if it does not exist
        patches_ls = ls_tree(dst_patches, directory=directory)
        if "patches.conf" not in patches_ls:
            # Patches config not setup, set it up
            config = {
                "parent": src,
                "previous": "",
                "base": get_commit_hash(dst, directory=directory),
                "trim": "",
                "trimbase": "",
            }
            set_patch_config(dst_patches, config, directory=directory)
        else:
            config = get_patch_config(dst_patches, directory=directory)
            if config["parent"] != src:
                warning("Updated parent to '{0}' from '{1}'".format(src, config["parent"]))
                config["parent"] = src
                config["base"] = get_commit_hash(dst, directory=directory)
            set_patch_config(dst_patches, config, directory=directory)
        # Command successful, do not switch back to previous branch
        current_branch = None
    finally:
        if current_branch is not None:
            checkout(current_branch, directory=directory)
Exemple #26
0
 def post_patch(self, destination, color='bluef'):
     if destination in self.debian_branches:
         return
     # Tag after patches have been applied
     with inbranch(destination):
         # Tag
         tag_name = self.tag_names[destination]
         if tag_exists(tag_name):
             if self.interactive:
                 warning("Tag exists: " + tag_name)
                 warning("Do you wish to overwrite it?")
                 if not maybe_continue('y'):
                     error("Answered no to continue, aborting.", exit=True)
             else:
                 warning("Overwriting tag: " + tag_name)
         else:
             info("Creating tag: " + tag_name)
         execute_command('git tag -f ' + tag_name)
     # Report of success
     name = destination.split('/')[-1]
     package = self.packages[name]
     distro = destination.split('/')[-2]
     info(ansi(color) + "####" + ansi('reset'), use_prefix=False)
     info(ansi(color) + "#### " + ansi('greenf') + "Successfully" +
          ansi(color) + " generated '" + ansi('boldon') + distro +
          ansi('boldoff') + "' debian for package"
          " '" + ansi('boldon') + package.name + ansi('boldoff') + "'" +
          " at version '" + ansi('boldon') + package.version + "-" +
          str(self.debian_inc) + ansi('boldoff') + "'" + ansi('reset'),
          use_prefix=False)
     info(ansi(color) + "####\n" + ansi('reset'), use_prefix=False)
Exemple #27
0
 def summarize_package(self, package, distro, color='bluef'):
     info(ansi(color) + "\n####" + ansi('reset'), use_prefix=False)
     info(ansi(color) + "#### Generating '" + ansi('boldon') + distro +
          ansi('boldoff') + "' debian for package"
          " '" + ansi('boldon') + package.name + ansi('boldoff') + "'" +
          " at version '" + ansi('boldon') + package.version + "-" +
          str(self.debian_inc) + ansi('boldoff') + "'" + ansi('reset'),
          use_prefix=False)
     info(ansi(color) + "####" + ansi('reset'), use_prefix=False)
Exemple #28
0
def generate_substitutions_from_package(package,
                                        os_name,
                                        os_version,
                                        ros_distro,
                                        installation_prefix='/usr',
                                        deb_inc=0,
                                        peer_packages=None,
                                        releaser_history=None,
                                        fallback_resolver=None,
                                        native=False,
                                        skip_package_names=None):
    info('{}Dependency-skip packages: {}{}'.format(ansi('purplef'),
                                                   skip_package_names,
                                                   ansi('reset')))
    peer_packages = peer_packages or []
    data = {}
    # Name, Version, Description
    data['Name'] = package.name
    data['Version'] = package.version
    data['Description'] = format_description(package.description)
    # Websites
    websites = [str(url) for url in package.urls if url.type == 'website']
    homepage = websites[0] if websites else ''
    if homepage == '':
        warning("No homepage set, defaulting to ''")
    data['Homepage'] = homepage
    # Debian Increment Number
    data['DebianInc'] = '' if native else '-{0}'.format(deb_inc)
    # Debian Package Format
    data['format'] = 'native' if native else 'quilt'
    # Package name
    data['Package'] = sanitize_package_name(package.name)
    # Installation prefix
    data['InstallationPrefix'] = installation_prefix
    # Resolve dependencies
    depends = package.run_depends + package.buildtool_export_depends
    build_depends = package.build_depends + package.buildtool_depends + package.test_depends

    unresolved_keys = depends + build_depends + package.replaces + package.conflicts
    # The installer key is not considered here, but it is checked when the keys are checked before this
    resolved_deps = resolve_dependencies(
        unresolved_keys,
        os_name,
        os_version,
        ros_distro,
        peer_packages + [d.name for d in package.replaces + package.conflicts],
        fallback_resolver,
        skip_package_names=skip_package_names)
    data['Depends'] = sorted(set(format_depends(depends, resolved_deps)))
    data['BuildDepends'] = sorted(
        set(format_depends(build_depends, resolved_deps)))
    data['Replaces'] = sorted(
        set(format_depends(package.replaces, resolved_deps)))
    data['Conflicts'] = sorted(
        set(format_depends(package.conflicts, resolved_deps)))

    # Build-type specific substitutions.
    build_type = package.get_build_type()
    if build_type == 'catkin':
        pass
    elif build_type == 'cmake':
        pass
    elif build_type == 'ament_cmake':
        pass
    elif build_type == 'ament_python':
        # Don't set the install-scripts flag if it's already set in setup.cfg.
        package_path = os.path.abspath(os.path.dirname(package.filename))
        setup_cfg_path = os.path.join(package_path, 'setup.cfg')
        data['pass_install_scripts'] = True
        if os.path.isfile(setup_cfg_path):
            setup_cfg = SafeConfigParser()
            setup_cfg.read([setup_cfg_path])
            if (setup_cfg.has_option('install', 'install-scripts')
                    or setup_cfg.has_option('install', 'install_scripts')):
                data['pass_install_scripts'] = False
    else:
        error("Build type '{}' is not supported by this version of bloom.".
              format(build_type),
              exit=True)

    # Set the distribution
    data['Distribution'] = os_version
    # Use the time stamp to set the date strings
    stamp = datetime.datetime.now(tz.tzlocal())
    data['Date'] = stamp.strftime('%a, %d %b %Y %T %z')
    data['YYYY'] = stamp.strftime('%Y')
    # Maintainers
    maintainers = []
    for m in package.maintainers:
        maintainers.append(str(m))
    data['Maintainer'] = maintainers[0]
    data['Maintainers'] = ', '.join(maintainers)
    # Changelog
    changelogs = get_changelogs(package, releaser_history)
    if changelogs and package.version not in [x[0] for x in changelogs]:
        warning("")
        warning(
            "A CHANGELOG.rst was found, but no changelog for this version was found."
        )
        warning(
            "You REALLY should have a entry (even a blank one) for each version of your package."
        )
        warning("")
    if not changelogs:
        # Ensure at least a minimal changelog
        changelogs = []
    if package.version not in [x[0] for x in changelogs]:
        changelogs.insert(0, (
            package.version, get_rfc_2822_date(datetime.datetime.now()),
            '  * Autogenerated, no changelog for this version found in CHANGELOG.rst.',
            package.maintainers[0].name, package.maintainers[0].email))
    bad_changelog = False
    # Make sure that the first change log is the version being released
    if package.version != changelogs[0][0]:
        error("")
        error("The version of the first changelog entry '{0}' is not the "
              "same as the version being currently released '{1}'.".format(
                  package.version, changelogs[0][0]))
        bad_changelog = True
    # Make sure that the current version is the latest in the changelog
    for changelog in changelogs:
        if parse_version(package.version) < parse_version(changelog[0]):
            error("")
            error(
                "There is at least one changelog entry, '{0}', which has a "
                "newer version than the version of package '{1}' being released, '{2}'."
                .format(changelog[0], package.name, package.version))
            bad_changelog = True
    if bad_changelog:
        error("This is almost certainly by mistake, you should really take a "
              "look at the changelogs for the package you are releasing.")
        error("")
        if not maybe_continue('n', 'Continue anyways'):
            sys.exit("User quit.")
    data['changelogs'] = changelogs
    # Use debhelper version 7 for oneric, otherwise 9
    data['debhelper_version'] = 7 if os_version in ['oneiric'] else 9
    # Summarize dependencies
    summarize_dependency_mapping(data, depends, build_depends, resolved_deps)

    def convertToUnicode(obj):
        if sys.version_info.major == 2:
            if isinstance(obj, str):
                return unicode(obj.decode('utf8'))
            elif isinstance(obj, unicode):
                return obj
        else:
            if isinstance(obj, bytes):
                return str(obj.decode('utf8'))
            elif isinstance(obj, str):
                return obj
        if isinstance(obj, list):
            for i, val in enumerate(obj):
                obj[i] = convertToUnicode(val)
            return obj
        elif isinstance(obj, type(None)):
            return None
        elif isinstance(obj, tuple):
            obj_tmp = list(obj)
            for i, val in enumerate(obj_tmp):
                obj_tmp[i] = convertToUnicode(obj_tmp[i])
            return tuple(obj_tmp)
        elif isinstance(obj, int):
            return obj
        raise RuntimeError('need to deal with type %s' % (str(type(obj))))

    for item in data.items():
        data[item[0]] = convertToUnicode(item[1])

    return data