Пример #1
0
 def create_from_template(self, template_name, data, directory,
                          chmod=None, outfile=None):
     # Configure template name
     extention = '.em'
     if not template_name.endswith(extention):
         template_file = template_name + extention
     else:
         template_file = template_name
         template_name = template_name[:len(extention)]
     # Open the template
     with change_directory(directory):
         with open(template_file, 'r') as f:
             template = f.read()
         execute_command('git rm ' + template_file)
     # Expand template
     outfile = outfile if outfile is not None else template_name
     info("Expanding template: '" + template_file + "' to '" +
          outfile + "'")
     result = em.expand(template, **data)
     # Write the template out
     with change_directory(directory):
         with open(outfile, 'w+') as f:
             f.write(result)
         # Set permissions if needed
         if chmod is not None:
             os.chmod(outfile, chmod)
Пример #2
0
def main(sysargs):
    parser = get_argument_parser()
    args = parser.parse_args(sys.argv[1:])
    repository = args.repository
    verbose = args.verbose

    # checkout target rpository
    info("Manually clone the repository")
    info("  git clone {0}".format(repository))
    git = get_vcs_client('git', tempfile.mktemp())
    info(fmt("@{gf}@!==> @|") +
             "Fetching repository from '{0}'".format(repository))
    ret = git.checkout(repository, verbose=verbose)
    if not ret:
        error("Could not checkout {}".format(repository))
        return 1

    # get the github repository info
    base_org, base_repo = get_gh_info(git.get_url())
    # get correct repo info (case sensitive)
    gh = get_github_interface()
    base_org, base_repo = get_gh_info(gh.get_repo(base_org, base_repo)['html_url'])

    base_branch = git.get_branches()[0] # is this ok?

    with change_directory(git.get_path()):
        # write travis yaml
        write_travis_yaml()
        # write readme
        write_readme_md(**locals())

        # create pull request
        open_pull_request(base_org=base_org, base_repo=base_repo, base_branch=base_branch, new_branch="add_travis")
Пример #3
0
    def commit(self):
        if self.disabled:
            return
        info(fmt("@{bf}<==@| Command successful, committing changes to working copy"))
        current_branch = get_current_branch()
        if current_branch is None:
            error("Could not determine current branch.", exit=True)
        with inbranch(get_commit_hash(get_current_branch())):
            with change_directory(self.clone_dir):
                new_branches = get_branches()
                for branch in self.current_branches:
                    if branch in new_branches:
                        new_branches.remove(branch)
                for branch in get_branches(local_only=True):
                    if branch not in new_branches:
                        with inbranch(branch):
                            cmd = 'git pull --rebase origin ' + branch
                            execute_command(cmd)
                execute_command('git push --all', silent=False)
                try:
                    execute_command('git push --tags', silent=False)
                except subprocess.CalledProcessError:
                    warning("Force pushing tags from clone to working repository, "
                            "you will have to force push back to origin...")
                    execute_command('git push --force --tags', silent=False)

        self.clean_up()
Пример #4
0
    def commit(self):
        if self.disabled:
            return
        info(
            fmt("@{bf}<==@| Command successful, committing changes to working copy"
                ))
        current_branch = get_current_branch()
        if current_branch is None:
            error("Could not determine current branch.", exit=True)
        with inbranch(get_commit_hash(get_current_branch())):
            with change_directory(self.clone_dir):
                new_branches = get_branches()
                for branch in self.current_branches:
                    if branch in new_branches:
                        new_branches.remove(branch)
                for branch in get_branches(local_only=True):
                    if branch not in new_branches:
                        with inbranch(branch):
                            cmd = 'git pull --rebase origin ' + branch
                            execute_command(cmd)
                execute_command('git push --all', silent=False)
                try:
                    execute_command('git push --tags', silent=False)
                except subprocess.CalledProcessError:
                    warning(
                        "Force pushing tags from clone to working repository, "
                        "you will have to force push back to origin...")
                    execute_command('git push --force --tags', silent=False)

        self.clean_up()
Пример #5
0
 def create_from_template(self, template_name, data, directory,
                          chmod=None, outfile=None):
     # Configure template name
     extention = '.em'
     if not template_name.endswith(extention):
         template_file = template_name + extention
     else:
         template_file = template_name
         template_name = template_name[:len(extention)]
     template_path = os.path.join('templates', template_file)
     # Get the template contents using pkg_resources
     group = 'bloom.generators.debian'
     # info("Looking for template: " + group + ':' + template_path)
     try:
         template = pkg_resources.resource_string(group, template_path)
     except IOError as err:
         error("Failed to load template "
               "'{0}': {1}".format(template_name, str(err)))
         self.exit(code.DEBIAN_FAILED_TO_LOAD_TEMPLATE)
     # Expand template
     outfile = outfile if outfile is not None else template_name
     info("Expanding template: '" + template_file + "' to '" + \
          outfile + "'")
     result = em.expand(template, **data)
     # Write the template out
     with change_directory(directory):
         with open(outfile, 'w+') as f:
             f.write(result)
         # Set permissions if needed
         if chmod is not None:
             os.chmod(outfile, chmod)
Пример #6
0
def export_upstream(uri, tag, vcs_type, output_dir, show_uri, name):
    tag = tag if tag != ":{none}" else None
    output_dir = output_dir or os.getcwd()
    if uri.startswith("git@"):
        uri_is_path = False
    else:
        uri_parsed = urlparse(uri)
        uri = uri if uri_parsed.scheme else uri_parsed.path
        uri_is_path = False if uri_parsed.scheme else True
    name = name or "upstream"
    with temporary_directory() as tmp_dir:
        info(
            "Checking out repository at '{0}'".format(show_uri or uri)
            + (" to reference '{0}'.".format(tag) if tag else ".")
        )
        if uri_is_path:
            upstream_repo = get_vcs_client(vcs_type, uri)
        else:
            repo_path = os.path.join(tmp_dir, "upstream")
            upstream_repo = get_vcs_client(vcs_type, repo_path)
            if not upstream_repo.checkout(uri, tag or ""):
                error(
                    "Failed to clone repository at '{0}'".format(uri)
                    + (" to reference '{0}'.".format(tag) if tag else "."),
                    exit=True,
                )
        if get_root() is not None and has_submodules(upstream_repo.get_path()):
            error(
                """\
bloom does not support exporting git repositories with submodules, see:

- https://github.com/ros-infrastructure/bloom/issues/202
- https://github.com/ros-infrastructure/bloom/issues/217
- https://github.com/vcstools/vcstools/issues/84
""",
                exit=True,
            )
        tarball_prefix = "{0}-{1}".format(name, tag) if tag else name
        tarball_path = os.path.join(output_dir, tarball_prefix)
        full_tarball_path = tarball_path + ".tar.gz"
        info("Exporting to archive: '{0}'".format(full_tarball_path))
        if not upstream_repo.export_repository(tag or "", tarball_path):
            error("Failed to create archive of upstream repository at '{0}'".format(show_uri))
            if tag and vcs_type == "git":  # can only check for git repos
                with change_directory(upstream_repo.get_path()):
                    if not tag_exists(tag):
                        warning("'{0}' is not a tag in the upstream repository...".format(tag))
                    if not branch_exists(tag):
                        warning("'{0}' is not a branch in the upstream repository...".format(tag))
        if not os.path.exists(full_tarball_path):
            error("Tarball was not created.", exit=True)
        info("md5: {0}".format(calculate_file_md5(full_tarball_path)))
Пример #7
0
def list_tracks(repository, distro):
    release_repo = get_release_repo(repository, distro)
    tracks_dict = None
    with change_directory(release_repo.get_path()):
        if check_for_bloom_conf(repository):
            info("No tracks, but old style bloom.conf available for conversion")
        else:
            tracks_dict = get_tracks_dict_raw()
            if tracks_dict and tracks_dict['tracks'].keys():
                info("Available tracks: " + str(tracks_dict['tracks'].keys()))
            else:
                error("Release repository has no tracks nor an old style bloom.conf file.", exit=True)
    return tracks_dict['tracks'].keys() if tracks_dict else None
Пример #8
0
def get_upstream_meta(upstream_dir, ros_distro):
    meta = None
    directory = os.getcwd()
    with change_directory(upstream_dir):
        if get_root() is not None:  # If in a git repo
            current_branch = get_current_branch()
        else:
            current_branch = None
        name, version, packages = get_package_data(current_branch,
                                                   quiet=False,
                                                   release_directory=directory)
    meta = {'name': name, 'version': version, 'type': 'package.xml'}
    return meta
Пример #9
0
def export_upstream(uri, tag, vcs_type, output_dir, show_uri, name):
    tag = tag if tag != ':{none}' else None
    output_dir = output_dir or os.getcwd()
    if uri.startswith('git@'):
        uri_is_path = False
    else:
        uri_parsed = urlparse(uri)
        uri = uri if uri_parsed.scheme else uri_parsed.path
        uri_is_path = False if uri_parsed.scheme else True
    name = name or 'upstream'
    with temporary_directory() as tmp_dir:
        info("Checking out repository at '{0}'".format(show_uri or uri) +
             (" to reference '{0}'.".format(tag) if tag else '.'))
        if uri_is_path:
            upstream_repo = get_vcs_client(vcs_type, uri)
        else:
            repo_path = os.path.join(tmp_dir, 'upstream')
            upstream_repo = get_vcs_client(vcs_type, repo_path)
            if not upstream_repo.checkout(uri, tag or ''):
                error("Failed to clone repository at '{0}'".format(uri) +
                      (" to reference '{0}'.".format(tag) if tag else '.'),
                      exit=True)
        if get_root() is not None and has_submodules(upstream_repo.get_path()):
            error("""\
bloom does not support exporting git repositories with submodules, see:

- https://github.com/ros-infrastructure/bloom/issues/202
- https://github.com/ros-infrastructure/bloom/issues/217
- https://github.com/vcstools/vcstools/issues/84
""",
                  exit=True)
        tarball_prefix = '{0}-{1}'.format(name, tag) if tag else name
        tarball_path = os.path.join(output_dir, tarball_prefix)
        full_tarball_path = tarball_path + '.tar.gz'
        info("Exporting to archive: '{0}'".format(full_tarball_path))
        if not upstream_repo.export_repository(tag or '', tarball_path):
            error("Failed to create archive of upstream repository at '{0}'".
                  format(show_uri))
            if tag and vcs_type == 'git':  # can only check for git repos
                with change_directory(upstream_repo.get_path()):
                    if not tag_exists(tag):
                        warning(
                            "'{0}' is not a tag in the upstream repository...".
                            format(tag))
                    if not branch_exists(tag):
                        warning(
                            "'{0}' is not a branch in the upstream repository..."
                            .format(tag))
        if not os.path.exists(full_tarball_path):
            error("Tarball was not created.", exit=True)
        info("md5: {0}".format(calculate_file_md5(full_tarball_path)))
Пример #10
0
def get_upstream_meta(upstream_dir, ros_distro):
    meta = None
    with change_directory(upstream_dir):
        if get_root() is not None:  # If in a git repo
            current_branch = get_current_branch()
        else:
            current_branch = None
        name, version, packages = get_package_data(current_branch, quiet=False)
    meta = {
        'name': name,
        'version': version,
        'type': 'package.xml'
    }
    return meta
Пример #11
0
 def commit(self):
     with inbranch(get_commit_hash(get_current_branch())):
         with change_directory(self.clone_dir):
             new_branches = get_branches()
             for branch in self.current_branches:
                 if branch in new_branches:
                     new_branches.remove(branch)
             for branch in get_branches(local_only=True):
                 if branch not in new_branches:
                     with inbranch(branch):
                         cmd = "git pull --rebase origin " + branch
                         execute_command(cmd)
             execute_command("git push --all")
             execute_command("git push --tags")
     self.clean_up()
Пример #12
0
 def detect_branches(self):
     self.packages = None
     with inbranch(self.src):
         if self.name is not None:
             self.packages = [self.name]
             return [self.name]
         name, version, packages = get_package_data(self.src)
         self.packages = packages
         # Check meta packages for valid CMakeLists.txt
         if isinstance(self.packages, dict):
             for path, pkg in self.packages.iteritems():
                 with change_directory(path):
                     if is_metapackage(pkg):
                         check_metapackage_for_valid_cmake(pkg.name)
         return name if type(name) is list else [name]
Пример #13
0
def get_upstream_meta(upstream_dir, ros_distro):
    meta = None
    with change_directory(upstream_dir):
        if get_root() is not None:  # If in a git repo
            current_branch = get_current_branch()
        else:
            current_branch = None
        name, version, stackages = get_package_data(
            current_branch,
            quiet=False,
            fuerte=(ros_distro == 'fuerte'))
    meta = {
        'name': name,
        'version': version,
        'type': 'package.xml' if isinstance(stackages, dict) else 'stack.xml'
    }
    return meta
Пример #14
0
def list_tracks(repository, distro):
    release_repo = get_release_repo(repository, distro)
    tracks_dict = None
    with change_directory(release_repo.get_path()):
        upconvert_bloom_to_config_branch()
        if check_for_bloom_conf(repository):
            info(
                "No tracks, but old style bloom.conf available for conversion")
        else:
            tracks_dict = get_tracks_dict_raw()
            if tracks_dict and tracks_dict['tracks'].keys():
                info("Available tracks: " + str(tracks_dict['tracks'].keys()))
            else:
                error(
                    "Release repository has no tracks nor an old style bloom.conf file.",
                    exit=True)
    return tracks_dict['tracks'].keys() if tracks_dict else None
Пример #15
0
Файл: git.py Проект: po1/bloom
 def commit(self):
     if self.disabled:
         return
     current_branch = get_current_branch()
     if current_branch is None:
         error("Could not determine current branch.", exit=True)
     with inbranch(get_commit_hash(get_current_branch())):
         with change_directory(self.clone_dir):
             new_branches = get_branches()
             for branch in self.current_branches:
                 if branch in new_branches:
                     new_branches.remove(branch)
             for branch in get_branches(local_only=True):
                 if branch not in new_branches:
                     with inbranch(branch):
                         cmd = 'git pull --rebase origin ' + branch
                         execute_command(cmd)
             execute_command('git push --all')
             execute_command('git push --tags')
     self.clean_up()
Пример #16
0
def export_upstream(uri, tag, vcs_type, output_dir, show_uri, name):
    tag = tag if tag != ':{none}' else None
    output_dir = output_dir or os.getcwd()
    if uri.startswith('git@'):
        uri_is_path = False
    else:
        uri_parsed = urlparse(uri)
        uri = uri if uri_parsed.scheme else uri_parsed.path
        uri_is_path = False if uri_parsed.scheme else True
    name = name or 'upstream'
    with temporary_directory() as tmp_dir:
        info("Checking out repository at '{0}'".format(show_uri or uri) +
             (" to reference '{0}'.".format(tag) if tag else '.'))
        if uri_is_path:
            upstream_repo = get_vcs_client(vcs_type, uri)
        else:
            repo_path = os.path.join(tmp_dir, 'upstream')
            upstream_repo = get_vcs_client(vcs_type, repo_path)
            if not upstream_repo.checkout(uri, tag or ''):
                error("Failed to clone repository at '{0}'".format(uri) +
                      (" to reference '{0}'.".format(tag) if tag else '.'),
                      exit=True)
        tarball_prefix = '{0}-{1}'.format(name, tag) if tag else name
        tarball_path = os.path.join(output_dir, tarball_prefix)
        full_tarball_path = tarball_path + '.tar.gz'
        info("Exporting to archive: '{0}'".format(full_tarball_path))
        if not upstream_repo.export_repository(tag or '', tarball_path):
            error("Failed to create archive of upstream repository at '{0}'"
                  .format(show_uri))
            if tag and vcs_type == 'git':  # can only check for git repos
                with change_directory(upstream_repo.get_path()):
                    if not tag_exists(tag):
                        warning("'{0}' is not a tag in the upstream repository..."
                                .format(tag))
                    if not branch_exists(tag):
                        warning("'{0}' is not a branch in the upstream repository..."
                                .format(tag))
        if not os.path.exists(full_tarball_path):
            error("Tarball was not created.", exit=True)
        info("md5: {0}".format(calculate_file_md5(full_tarball_path)))
Пример #17
0
def export_upstream(uri, tag, vcs_type, output_dir, show_uri, name):
    tag = tag if tag != ':{none}' else None
    output_dir = output_dir or os.getcwd()
    if uri.startswith('git@'):
        uri_is_path = False
    else:
        uri_parsed = urlparse(uri)
        uri = uri if uri_parsed.scheme else uri_parsed.path
        uri_is_path = False if uri_parsed.scheme else True
    name = name or 'upstream'
    with temporary_directory() as tmp_dir:
        info("Checking out repository at '{0}'".format(show_uri or uri) +
            (" to reference '{0}'.".format(tag) if tag else '.'))
        if uri_is_path:
            upstream_repo = get_vcs_client(vcs_type, uri)
        else:
            repo_path = os.path.join(tmp_dir, 'upstream')
            upstream_repo = get_vcs_client(vcs_type, repo_path)
            if not upstream_repo.checkout(uri, tag or ''):
                error("Failed to clone repository at '{0}'".format(uri) +
                      (" to reference '{0}'.".format(tag) if tag else '.'),
                      exit=True)
        tarball_prefix = '{0}-{1}'.format(name, tag) if tag else name
        tarball_path = os.path.join(output_dir, tarball_prefix)
        full_tarball_path = tarball_path + '.tar.gz'
        info("Exporting to archive: '{0}'".format(full_tarball_path))
        if not upstream_repo.export_repository(tag or '', tarball_path):
            error("Failed to create archive of upstream repository at '{0}'"
                  .format(show_uri))
            if tag:
                with change_directory(upstream_repo.get_path()):
                    if not tag_exists(tag):
                        warning("'{0}' is not a tag in the upstream repository..."
                                .format(tag))
                    if not branch_exists(tag):
                        warning("'{0}' is not a branch in the upstream repository..."
                                .format(tag))
        if not os.path.exists(full_tarball_path):
            error("Tarball was not created.", exit=True)
        info("md5: {0}".format(calculate_file_md5(full_tarball_path)))
Пример #18
0
def main(sysargs):
    parser = get_argument_parser()
    args = parser.parse_args(sys.argv[1:])
    repository = args.repository
    verbose = args.verbose

    # checkout target rpository
    info("Manually clone the repository")
    info("  git clone {0}".format(repository))
    git = get_vcs_client('git', tempfile.mktemp())
    info(
        fmt("@{gf}@!==> @|") +
        "Fetching repository from '{0}'".format(repository))
    ret = git.checkout(repository, verbose=verbose)
    if not ret:
        error("Could not checkout {}".format(repository))
        return 1

    # get the github repository info
    base_org, base_repo = get_gh_info(git.get_url())
    # get correct repo info (case sensitive)
    gh = get_github_interface()
    base_org, base_repo = get_gh_info(
        gh.get_repo(base_org, base_repo)['html_url'])

    base_branch = git.get_branches()[0]  # is this ok?

    with change_directory(git.get_path()):
        # write travis yaml
        write_travis_yaml()
        # write readme
        write_readme_md(**locals())

        # create pull request
        open_pull_request(base_org=base_org,
                          base_repo=base_repo,
                          base_branch=base_branch,
                          new_branch="add_travis")
Пример #19
0
 def commit(self):
     with inbranch(get_commit_hash(get_current_branch())):
         with change_directory(self.clone_dir):
             execute_command('git push --force --all')
             execute_command('git push --force --tags')
     self.clean_up()
Пример #20
0
def perform_release(repository, track, distro, new_track, interactive, pretend, pull_request_only):
    release_repo = get_release_repo(repository, distro)
    with change_directory(release_repo.get_path()):
        # Check to see if the old bloom.conf exists
        if check_for_bloom_conf(repository):
            # Convert to a track
            info("Old bloom.conf file detected.")
            info(fmt("@{gf}@!==> @|Converting to bloom.conf to track"))
            convert_old_bloom_conf(None if new_track else distro)
        upconvert_bloom_to_config_branch()
        # Check that the track is valid
        tracks_dict = get_tracks_dict_raw()
        # If new_track, create the new track first
        if new_track:
            if not track:
                error("You must specify a track when creating a new one.", exit=True)
            if track in tracks_dict['tracks']:
                warning("Track '{0}' exists, editing...".format(track))
                edit_track_cmd(track)
                tracks_dict = get_tracks_dict_raw()
            else:
                # Create a new track called <track>,
                # copying an existing track if possible,
                # and overriding the ros_distro
                warning("Creating track '{0}'...".format(track))
                overrides = {'ros_distro': distro}
                new_track_cmd(track, copy_track='', overrides=overrides)
                tracks_dict = get_tracks_dict_raw()
        if track and track not in tracks_dict['tracks']:
            error("Given track '{0}' does not exist in release repository."
                  .format(track))
            error("Available tracks: " + str(tracks_dict['tracks'].keys()),
                  exit=True)
        elif not track:
            tracks = tracks_dict['tracks'].keys()
            # Error out if there are no tracks
            if len(tracks) == 0:
                error("Release repository has no tracks.")
                info("Manually clone the repository:")
                info("  git clone {0}".format(release_repo.get_url()))
                info("And then create a new track:")
                info("  git-bloom-config new <track name>")
                error("Run again after creating a track.", exit=True)
            # Error out if there is more than one track
            if len(tracks) != 1:
                error("No track specified and there is not just one track.")
                error("Please specify one of the available tracks: " +
                      str(tracks), exit=True)
            # Get the only track
            track = tracks[0]
        start_summary(track)
        if not pull_request_only:
            _perform_release(repository, track, distro, new_track, interactive, pretend, tracks_dict)
        # Propose github pull request
        info(fmt("@{gf}@!==> @|") +
             "Generating pull request to distro file located at '{0}'"
             .format(get_disitrbution_file_url(distro)))
        try:
            pull_request_url = open_pull_request(track, repository, distro)
            if pull_request_url:
                info(fmt(_success) + "Pull request opened at: {0}".format(pull_request_url))
                if 'BLOOM_NO_WEBBROWSER' not in os.environ and platform.system() in ['Darwin']:
                    webbrowser.open(pull_request_url)
            else:
                info("The release of your packages was successful, but the pull request failed.")
                info("Please manually open a pull request by editing the file here: '{0}'"
                     .format(get_disitrbution_file_url(distro)))
                info(fmt(_error) + "No pull request opened.")
        except Exception as e:
            debug(traceback.format_exc())
            error("Failed to open pull request: {0} - {1}".format(type(e).__name__, e), exit=True)
Пример #21
0
def open_pull_request(track, repository, distro):
    # Get the diff
    distribution_file = get_distribution_file(distro)
    if repository in distribution_file.repositories and \
       distribution_file.repositories[repository].release_repository is not None:
        orig_version = distribution_file.repositories[repository].release_repository.version
    else:
        orig_version = None
    updated_distribution_file = generate_ros_distro_diff(track, repository, distro)
    if updated_distribution_file is None:
        # There were no changes, no pull request required
        return None
    version = updated_distribution_file.repositories[repository].release_repository.version
    updated_distro_file_yaml = yaml_from_distribution_file(updated_distribution_file)
    # Determine if the distro file is hosted on github...
    base_org, base_repo, base_branch, base_path = get_gh_info(get_disitrbution_file_url(distro))
    if None in [base_org, base_repo, base_branch, base_path]:
        warning("Automated pull request only available via github.com")
        return
    # Get the github interface
    gh = get_github_interface()
    # Determine the head org/repo for the pull request
    head_org = gh.username  # The head org will always be gh user
    head_repo = None
    # Check if the github user and the base org are the same
    if gh.username == base_org:
        # If it is, then a fork is not necessary
        head_repo = base_repo
    else:
        info(fmt("@{bf}@!==> @|@!Checking on github for a fork to make the pull request from..."))
        # It is not, so a fork will be required
        # Check if a fork already exists on the user's account with the same name
        base_full_name = '{base_org}/{base_repo}'.format(**locals())
        try:
            repo_data = gh.get_repo(gh.username, base_repo)
            if repo_data.get('fork', False):  # Check if it is a fork
                # If it is, check that it is a fork of the destination
                parent = repo_data.get('parent', {}).get('full_name', None)
                if parent == base_full_name:
                    # This is a valid fork
                    head_repo = base_repo
        except GithubException as exc:
            debug("Received GithubException while checking for fork: {exc}".format(**locals()))
            pass  # 404 or unauthorized, but unauthorized should have been caught above
        # If not head_repo, then either the fork has a different name, or there isn't one
        if head_repo is None:
            info(fmt("@{bf}@!==> @|@!" + "{head_org}/{base_repo} is not a fork, searching...".format(**locals())))
            # First we should look at every repository for the user and see if they are a fork
            user_repos = gh.list_repos(gh.username)
            for repo in user_repos:
                # If it is a fork and the parent is base_org/base_repo
                if repo.get('fork', False) and repo.get('parent', {}).get('full_name', '') == base_full_name:
                    # Then this is a valid fork
                    head_repo = repo['name']
        # If not head_repo still, a fork does not exist and must be created
        if head_repo is None:
            warning("Could not find a fork of {base_full_name} on the {gh.username} Github account."
                    .format(**locals()))
            warning("Would you like to create one now?")
            if not maybe_continue():
                warning("Skipping the pull request...")
                return
            # Create a fork
            try:
                gh.create_fork(base_org, base_repo)  # Will raise if not successful
                head_repo = base_repo
            except GithubException as exc:
                error("Aborting pull request: {0}".format(exc))
                return
    info(fmt("@{bf}@!==> @|@!" +
             "Using this fork to make a pull request from: {head_org}/{head_repo}".format(**locals())))
    # Clone the fork
    info(fmt("@{bf}@!==> @|@!" + "Cloning {0}/{1}...".format(head_org, head_repo)))
    new_branch = None
    title = "{0}: {1} in '{2}' [bloom]".format(repository, version, base_path)
    body = """\
Increasing version of package(s) in repository `{0}` to `{2}`:

- distro file: `{3}`
- bloom version: `{4}`
- previous version for package: `{1}`
""".format(repository, orig_version or 'null', version, base_path, bloom.__version__)
    body += get_changelog_summary(generate_release_tag(distro))
    with temporary_directory() as temp_dir:
        def _my_run(cmd, msg=None):
            if msg:
                info(fmt("@{bf}@!==> @|@!" + sanitize(msg)))
            else:
                info(fmt("@{bf}@!==> @|@!" + sanitize(str(cmd))))
            from subprocess import check_call
            check_call(cmd, shell=True)
        # Use the oauth token to clone
        rosdistro_url = 'https://{gh.token}:[email protected]/{base_org}/{base_repo}.git'.format(**locals())
        rosdistro_fork_url = 'https://{gh.token}:[email protected]/{head_org}/{head_repo}.git'.format(**locals())
        _my_run('mkdir -p {base_repo}'.format(**locals()))
        with change_directory(base_repo):
            _my_run('git init')
            branches = [x['name'] for x in gh.list_branches(head_org, head_repo)]
            new_branch = 'bloom-{repository}-{count}'
            count = 0
            while new_branch.format(repository=repository, count=count) in branches:
                count += 1
            new_branch = new_branch.format(repository=repository, count=count)
            # Final check
            info(fmt("@{cf}Pull Request Title: @{yf}" + title))
            info(fmt("@{cf}Pull Request Body : \n@{yf}" + body))
            msg = fmt("@!Open a @|@{cf}pull request@| @!@{kf}from@| @!'@|@!@{bf}" +
                      "{head_repo}/{head_repo}:{new_branch}".format(**locals()) +
                      "@|@!' @!@{kf}into@| @!'@|@!@{bf}" +
                      "{base_org}/{base_repo}:{base_branch}".format(**locals()) +
                      "@|@!'?")
            info(msg)
            if not maybe_continue():
                warning("Skipping the pull request...")
                return
            _my_run('git checkout -b {new_branch}'.format(**locals()))
            _my_run('git pull {rosdistro_url} {base_branch}'.format(**locals()), "Pulling latest rosdistro branch")
            with open('{0}'.format(base_path), 'w') as f:
                info(fmt("@{bf}@!==> @|@!Writing new distribution file: ") + str(base_path))
                f.write(updated_distro_file_yaml)
            _my_run('git add {0}'.format(base_path))
            _my_run('git commit -m "{0}"'.format(title))
            _my_run('git push {rosdistro_fork_url} {new_branch}'.format(**locals()), "Pushing changes to fork")
    # Open the pull request
    return gh.create_pull_request(base_org, base_repo, base_branch, head_org, new_branch, title, body)
Пример #22
0
def open_pull_request(track, repository, distro):
    # Get the diff
    release_file = get_release_file(distro)
    if repository in release_file.repositories:
        orig_version = release_file.repositories[repository].version
    else:
        orig_version = None
    updated_release_file = generate_ros_distro_diff(track, repository, distro)
    if updated_release_file is None:
        # There were no changes, no pull request required
        return None
    version = updated_release_file.repositories[repository].version
    updated_distro_file = yaml_from_release_file(updated_release_file)
    # Determine if the distro file is hosted on github...
    gh_org, gh_repo, gh_branch, gh_path = get_gh_info(
        get_release_file_url(distro))
    if None in [gh_org, gh_repo, gh_branch, gh_path]:
        warning("Automated pull request only available via github.com")
        return
    # Get the github user name
    gh_username = None
    bloom_user_path = os.path.join(os.path.expanduser('~'), '.bloom_user')
    if os.path.exists(bloom_user_path):
        with open(bloom_user_path, 'r') as f:
            gh_username = f.read().strip()
    gh_username = gh_username or getpass.getuser()
    response = raw_input("github user name [{0}]: ".format(gh_username))
    if response:
        gh_username = response
        info(
            "Would you like bloom to store your github user name (~/.bloom_user)?"
        )
        if maybe_continue():
            with open(bloom_user_path, 'w') as f:
                f.write(gh_username)
        else:
            with open(bloom_user_path, 'w') as f:
                f.write(' ')
            warning(
                "If you want to have bloom store it in the future remove the ~/.bloom_user file."
            )
    # Get the github password
    gh_password = getpass.getpass("github password (This is not stored):")
    if not gh_password or not gh_username:
        error("Either the github username or github password is not set.")
        warning("Skipping the pull request...")
        return
    # Check for fork
    info(fmt("@{bf}@!==> @|@!Checking for rosdistro fork on github..."))
    gh_user_repos = fetch_github_api(
        'https://api.github.com/users/{0}/repos'.format(gh_username),
        use_pagination=True)
    if gh_user_repos is None:
        error("Failed to get a list of repositories for user: '******'".format(
            gh_username))
        warning("Skipping the pull request...")
        return
    if 'rosdistro' not in [x['name'] for x in gh_user_repos if 'name' in x]:
        warning(
            "Github user '{0}' does not have a fork ".format(gh_username) +
            "of the {0}:{1} repository, create one?".format(gh_org, gh_repo))
        if not maybe_continue():
            warning("Skipping the pull request...")
            return
        # Create a fork
        create_fork(gh_org, gh_repo, gh_username, gh_password)
    # Clone the fork
    info(
        fmt("@{bf}@!==> @|@!" +
            "Cloning {0}/{1}...".format(gh_username, gh_repo)))
    temp_dir = tempfile.mkdtemp()
    new_branch = None
    title = "{0}: {1} in '{2}' [bloom]".format(repository, version, gh_path)
    body = """\
Increasing version of package(s) in repository `{0}`:
- previous version: `{1}`
- new version: `{2}`
- distro file: `{3}`
- bloom version: `{4}`
""".format(repository, orig_version or 'null', version, gh_path,
           bloom.__version__)
    with change_directory(temp_dir):

        def _my_run(cmd):
            info(fmt("@{bf}@!==> @|@!" + str(cmd)))
            # out = check_output(cmd, stderr=subprocess.STDOUT, shell=True)
            out = None
            from subprocess import call
            call(cmd, shell=True)
            if out:
                info(out, use_prefix=False)

        _my_run('git clone https://github.com/{0}/{1}.git'.format(
            gh_username, gh_repo))
        with change_directory(gh_repo):
            _my_run(
                'git remote add bloom https://github.com/{0}/{1}.git'.format(
                    gh_org, gh_repo))
            _my_run('git remote update')
            _my_run('git fetch')
            track_branches()
            branches = get_branches()
            new_branch = 'bloom-{repository}-{count}'
            count = 0
            while new_branch.format(repository=repository,
                                    count=count) in branches:
                count += 1
            new_branch = new_branch.format(repository=repository, count=count)
            # Final check
            info(fmt("@{cf}Pull Request Title: @{yf}" + title))
            info(fmt("@{cf}Pull Request Body : \n@{yf}" + body))
            msg = fmt(
                "@!Open a @|@{cf}pull request@| @!@{kf}from@| @!'@|@!@{bf}" +
                "{gh_username}/{gh_repo}:{new_branch}".format(**locals()) +
                "@|@!' @!@{kf}into@| @!'@|@!@{bf}" +
                "{gh_org}/{gh_repo}:{gh_branch}".format(**locals()) + "@|@!'?")
            info(msg)
            if not maybe_continue():
                warning("Skipping the pull request...")
                return
            _my_run('git checkout -b {0} bloom/{1}'.format(
                new_branch, gh_branch))
            with open('{0}'.format(gh_path), 'w') as f:
                info(
                    fmt("@{bf}@!==> @|@!Writing new distribution file: ") +
                    str(gh_path))
                f.write(updated_distro_file)
            _my_run('git add {0}'.format(gh_path))
            _my_run('git commit -m "{0}"'.format(title))
            _my_run('git push origin {0}'.format(new_branch))
    # Open the pull request
    return create_pull_request(gh_org, gh_repo, gh_username, gh_password,
                               gh_branch, new_branch, title, body)
Пример #23
0
def perform_release(repository, track, distro, new_track, interactive,
                    pretend):
    release_repo = get_release_repo(repository, distro)
    with change_directory(release_repo.get_path()):
        # Check to see if the old bloom.conf exists
        if check_for_bloom_conf(repository):
            # Convert to a track
            info("Old bloom.conf file detected.")
            info(fmt("@{gf}@!==> @|Converting to bloom.conf to track"))
            convert_old_bloom_conf(None if new_track else distro)
        upconvert_bloom_to_config_branch()
        # Check that the track is valid
        tracks_dict = get_tracks_dict_raw()
        # If new_track, create the new track first
        if new_track:
            if not track:
                error("You must specify a track when creating a new one.",
                      exit=True)
            if track in tracks_dict['tracks']:
                warning("Track '{0}' exists, editing...".format(track))
                edit_track_cmd(track)
                tracks_dict = get_tracks_dict_raw()
            else:
                # Create a new track called <track>,
                # copying an existing track if possible,
                # and overriding the ros_distro
                warning("Creating track '{0}'...".format(track))
                overrides = {'ros_distro': distro}
                new_track_cmd(track, copy_track='', overrides=overrides)
                tracks_dict = get_tracks_dict_raw()
        if track and track not in tracks_dict['tracks']:
            error("Given track '{0}' does not exist in release repository.".
                  format(track))
            error("Available tracks: " + str(tracks_dict['tracks'].keys()),
                  exit=True)
        elif not track:
            tracks = tracks_dict['tracks'].keys()
            # Error out if there are no tracks
            if len(tracks) == 0:
                error("Release repository has no tracks.")
                info("Manually clone the repository:")
                info("  git clone {0}".format(release_repo.get_url()))
                info("And then create a new track:")
                info("  git-bloom-config new <track name>")
                error("Run again after creating a track.", exit=True)
            # Error out if there is more than one track
            if len(tracks) != 1:
                error("No track specified and there is not just one track.")
                error("Please specify one of the available tracks: " +
                      str(tracks),
                      exit=True)
            # Get the only track
            track = tracks[0]
        start_summary(track)
        # Ensure the track is complete
        track_dict = tracks_dict['tracks'][track]
        track_dict = update_track(track_dict)
        tracks_dict['tracks'][track] = track_dict
        # Set the release repositories' remote if given
        release_repo_url = track_dict.get('release_repo_url', None)
        if release_repo_url is not None:
            info(
                fmt("@{gf}@!==> @|") +
                "Setting release repository remote url to '{0}'".format(
                    release_repo_url))
            cmd = 'git remote set-url origin ' + release_repo_url
            info(fmt("@{bf}@!==> @|@!") + str(cmd))
            try:
                subprocess.check_call(cmd, shell=True)
            except subprocess.CalledProcessError:
                error("Setting the remote url failed, exiting.", exit=True)
        # Check for push permissions
        try:
            info(
                fmt("@{gf}@!==> @|Testing for push permission on release repository"
                    ))
            cmd = 'git remote -v'
            info(fmt("@{bf}@!==> @|@!") + str(cmd))
            subprocess.check_call(cmd, shell=True)
            # Dry run will authenticate, but not push
            cmd = 'git push --dry-run'
            info(fmt("@{bf}@!==> @|@!") + str(cmd))
            subprocess.check_call(cmd, shell=True)
        except subprocess.CalledProcessError:
            error("Cannot push to remote release repository.", exit=True)
        # Write the track config before releasing
        write_tracks_dict_raw(tracks_dict)
        # Run the release
        info(
            fmt("@{gf}@!==> @|") +
            "Releasing '{0}' using release track '{1}'".format(
                repository, track))
        cmd = 'git-bloom-release ' + str(track)
        if pretend:
            cmd += ' --pretend'
        info(fmt("@{bf}@!==> @|@!" + str(cmd)))
        try:
            subprocess.check_call(cmd, shell=True)
        except subprocess.CalledProcessError:
            error("Release failed, exiting.", exit=True)
        info(
            fmt(_success) +
            "Released '{0}' using release track '{1}' successfully".format(
                repository, track))
        # Commit the summary
        update_summary(track, repository, distro)
        commit_summary()
        # Check for pushing
        if interactive:
            info("Releasing complete, push?")
            if not maybe_continue():
                error("User answered no to continue prompt, aborting.",
                      exit=True)
        # Push changes to the repository
        info(
            fmt("@{gf}@!==> @|") +
            "Pushing changes to release repository for '{0}'".format(
                repository))
        cmd = 'git push --all'
        if pretend:
            cmd += ' --dry-run'
        info(fmt("@{bf}@!==> @|@!" + str(cmd)))
        try:
            subprocess.check_call(cmd, shell=True)
        except subprocess.CalledProcessError:
            error(
                "Pushing changes failed, would you like to add '--force' to 'git push --all'?"
            )
            if not maybe_continue():
                error("Pushing changes failed, exiting.", exit=True)
            cmd += ' --force'
            info(fmt("@{bf}@!==> @|@!" + str(cmd)))
            try:
                subprocess.check_call(cmd, shell=True)
            except subprocess.CalledProcessError:
                error("Pushing changes failed, exiting.", exit=True)
        info(fmt(_success) + "Pushed changes successfully")
        # Push tags to the repository
        info(
            fmt("@{gf}@!==> @|") +
            "Pushing tags to release repository for '{0}'".format(repository))
        cmd = 'git push --tags'
        if pretend:
            cmd += ' --dry-run'
        info(fmt("@{bf}@!==> @|@!" + str(cmd)))
        try:
            subprocess.check_call(cmd, shell=True)
        except subprocess.CalledProcessError:
            error(
                "Pushing changes failed, would you like to add '--force' to 'git push --tags'?"
            )
            if not maybe_continue():
                error("Pushing tags failed, exiting.", exit=True)
            cmd += ' --force'
            info(fmt("@{bf}@!==> @|@!" + str(cmd)))
            try:
                subprocess.check_call(cmd, shell=True)
            except subprocess.CalledProcessError:
                error("Pushing tags failed, exiting.", exit=True)
        info(fmt(_success) + "Pushed tags successfully")
        # Propose github pull request
        info(
            fmt("@{gf}@!==> @|") +
            "Generating pull request to distro file located at '{0}'".format(
                get_release_file_url(distro)))
        try:
            pull_request_url = open_pull_request(track, repository, distro)
            if pull_request_url:
                info(
                    fmt(_success) +
                    "Pull request opened at: {0}".format(pull_request_url))
                if 'BLOOM_NO_WEBBROWSER' in os.environ and platform.system(
                ) not in ['Darwin']:
                    webbrowser.open(pull_request_url)
            else:
                info(
                    "The release of your packages was successful, but the pull request failed."
                )
                info(
                    "Please manually open a pull request by editing the file here: '{0}'"
                    .format(get_release_file_url(distro)))
                info(fmt(_error) + "No pull request opened.")
        except Exception as e:
            debug(traceback.format_exc())
            error("Failed to open pull request: {0} - {1}".format(
                type(e).__name__, e),
                  exit=True)
Пример #24
0
def perform_release(repository, track, distro, new_track, interactive, pretend, ssh_pull_request):
    release_repo = get_release_repo(repository, distro)
    with change_directory(release_repo.get_path()):
        # Check to see if the old bloom.conf exists
        if check_for_bloom_conf(repository):
            # Convert to a track
            info("Old bloom.conf file detected.")
            info(fmt("@{gf}@!==> @|Converting to bloom.conf to track"))
            convert_old_bloom_conf(None if new_track else distro)
        upconvert_bloom_to_config_branch()
        # Check that the track is valid
        tracks_dict = get_tracks_dict_raw()
        # If new_track, create the new track first
        if new_track:
            if not track:
                error("You must specify a track when creating a new one.", exit=True)
            if track in tracks_dict['tracks']:
                warning("Track '{0}' exists, editing...".format(track))
                edit_track_cmd(track)
                tracks_dict = get_tracks_dict_raw()
            else:
                # Create a new track called <track>,
                # copying an existing track if possible,
                # and overriding the ros_distro
                warning("Creating track '{0}'...".format(track))
                overrides = {'ros_distro': distro}
                new_track_cmd(track, copy_track='', overrides=overrides)
                tracks_dict = get_tracks_dict_raw()
        if track and track not in tracks_dict['tracks']:
            error("Given track '{0}' does not exist in release repository."
                  .format(track))
            error("Available tracks: " + str(tracks_dict['tracks'].keys()),
                  exit=True)
        elif not track:
            tracks = tracks_dict['tracks'].keys()
            # Error out if there are no tracks
            if len(tracks) == 0:
                error("Release repository has no tracks.")
                info("Manually clone the repository:")
                info("  git clone {0}".format(release_repo.get_url()))
                info("And then create a new track:")
                info("  git-bloom-config new <track name>")
                error("Run again after creating a track.", exit=True)
            # Error out if there is more than one track
            if len(tracks) != 1:
                error("No track specified and there is not just one track.")
                error("Please specify one of the available tracks: " +
                      str(tracks), exit=True)
            # Get the only track
            track = tracks[0]
        start_summary(track)
        # Ensure the track is complete
        track_dict = tracks_dict['tracks'][track]
        track_dict = update_track(track_dict)
        tracks_dict['tracks'][track] = track_dict
        # Set the release repositories' remote if given
        release_repo_url = track_dict.get('release_repo_url', None)
        if release_repo_url is not None:
            info(fmt("@{gf}@!==> @|") +
                 "Setting release repository remote url to '{0}'"
                 .format(release_repo_url))
            cmd = 'git remote set-url origin ' + release_repo_url
            info(fmt("@{bf}@!==> @|@!") + str(cmd))
            try:
                subprocess.check_call(cmd, shell=True)
            except subprocess.CalledProcessError:
                error("Setting the remote url failed, exiting.", exit=True)
        # Check for push permissions
        try:
            info(fmt(
                "@{gf}@!==> @|Testing for push permission on release repository"
            ))
            cmd = 'git remote -v'
            info(fmt("@{bf}@!==> @|@!") + str(cmd))
            subprocess.check_call(cmd, shell=True)
            # Dry run will authenticate, but not push
            cmd = 'git push --dry-run'
            info(fmt("@{bf}@!==> @|@!") + str(cmd))
            subprocess.check_call(cmd, shell=True)
        except subprocess.CalledProcessError:
            error("Cannot push to remote release repository.", exit=True)
        # Write the track config before releasing
        write_tracks_dict_raw(tracks_dict)
        # Run the release
        info(fmt("@{gf}@!==> @|") +
             "Releasing '{0}' using release track '{1}'"
             .format(repository, track))
        cmd = 'git-bloom-release ' + str(track)
        if pretend:
            cmd += ' --pretend'
        info(fmt("@{bf}@!==> @|@!" + str(cmd)))
        try:
            subprocess.check_call(cmd, shell=True)
        except subprocess.CalledProcessError:
            error("Release failed, exiting.", exit=True)
        info(fmt(_success) +
             "Released '{0}' using release track '{1}' successfully"
             .format(repository, track))
        # Commit the summary
        update_summary(track, repository, distro)
        commit_summary()
        # Check for pushing
        if interactive:
            info("Releasing complete, push?")
            if not maybe_continue():
                error("User answered no to continue prompt, aborting.",
                      exit=True)
        # Push changes to the repository
        info(fmt("@{gf}@!==> @|") +
             "Pushing changes to release repository for '{0}'"
             .format(repository))
        cmd = 'git push --all'
        if pretend:
            cmd += ' --dry-run'
        info(fmt("@{bf}@!==> @|@!" + str(cmd)))
        try:
            subprocess.check_call(cmd, shell=True)
        except subprocess.CalledProcessError:
            error("Pushing changes failed, would you like to add '--force' to 'git push --all'?")
            if not maybe_continue():
                error("Pushing changes failed, exiting.", exit=True)
            cmd += ' --force'
            info(fmt("@{bf}@!==> @|@!" + str(cmd)))
            try:
                subprocess.check_call(cmd, shell=True)
            except subprocess.CalledProcessError:
                error("Pushing changes failed, exiting.", exit=True)
        info(fmt(_success) + "Pushed changes successfully")
        # Push tags to the repository
        info(fmt("@{gf}@!==> @|") +
             "Pushing tags to release repository for '{0}'"
             .format(repository))
        cmd = 'git push --tags'
        if pretend:
            cmd += ' --dry-run'
        info(fmt("@{bf}@!==> @|@!" + str(cmd)))
        try:
            subprocess.check_call(cmd, shell=True)
        except subprocess.CalledProcessError:
            error("Pushing changes failed, would you like to add '--force' to 'git push --tags'?")
            if not maybe_continue():
                error("Pushing tags failed, exiting.", exit=True)
            cmd += ' --force'
            info(fmt("@{bf}@!==> @|@!" + str(cmd)))
            try:
                subprocess.check_call(cmd, shell=True)
            except subprocess.CalledProcessError:
                error("Pushing tags failed, exiting.", exit=True)
        info(fmt(_success) + "Pushed tags successfully")
        # Propose github pull request
        info(fmt("@{gf}@!==> @|") +
             "Generating pull request to distro file located at '{0}'"
             .format(get_disitrbution_file_url(distro)))
        try:
            pull_request_url = open_pull_request(track, repository, distro, ssh_pull_request)
            if pull_request_url:
                info(fmt(_success) + "Pull request opened at: {0}".format(pull_request_url))
                if 'BLOOM_NO_WEBBROWSER' in os.environ and platform.system() not in ['Darwin']:
                    webbrowser.open(pull_request_url)
            else:
                info("The release of your packages was successful, but the pull request failed.")
                info("Please manually open a pull request by editing the file here: '{0}'"
                     .format(get_disitrbution_file_url(distro)))
                info(fmt(_error) + "No pull request opened.")
        except Exception as e:
            debug(traceback.format_exc())
            error("Failed to open pull request: {0} - {1}".format(type(e).__name__, e), exit=True)
Пример #25
0
def open_pull_request(track, repository, distro):
    # Get the diff
    release_file = get_release_file(distro)
    if repository in release_file.repositories:
        orig_version = release_file.repositories[repository].version
    else:
        orig_version = None
    updated_release_file = generate_ros_distro_diff(track, repository, distro)
    if updated_release_file is None:
        # There were no changes, no pull request required
        return None
    version = updated_release_file.repositories[repository].version
    updated_distro_file = yaml_from_release_file(updated_release_file)
    # Determine if the distro file is hosted on github...
    gh_org, gh_repo, gh_branch, gh_path = get_gh_info(get_release_file_url(distro))
    if None in [gh_org, gh_repo, gh_branch, gh_path]:
        warning("Automated pull request only available via github.com")
        return
    # Get the github user name
    gh_username = None
    bloom_user_path = os.path.join(os.path.expanduser("~"), ".bloom_user")
    if os.path.exists(bloom_user_path):
        with open(bloom_user_path, "r") as f:
            gh_username = f.read().strip()
    gh_username = gh_username or getpass.getuser()
    response = raw_input("github user name [{0}]: ".format(gh_username))
    if response:
        gh_username = response
        info("Would you like bloom to store your github user name (~/.bloom_user)?")
        if maybe_continue():
            with open(bloom_user_path, "w") as f:
                f.write(gh_username)
        else:
            with open(bloom_user_path, "w") as f:
                f.write(" ")
            warning("If you want to have bloom store it in the future remove the ~/.bloom_user file.")
    # Get the github password
    gh_password = getpass.getpass("github password (This is not stored):")
    if not gh_password or not gh_username:
        error("Either the github username or github password is not set.")
        warning("Skipping the pull request...")
        return
    # Check for fork
    info(fmt("@{bf}@!==> @|@!Checking for rosdistro fork on github..."))
    gh_user_repos = fetch_github_api("https://api.github.com/users/{0}/repos".format(gh_username), use_pagination=True)
    if gh_user_repos is None:
        error("Failed to get a list of repositories for user: '******'".format(gh_username))
        warning("Skipping the pull request...")
        return
    if "rosdistro" not in [x["name"] for x in gh_user_repos if "name" in x]:
        warning(
            "Github user '{0}' does not have a fork ".format(gh_username)
            + "of the {0}:{1} repository, create one?".format(gh_org, gh_repo)
        )
        if not maybe_continue():
            warning("Skipping the pull request...")
            return
        # Create a fork
        create_fork(gh_org, gh_repo, gh_username, gh_password)
    # Clone the fork
    info(fmt("@{bf}@!==> @|@!" + "Cloning {0}/{1}...".format(gh_username, gh_repo)))
    temp_dir = tempfile.mkdtemp()
    new_branch = None
    title = "{0}: {1} in '{2}' [bloom]".format(repository, version, gh_path)
    body = """\
Increasing version of package(s) in repository `{0}`:
- previous version: `{1}`
- new version: `{2}`
- distro file: `{3}`
- bloom version: `{4}`
""".format(
        repository, orig_version or "null", version, gh_path, bloom.__version__
    )
    with change_directory(temp_dir):

        def _my_run(cmd):
            info(fmt("@{bf}@!==> @|@!" + str(cmd)))
            # out = check_output(cmd, stderr=subprocess.STDOUT, shell=True)
            out = None
            from subprocess import call

            call(cmd, shell=True)
            if out:
                info(out, use_prefix=False)

        _my_run("git clone https://github.com/{0}/{1}.git".format(gh_username, gh_repo))
        with change_directory(gh_repo):
            _my_run("git remote add bloom https://github.com/{0}/{1}.git".format(gh_org, gh_repo))
            _my_run("git remote update")
            _my_run("git fetch")
            track_branches()
            branches = get_branches()
            new_branch = "bloom-{repository}-{count}"
            count = 0
            while new_branch.format(repository=repository, count=count) in branches:
                count += 1
            new_branch = new_branch.format(repository=repository, count=count)
            # Final check
            info(fmt("@{cf}Pull Request Title: @{yf}" + title))
            info(fmt("@{cf}Pull Request Body : \n@{yf}" + body))
            msg = fmt(
                "@!Open a @|@{cf}pull request@| @!@{kf}from@| @!'@|@!@{bf}"
                + "{gh_username}/{gh_repo}:{new_branch}".format(**locals())
                + "@|@!' @!@{kf}into@| @!'@|@!@{bf}"
                + "{gh_org}/{gh_repo}:{gh_branch}".format(**locals())
                + "@|@!'?"
            )
            info(msg)
            if not maybe_continue():
                warning("Skipping the pull request...")
                return
            _my_run("git checkout -b {0} bloom/{1}".format(new_branch, gh_branch))
            with open("{0}".format(gh_path), "w") as f:
                info(fmt("@{bf}@!==> @|@!Writing new distribution file: ") + str(gh_path))
                f.write(updated_distro_file)
            _my_run("git add {0}".format(gh_path))
            _my_run('git commit -m "{0}"'.format(title))
            _my_run("git push origin {0}".format(new_branch))
    # Open the pull request
    return create_pull_request(gh_org, gh_repo, gh_username, gh_password, gh_branch, new_branch, title, body)
Пример #26
0
def perform_release(repository, track, distro, new_track, interactive):
    release_repo = get_release_repo(repository, distro)
    with change_directory(release_repo.get_path()):
        # Check for push permissions
        try:
            info(fmt("@{gf}@!==> @|Testing for push permission on release repository"))
            check_output('git push', shell=True)
        except subprocess.CalledProcessError:
            error("Cannot push to remote release repository.", exit=True)
        # Check to see if the old bloom.conf exists
        if check_for_bloom_conf(repository):
            # Convert to a track
            info("Old bloom.conf file detected.")
            info(fmt("@{gf}@!==> @|Converting to bloom.conf to track"))
            convert_old_bloom_conf(None if new_track else distro)
        # Check that the track is valid
        tracks_dict = get_tracks_dict_raw()
        # If new_track, create the new track first
        if new_track:
            if not track:
                error("You must specify a track when creating a new one.", exit=True)
            overrides = {'ros_distro': distro}
            if track in tracks_dict['tracks']:
                warning("Track '{0}' exists, editing instead...".format(track))
                edit_track_cmd(track)
            else:
                # Create a new track called <track>,
                # copying an existing track if possible,
                # and overriding the ros_distro
                new_track_cmd(track, copy_track='', overrides=overrides)
                tracks_dict = get_tracks_dict_raw()
        if track and track not in tracks_dict['tracks']:
            error("Given track '{0}' does not exist in release repository."
                  .format(track))
            error("Available tracks: " + str(tracks_dict['tracks'].keys()),
                  exit=True)
        elif not track:
            tracks = tracks_dict['tracks'].keys()
            # Error out if there are no tracks
            if len(tracks) == 0:
                error("Release repository has no tracks.")
                info("Manually clone the repository:")
                info("  git clone {0}".format(release_repo.get_url()))
                info("And then create a new track:")
                info("  git-bloom-config new <track name>")
                error("Run again after creating a track.", exit=True)
            # Error out if there is more than one track
            if len(tracks) != 1:
                error("No track specified and there is not just one track.")
                error("Please specify one of the available tracks: " +
                      str(tracks), exit=True)
            # Get the only track
            track = tracks[0]
        # Ensure the track is complete
        track_dict = tracks_dict['tracks'][track]
        update_track(track_dict)
        tracks_dict['tracks'][track] = track_dict
        write_tracks_dict_raw(tracks_dict)
        # Run the release
        info(fmt("@{gf}@!==> @|") +
             "Releasing '{0}' using release track '{1}'"
             .format(repository, track))
        cmd = 'git-bloom-release ' + str(track)
        info(fmt("@{bf}@!==> @|@!" + str(cmd)))
        try:
            subprocess.check_call(cmd, shell=True)
        except subprocess.CalledProcessError:
            error("Release failed, exiting.", exit=True)
        info(fmt(_success) +
             "Released '{0}' using release track '{1}' successfully"
             .format(repository, track))
        # Check for pushing
        if interactive:
            info("Releasing complete, push?")
            if not maybe_continue():
                error("User answered no to continue prompt, aborting.",
                      exit=True)
        # Push changes to the repository
        info(fmt("@{gf}@!==> @|") +
             "Pushing changes to release repository for '{0}'"
             .format(repository))
        cmd = 'git push --all'
        info(fmt("@{bf}@!==> @|@!" + str(cmd)))
        try:
            subprocess.check_call(cmd, shell=True)
        except subprocess.CalledProcessError:
            error("Pushing changes failed, would you like to add '--force' to 'git push --all'?")
            if not maybe_continue():
                error("Pushing changes failed, exiting.", exit=True)
            cmd += ' --force'
            info(fmt("@{bf}@!==> @|@!" + str(cmd)))
            try:
                subprocess.check_call(cmd, shell=True)
            except subprocess.CalledProcessError:
                error("Pushing changes failed, exiting.", exit=True)
        info(fmt(_success) + "Pushed changes successfully")
        # Push tags to the repository
        info(fmt("@{gf}@!==> @|") +
             "Pushing tags to release repository for '{0}'"
             .format(repository))
        cmd = 'git push --tags'
        info(fmt("@{bf}@!==> @|@!" + str(cmd)))
        try:
            subprocess.check_call(cmd, shell=True)
        except subprocess.CalledProcessError:
            error("Pushing changes failed, would you like to add '--force' to 'git push --tags'?")
            if not maybe_continue():
                error("Pushing tags failed, exiting.", exit=True)
            cmd += ' --force'
            info(fmt("@{bf}@!==> @|@!" + str(cmd)))
            try:
                subprocess.check_call(cmd, shell=True)
            except subprocess.CalledProcessError:
                error("Pushing tags failed, exiting.", exit=True)
        info(fmt(_success) + "Pushed tags successfully")
        # Propose github pull request
        info(fmt("@{gf}@!==> @|") +
             "Generating pull request to distro file located at '{0}'"
             .format(ROS_DISTRO_FILE).format(distro))
        generate_ros_distro_diff(track, repository, distro)
        info("In the future this will create a pull request for you, done for now...")
        info(fmt(_success) + "Pull request opened at: '{0}'".format('Not yet Implemented'))
Пример #27
0
def open_pull_request(track, repository, distro, distro_file_url=ROS_DISTRO_FILE):
    # Get the diff
    distro_file_url = distro_file_url.format(distro)
    distro_file_raw = fetch_distro_file(distro_file_url)
    distro_file = yaml.load(distro_file_raw)
    if repository in distro_file['repositories']:
        orig_version = distro_file['repositories'][repository].get('version', None)
    else:
        orig_version = None
    udiff_patch_file, updated_distro_file = generate_ros_distro_diff(track, repository, distro,
                                                                     distro_file_url, distro_file,
                                                                     distro_file_raw)
    if None in [udiff_patch_file, updated_distro_file]:
        # There were no changes, no pull request required
        return None
    version = distro_file['repositories'][repository]['version']
    # Determine if the distro file is hosted on github...
    distro_file_url = distro_file_url.format(distro)
    gh_org, gh_repo, gh_branch, gh_path = get_gh_info(distro_file_url)
    if None in [gh_org, gh_repo, gh_branch, gh_path]:
        warning("Automated pull request only available via github.com")
        return
    # Determine if we have a .netrc file
    gh_username = None
    try:
        netrc_hosts = netrc.netrc().hosts
    except Exception as e:
        error("Failed to parse ~/.netrc file: {0}".format(e))
        warning("Skipping the pull request...")
        return
    for host in netrc_hosts.keys():
        if 'github.com' in host:
            gh_username = netrc_hosts[host][0]
            gh_password = netrc_hosts[host][2]
    if None in [gh_username, gh_password]:
        error("Either the github username or github password is not set in the ~/.netrc file.")
        warning("Skipping the pull request...")
        return
    # Check for fork
    info(fmt("@{bf}@!==> @|@!Checking for rosdistro fork on github..."))
    gh_user_repos = fetch_github_api('https://api.github.com/users/{0}/repos'.format(gh_username))
    if gh_user_repos is None:
        error("Failed to get a list of repositories for user: '******'".format(gh_username))
        warning("Skipping the pull request...")
        return
    if 'rosdistro' not in [x['name'] for x in gh_user_repos if 'name' in x]:
        warning("Github user '{0}' does not have a fork ".format(gh_username) +
                "of the {0}:{1} repository, create one?".format(gh_org, gh_repo))
        if not maybe_continue():
            warning("Skipping the pull request...")
            return
        # Create a fork
        create_fork(gh_org, gh_repo, gh_username, gh_password)
    # Clone the fork
    info(fmt("@{bf}@!==> @|@!" + "Cloning {0}/{1}...".format(gh_username, gh_repo)))
    temp_dir = tempfile.mkdtemp()
    new_branch = None
    title = "{0}: {1} in '{2}' [bloom]".format(repository, version, os.path.basename(gh_path))
    body = """\
Increasing version of package(s) in repository `{0}`:
- previous version: `{1}`
- new version: `{2}`
- distro file: `{3}`
- bloom version: `{4}`
""".format(repository, orig_version or 'null', version, gh_path, bloom.__version__)
    with change_directory(temp_dir):
        def _my_run(cmd):
            info(fmt("@{bf}@!==> @|@!" + str(cmd)))
            out = check_output(cmd, stderr=subprocess.STDOUT, shell=True)
            if out:
                info(out, use_prefix=False)
        _my_run('git clone https://github.com/{0}/{1}.git'.format(gh_username, gh_repo))
        with change_directory(gh_repo):
            _my_run('git remote add bloom https://github.com/{0}/{1}.git'.format(gh_org, gh_repo))
            _my_run('git remote update')
            _my_run('git fetch')
            track_branches()
            branches = get_branches()
            new_branch = 'bloom-patch-{0}'
            count = 0
            while new_branch.format(count) in branches:
                count += 1
            new_branch = new_branch.format(count)
            # Final check
            info(fmt("@{cf}Pull Request Title: @{yf}" + title))
            info(fmt("@{cf}Pull Request Body : \n@{yf}" + body))
            msg = fmt("@!Open a @|@{cf}pull request@| @!@{kf}from@| @!'@|@!@{bf}" +
                      "{gh_username}/{gh_repo}:{new_branch}".format(**locals()) +
                      "@|@!' @!@{kf}into@| @!'@|@!@{bf}" +
                      "{gh_org}/{gh_repo}:{gh_branch}".format(**locals()) +
                      "@|@!'?")
            info(msg)
            if not maybe_continue():
                warning("Skipping the pull request...")
                return
            _my_run('git checkout -b {0} bloom/{1}'.format(new_branch, gh_branch))
            with open('{0}'.format(gh_path), 'w') as f:
                info(fmt("@{bf}@!==> @|@!Writing new distribution file: ") + str(gh_path))
                f.write(updated_distro_file)
            _my_run('git add {0}'.format(gh_path))
            _my_run('git commit -m "{0}"'.format(title))
            _my_run('git push origin {0}'.format(new_branch))
    # Open the pull request
    return create_pull_request(gh_org, gh_repo, gh_username, gh_password, gh_branch, new_branch, title, body)