Пример #1
0
def update_crate_repositories_branches(args, temp_dir, repositories):
    write_msg('=> Merging "master" branches into "crate" branches...')
    for repo in repositories:
        merging_branches(repo, temp_dir, "master")
    write_msg('Done!')

    write_msg('=> Updating [crate] crates version...')
    for crate in args.crates:
        crate = crate['crate']
        if args.specified_crate is not None and crate[
                'crate'] != args.specified_crate:
            continue
        if update_crate_version(crate["repository"], crate["crate"],
                                crate["path"], temp_dir,
                                args.specified_crate) is False:
            write_error('The update for the "{}" crate failed...'.format(
                crate["crate"]))
            return False
    write_msg('Done!')

    write_msg('=> Committing{} to the "{}" branch...'.format(
        " and pushing" if args.no_push is False else "",
        consts.CRATE_TMP_BRANCH))
    for repo in repositories:
        commit(repo, temp_dir, "Update versions [ci skip]")
        if args.no_push is False:
            push(repo, temp_dir, consts.CRATE_TMP_BRANCH)
    write_msg('Done!')
    if args.no_push is False:
        write_msg('=> Creating PRs on crate branch...')
        for repo in repositories:
            create_pull_request(repo, consts.CRATE_TMP_BRANCH, "crate",
                                args.token)
        write_msg('Done!')
    return True
Пример #2
0
def update_crates_versions(args, temp_dir, repositories):
    write_msg('=> Updating [master] crates version...')
    for crate in args.crates:
        update_type = crate['up-type']
        crate = crate['crate']
        if args.specified_crate is not None and crate[
                'crate'] != args.specified_crate:
            continue
        if update_repo_version(crate["repository"], crate["crate"],
                               crate["path"], temp_dir, update_type,
                               args.badges_only or args.tags_only) is False:
            write_error('The update for the "{}" crate failed...'.format(
                crate["crate"]))
            return False
    write_msg('Done!')
    if args.badges_only is False and args.tags_only is False:
        write_msg('=> Committing{} to the "{}" branch...'.format(
            " and pushing" if args.no_push is False else "",
            consts.MASTER_TMP_BRANCH))
        for repo in repositories:
            commit(repo, temp_dir, "Update versions [ci skip]")
            if args.no_push is False:
                push(repo, temp_dir, consts.MASTER_TMP_BRANCH)
        write_msg('Done!')

        if args.no_push is False:
            write_msg('=> Creating PRs on master branch...')
            for repo in repositories:
                create_pull_request(repo, consts.MASTER_TMP_BRANCH, "master",
                                    args.token)
            write_msg('Done!')
    return True
Пример #3
0
def change_command(user):
    ws = get_worksheet()
    stored_row = ""
    try:
        if "-r" in sys.argv:
            row_number = int(get_argument(sys.argv, "-r"))
            if row_number and row_number >= 2:
                selected_row = ws.row_values(row_number)
                if user == selected_row[0]:
                    stored_row = selected_row
                else:
                    write_error("You can't edit others information")
                    exit()
            else:
                write_error("Invalid row")
                exit()
        else:
            row_number = get_users_last_row(ws, user)
            stored_row = ws.row_values(row_number)

        display_loading_message("Updating info", "Information updated")
        new_date = get_date() if "-d" in sys.argv else stored_row[1]
        new_message = get_argument(
            sys.argv, "-m") if "-m" in sys.argv else stored_row[2]
        new_description = get_argument(sys.argv, "-t") if "-t" in sys.argv else stored_row[3] \
            if len(stored_row) >= 4 else ""

        stored_row = [stored_row[0], new_date, new_message, new_description]
        update_row(ws, stored_row, row_number)

        hide_loading_message_with_error(False)
    except Exception:
        hide_loading_message_with_error(True)
        exit()
Пример #4
0
def switch(command, user, is_sudo):
    try:
        if command == "init":
            init_app()
        elif command == "write":
            startup_check()
            write_command(user)
        elif command == "read":
            startup_check()
            read_command()
        elif command == "share":
            startup_check()
            share_command()
        elif command == "change":
            startup_check()
            change_command(user)
        elif command == "version":
            version_command()
        elif command == "help":
            help_command()
        elif command == "delete":
            startup_check()
            delete_command(user, is_sudo)
        elif command == "reset":
            reset_command()
        else:
            write_error(
                "Command not found. For further informations use `servy help`")
    except KeyboardInterrupt:
        hide_loading_message_with_error(True, "\n")
Пример #5
0
def delete_command(user, is_sudo):
    ws = get_worksheet()

    if "-r" in sys.argv:
        row = int(get_argument(sys.argv, "-r"))
        if row >= 2:
            try:
                display_loading_message("Deleting message", "Message deleted")

                if int(is_sudo) != 0:
                    selected_row = ws.row_values(row)
                    if selected_row[0] and user != selected_row[0]:
                        hide_loading_message_with_error(
                            True,
                            "You cannot delete rows written by other users")
                        exit()

                delete_row(ws, row)
                hide_loading_message_with_error(False)
            except Exception:
                hide_loading_message_with_error(True)
        else:
            write_error("Invalid row")
    else:
        try:
            display_loading_message("Deleting message", "Message deleted")
            last_row = get_users_last_row(ws, user)
            delete_row(ws, last_row)
            hide_loading_message_with_error(False)
        except IndexError:
            hide_loading_message_with_error(
                True, "Error. No rows inserted by the current user")
Пример #6
0
def create_pull_request(repo_name, from_branch, target_branch, token):
    r = post_content(
        '{}/repos/{}/{}/pulls'.format(consts.GH_API_URL, consts.ORGANIZATION,
                                      repo_name), token,
        {
            'title':
            '[release] merging {} into {}'.format(from_branch, target_branch),
            'body':
            'cc @GuillaumeGomez @EPashkin @sdroege',
            'base':
            target_branch,
            'head':
            from_branch,
            'maintainer_can_modify':
            True
        })
    if r is None:
        write_error(
            "Pull request from {repo}/{from_b} to {repo}/{target} couldn't be created. You "
            "need to do it yourself... (url provided at the end)".format(
                repo=repo_name, from_b=from_branch, target=target_branch))
        input("Press ENTER once done to continue...")
        PULL_REQUESTS.append('|=> "{}/{}/{}/compare/{}...{}?expand=1"'.format(
            consts.GITHUB_URL, consts.ORGANIZATION, repo_name, target_branch,
            from_branch))
    else:
        write_msg("===> Pull request created: {}".format(r['html_url']))
        PULL_REQUESTS.append('> {}'.format(r['html_url']))
Пример #7
0
def update_version(version, update_type, section_name, place_type="section"):
    version_split = version.replace('"', '').split('.')
    if len(version_split) != 3:
        # houston, we've got a problem!
        write_error('Invalid version in {} "{}": {}'.format(
            place_type, section_name, version))
        return None
    if update_type == UpdateType.MINOR:
        version_split[update_type] = str(int(version_split[update_type]) + 1)
    elif update_type == UpdateType.MEDIUM:
        version_split[update_type] = str(int(version_split[update_type]) + 1)
        version_split[UpdateType.MINOR] = '0'
    else:
        i = 0
        for c in version_split[update_type]:
            if c >= '0' and c <= '9':
                break
            i += 1
        if i >= len(c):
            return None
        s = version_split[update_type][i:]
        version_split[update_type] = '{}{}'.format(
            version_split[update_type][:i], str(int(s) + 1))
        version_split[UpdateType.MEDIUM] = '0'
        version_split[UpdateType.MINOR] = '0'
    return '"{}"'.format('.'.join(version_split))
Пример #8
0
def update_doc_content_repository(repositories, temp_dir, token, no_push,
                                  args):
    if clone_repo(consts.DOC_CONTENT_REPO, temp_dir) is False:
        input('Try to fix the problem then press ENTER to continue...')
    write_msg("Done!")
    repo_path = join(temp_dir, consts.DOC_CONTENT_REPO)
    write_msg("=> Generating documentation for crates...")
    for repo in repositories:
        current = None
        for crate in args.crates:
            crate = crate['crate']
            if crate['repository'] == repo:
                current = crate
                break
        if current is None:
            input(
                'No repository matches "{}", something is weird. (Press ENTER TO CONTINUE)'
            )
            continue
        if current.get("doc", True) is False:
            continue
        write_msg('==> Generating documentation for "{}"'.format(current))
        path = join(temp_dir, current['repository'])
        command = [
            'bash', '-c', 'cd {} && make doc && mv vendor.md {}'.format(
                path, join(repo_path, current['crate']))
        ]
        if not exec_command_and_print_error(command):
            input("Fix the error and then press ENTER")
    write_msg('Done!')
    write_msg('Committing "{}" changes...'.format(consts.DOC_CONTENT_REPO))
    commit(consts.DOC_CONTENT_REPO, temp_dir, "Update vendor files")
    if no_push is False:
        push(consts.DOC_CONTENT_REPO, temp_dir, consts.MASTER_TMP_BRANCH)

    # We always make minor releases in here, no need for a more important one considering we don't
    # change the API.
    if update_repo_version(consts.DOC_CONTENT_REPO, consts.DOC_CONTENT_REPO,
                           "", temp_dir, UpdateType.MINOR, False) is False:
        write_error('The update for the "{}" crate failed...'.format(
            consts.DOC_CONTENT_REPO))
        input('Fix the error and then press ENTER')
    commit(consts.DOC_CONTENT_REPO, temp_dir, "Update version")
    if no_push is False:
        push(consts.DOC_CONTENT_REPO, temp_dir, consts.MASTER_TMP_BRANCH)
        create_pull_request(consts.DOC_CONTENT_REPO, consts.MASTER_TMP_BRANCH,
                            "master", token, False)
        input((
            'All done with the "{}" update: please merge the PR then press ENTER so the '
            'publication can performed...').format(consts.DOC_CONTENT_REPO))
        publish_crate(consts.DOC_CONTENT_REPO,
                      "",
                      temp_dir,
                      consts.DOC_CONTENT_REPO,
                      checkout_branch='master')
        write_msg('Ok all done! We can move forward now!')
    else:
        write_msg((
            'All with "{}", you still need to publish a new version if you want the changes '
            'to be taken into account').format(consts.DOC_CONTENT_REPO))
Пример #9
0
def share_command():
    if "-l" in sys.argv:
        ss = get_spreadsheet()
        print_permissions(ss)
    elif "-a" in sys.argv:
        email = get_argument(sys.argv, "-a")
        if validate_email(email):
            try:
                display_loading_message("Adding permission", "Permission added")
                ss = get_spreadsheet()
                share_spreadsheet(ss, email)
                hide_loading_message_with_error(False)
            except Exception:
                hide_loading_message_with_error(True)
        else:
            write_error("Invalid email: " + email)
    elif "-d" in sys.argv:
        email = get_argument(sys.argv, "-d")
        if validate_email(email):
            try:
                display_loading_message("Removing permission", "Permission removed")
                ss = get_spreadsheet()
                ss.remove_permissions(email)
                hide_loading_message_with_error(False)
            except Exception:
                hide_loading_message_with_error(True)
        else:
            write_error("Invalid email: " + email)
Пример #10
0
    def handle_error(self, req, client, addr, exc):
        request_start = time.time()
        addr = addr or ('', -1)

        if isinstance(exc, (InvalidRequestLine, InvalidRequestMethod,
                            InvalidHTTPVersion, InvalidHeader, InvalidHeaderName,
                            LimitRequestLine, LimitRequestHeaders,
                            InvalidProxyLine, ForbiddenProxyRequest,
                            SSLError)):
            status_int = 400
            reason = "Bad Request"

            if isinstance(exc, InvalidRequestLine):
                msg = "Invalid request line: {!s}".format(exc)
            elif isinstance(exc, InvalidRequestMethod):
                msg = "Invalid method: {!s}".format(exc)
            elif isinstance(exc, InvalidHTTPVersion):
                msg = "Invalid http version: {!s}".format(exc)
            elif isinstance(exc, (InvalidHeaderName, InvalidHeader,)):
                msg = str(exc)
                if not req and hasattr(exc, "req"):
                    req = exc.req
            elif isinstance(exc, LimitRequestLine):
                msg = str(exc)
            elif isinstance(exc, LimitRequestHeaders):
                msg = "Error parsing headers: {!s}".format(exc)
            elif isinstance(exc, SSLError):
                reason = "Forbidden"
                msg = str(exc)
                status_int = 403

            msg = "Invalid request from ip={ip}: {error}"
            self.log.debug(msg.format(ip=addr[0], error=str(exc)))
        else:
            if hasattr(req, 'uri'):
                self.log.exception("Error hanling request {!s}".format(req.uri))
            status_int = 500
            reason = "Internal Server Error"
            msg = ""

        if req is not None:
            request_time = time.time() - request_start
            environ = default_environ(req, client, self.config)
            environ['REMOTE_ADDR'] = addr[0]
            environ['REMOTE_PORT'] = str(addr[1])
            resp = Response(req, client, self.config)
            resp.status = "{} {}".format(status_int, reason)
            resp.length = len(msg)
            self.log.access(resp, req, environ, request_time)

        try:
            write_error(client, status_int, reason, msg)
        except Exception:
            self.log.debug("Failed to send error message.")
Пример #11
0
def build_docs(repo_name, temp_dir):
    path = join(temp_dir, repo_name)
    features = get_features(join(path, 'Cargo.toml'))
    command = [
        'bash', '-c',
        'cd {} && cargo doc --no-default-features --features "{}"'.format(
            path, features)
    ]
    if not exec_command_and_print_error(command):
        input(
            "Couldn't generate docs! Try to fix it and then press ENTER to continue..."
        )
    doc_folder = join(path, 'target/doc')
    try:
        file_list = ' '.join([
            '"{}"'.format(f) for f in listdir(doc_folder)
            if isfile(join(doc_folder, f))
        ])
    except Exception as e:
        write_error('Error occured in build docs: {}'.format(e))
        input(
            "It seems like the \"{}\" folder doesn't exist. Try to fix it then press ENTER..."
            .format(doc_folder))
    command = [
        'bash', '-c', 'cd {} && cp -r "{}" src/{} {} "{}"'.format(
            doc_folder, repo_name.replace('-', '_'),
            repo_name.replace('-', '_'), file_list,
            join(temp_dir, consts.DOC_REPO))
    ]
    if not exec_command_and_print_error(command):
        input(
            "Couldn't copy docs! Try to fix it and then press ENTER to continue..."
        )
    lines = get_file_content(join(path,
                                  'target/doc/search-index.js')).split('\n')
    before = True
    fill_extras = len(SEARCH_INDEX_BEFORE) == 0
    for line in lines:
        if line.startswith('searchIndex['):
            before = False
            # We need to be careful in here if we're in a sys repository (which should never be the
            # case!).
            if line.startswith('searchIndex["{}"]'.format(
                    repo_name.replace('-', '_'))):
                SEARCH_INDEX.append(line)
        elif fill_extras is True:
            if before is True:
                SEARCH_INDEX_BEFORE.append(line)
            else:
                SEARCH_INDEX_AFTER.append(line)
    input(
        "Couldn't find \"{}\" in `searchIndex.js`! Try to fix it and then press ENTER to \
          continue...".format(repo_name.replace('-', '_')))
Пример #12
0
def append_default_spreadsheet(credentials_path, default_spreadsheet):
    with open(credentials_path, "r+") as credentials:
        try:
            credentials_json = load(credentials)
            credentials_json["default_spreadsheet"] = default_spreadsheet
            credentials.seek(0, 0)
            dump(credentials_json, credentials)
            credentials.truncate()
        except decoder.JSONDecodeError:
            write_error("credentials.json does not contain a valid json")
            reset_command()
            exit()
Пример #13
0
def update_gtk_rs_blog(args, temp_dir):
    if args.doc_only is True or args.tags_only is True:
        return
    write_msg('=> Updating blog...')
    if update_badges(consts.BLOG_REPO, temp_dir,
                     args.specified_crate) is False:
        write_error("Error when trying to update badges...")
    elif args.no_push is False:
        commit_and_push(consts.BLOG_REPO, temp_dir, "Update versions",
                        consts.MASTER_TMP_BRANCH)
        create_pull_request(consts.BLOG_REPO, consts.MASTER_TMP_BRANCH,
                            "master", args.token)
    write_msg('Done!')
Пример #14
0
def generate_new_tag(repository, temp_dir, specified_crate):
    versions = {}
    version = None
    # In some repositories (like sys), there are more than one crates. In such case, we try to
    # get the most common version number and then we create the tag from there.
    #
    # First, we get all versions.
    for crate in consts.CRATE_LIST:
        if crate['repository'] == repository:
            versions[crate['crate']] = CRATES_VERSION[crate['crate']]
            if crate['crate'].endswith('-sys') or crate['crate'].endswith(
                    '-sys-rs'):
                version = CRATES_VERSION[crate['crate']]
    if (specified_crate is not None
            and (specified_crate.endswith('-sys')
                 or specified_crate.endswith('-sys-rs'))):
        write_msg(
            'Seems like "{}" is part of a repository with multiple crates so no \
                   tag generation this time...'.format(specified_crate))
        return

    if version is None:
        most_common = {}
        # Now we get how many crates have this version.
        for version in versions:
            if versions[version] in most_common:
                most_common[versions[version]] += 1
            else:
                most_common[versions[version]] = 1
        # Now we get the "lowest" version that will be used as default tag name.
        for common in most_common:
            if version is None or compare_versions(common, version) < 0:
                version = common
        # And now we get the most common tag name.
        for common in most_common:
            if version is None or most_common[version] < most_common[common]:
                version = common
        if version is None:
            write_error(
                'Something impossible happened for "{}": no version can be tagged...'
                .format(repository))
            input(
                'If you think you can do better, go ahead! (In "{}") Then press ENTER to continue'
                .format(join(temp_dir, repository)))
            return
    write_msg('==> Creating new tag "{}" for repository "{}"...'.format(
        version, repository))
    create_tag_and_push(version, repository, temp_dir)
Пример #15
0
def update_version(version, update_type, section_name, place_type="section"):
    version_split = version.replace('"', '').split('.')
    if len(version_split) != 3:
        # houston, we've got a problem!
        write_error('Invalid version in {} "{}": {}'.format(
            place_type, section_name, version))
        return None
    if update_type == UpdateType.MINOR:
        version_split[update_type] = str(int(version_split[update_type]) + 1)
    elif update_type == UpdateType.MEDIUM:
        version_split[update_type] = str(int(version_split[update_type]) + 1)
        version_split[UpdateType.MINOR] = '0'
    else:
        version_split[update_type] = str(int(version_split[update_type]) + 1)
        version_split[UpdateType.MEDIUM] = '0'
        version_split[UpdateType.MINOR] = '0'
    return '"{}"'.format('.'.join(version_split))
Пример #16
0
def write_command(user):
    if "-m" in sys.argv:
        try:
            ws = get_worksheet()
            current_row = next_available_row(ws)
            display_loading_message("Saving message", "Message saved")
            message = get_argument(sys.argv, "-m")
            set_name_date(current_row, user, ws)
            ws.update_acell("C{}".format(current_row), message)

            if "-t" in sys.argv:
                description = get_argument(sys.argv, "-t")
                ws.update_acell("D{}".format(current_row), description)

            hide_loading_message_with_error(False)
        except Exception:
            hide_loading_message_with_error(True)
    else:
        write_error("A message argument should be specified")
Пример #17
0
def end_docs_build(temp_dir):
    path = join(temp_dir, consts.DOC_REPO)
    revert_changes(consts.DOC_REPO, temp_dir,
                   ['COPYRIGHT.txt', 'LICENSE-APACHE.txt', 'LICENSE-MIT.txt'])
    try:
        with open(join(path, 'search-index.js'), 'w') as file:
            file.write('\n'.join(SEARCH_INDEX_BEFORE) + '\n')
            if SEARCH_INDEX[-1].endswith("},\\"):
                SEARCH_INDEX[-1] = SEARCH_INDEX[
                    -1][:-2] + '\\'  # we remove the last comma
            file.write('\n'.join(SEARCH_INDEX))
            file.write('\n'.join(SEARCH_INDEX_AFTER))
        add_to_commit(consts.DOC_REPO, temp_dir, ['.'])
    except Exception as err:
        write_error('An exception occured in "end_docs_build": {}'.format(err))
        input("Press ENTER to continue...")
    input(
        'If you want to prevent "{}" to be updated, now is the good time! Press ENTER to '
        'continue...'.format(join(path, "main.js")))
Пример #18
0
def clone_repositories(args, temp_dir):
    write_msg('=> Cloning the repositories...')
    repositories = []
    for crate in args.crates:
        crate = crate['crate']
        if args.specified_crate is not None and crate[
                'crate'] != args.specified_crate:
            continue
        if crate["repository"] not in repositories:
            repositories.append(crate["repository"])
            if clone_repo(crate["repository"], temp_dir) is False:
                write_error('Cannot clone the "{}" repository...'.format(
                    crate["repository"]))
                return []
    if len(repositories) < 1:
        write_msg('No crate "{}" found. Aborting...'.format(
            args.specified_crate))
        return []
    if args.doc_only is False:
        if clone_repo(consts.BLOG_REPO, temp_dir, depth=1) is False:
            write_error('Cannot clone the "{}" repository...'.format(
                consts.BLOG_REPO))
            return []
    if clone_repo(consts.DOC_REPO, temp_dir, depth=1) is False:
        write_error('Cannot clone the "{}" repository...'.format(
            consts.DOC_REPO))
        return []
    write_msg('Done!')
    return repositories
Пример #19
0
def main(argv):
    try:
        opts, args = getopt.getopt(argv, "ht:m:c:", [
            "help", "token=", "mode=", "no-push", "doc-only", "crate",
            "badges-only"
        ])
    except getopt.GetoptError:
        write_help()
        sys.exit(2)

    token = None
    mode = None
    no_push = False
    doc_only = False
    specified_crate = None
    badges_only = False
    for opt, arg in opts:
        if opt in ('-h', '--help'):
            write_help()
            sys.exit(0)
        elif opt in ("-t", "--token"):
            token = arg
        elif opt in ("-m", "--mode"):
            mode = UpdateType.create_from_string(arg)
            if mode is None:
                write_error(
                    '{}: Invalid update type received. Accepted values: '
                    '(MINOR|MEDIUM|MAJOR)'.format(opt))
                sys.exit(3)
        elif opt in ("--no-push"):
            no_push = True
        elif opt in ("--doc-only"):
            doc_only = True
        elif opt in ("--badges-only"):
            badges_only = True
        elif opt in ('-c', '--crate'):
            specified_crate = arg
        else:
            write_msg('"{}": unknown option'.format(opt))
            write_msg('Use "-h" or "--help" to see help')
            sys.exit(0)
    if token is None and no_push is False:
        write_error('Missing token argument.')
        sys.exit(4)
    if mode is None and doc_only is False and badges_only is False:
        write_error('Missing update type argument.')
        sys.exit(5)
    start(mode, token, no_push, doc_only, specified_crate, badges_only)
Пример #20
0
def start(update_type, token, no_push, doc_only, specified_crate, badges_only):
    write_msg('=> Creating temporary directory...')
    with TemporaryDirectory() as temp_dir:
        write_msg('Temporary directory created in "{}"'.format(temp_dir))
        write_msg('=> Cloning the repositories...')
        repositories = []
        for crate in consts.CRATE_LIST:
            if specified_crate is not None and crate[
                    'crate'] != specified_crate:
                continue
            if crate["repository"] not in repositories:
                repositories.append(crate["repository"])
                if clone_repo(crate["repository"], temp_dir) is False:
                    write_error('Cannot clone the "{}" repository...'.format(
                        crate["repository"]))
                    return
        if len(repositories) < 1:
            write_msg(
                'No crate "{}" found. Aborting...'.format(specified_crate))
            return
        if doc_only is False:
            if clone_repo(consts.BLOG_REPO, temp_dir, depth=1) is False:
                write_error('Cannot clone the "{}" repository...'.format(
                    consts.BLOG_REPO))
                return
        if clone_repo(consts.DOC_REPO, temp_dir, depth=1) is False:
            write_error('Cannot clone the "{}" repository...'.format(
                consts.DOC_REPO))
            return
        write_msg('Done!')

        if doc_only is False:
            write_msg('=> Updating [master] crates version...')
            for crate in consts.CRATE_LIST:
                if specified_crate is not None and crate[
                        'crate'] != specified_crate:
                    continue
                if update_repo_version(crate["repository"], crate["crate"],
                                       crate["path"], temp_dir, update_type,
                                       badges_only) is False:
                    write_error(
                        'The update for the "{}" crate failed...'.format(
                            crate["crate"]))
                    return
            write_msg('Done!')

            if badges_only is False:
                write_msg('=> Committing{} to the "{}" branch...'.format(
                    " and pushing" if no_push is False else "",
                    consts.MASTER_TMP_BRANCH))
                for repo in repositories:
                    commit(repo, temp_dir, "Update versions [ci skip]")
                    if no_push is False:
                        push(repo, temp_dir, consts.MASTER_TMP_BRANCH)
                write_msg('Done!')

                if no_push is False:
                    write_msg('=> Creating PRs on master branch...')
                    for repo in repositories:
                        create_pull_request(repo, consts.MASTER_TMP_BRANCH,
                                            "master", token)
                    write_msg('Done!')

                write_msg('=> Building blog post...')
                build_blog_post(repositories, temp_dir, token)
                write_msg('Done!')

        write_msg('=> Checking out "crate" branches')
        for repo in repositories:
            checkout_target_branch(repo, temp_dir, "crate")
        write_msg('Done!')

        if doc_only is False and badges_only is False:
            write_msg('=> Merging "master" branches into "crate" branches...')
            for repo in repositories:
                merging_branches(repo, temp_dir, "master")
            write_msg('Done!')

            write_msg('=> Updating [crate] crates version...')
            for crate in consts.CRATE_LIST:
                if specified_crate is not None and crate[
                        'crate'] != specified_crate:
                    continue
                if update_crate_version(crate["repository"], crate["crate"],
                                        crate["path"], temp_dir,
                                        specified_crate) is False:
                    write_error(
                        'The update for the "{}" crate failed...'.format(
                            crate["crate"]))
                    return
            write_msg('Done!')

            write_msg('=> Committing{} to the "{}" branch...'.format(
                " and pushing" if no_push is False else "",
                consts.CRATE_TMP_BRANCH))
            for repo in repositories:
                commit(repo, temp_dir, "Update versions [ci skip]")
                if no_push is False:
                    push(repo, temp_dir, consts.CRATE_TMP_BRANCH)
            write_msg('Done!')

            if no_push is False:
                write_msg('=> Creating PRs on crate branch...')
                for repo in repositories:
                    create_pull_request(repo, consts.CRATE_TMP_BRANCH, "crate",
                                        token)
                write_msg('Done!')

                write_msg('+++++++++++++++')
                write_msg('++ IMPORTANT ++')
                write_msg('+++++++++++++++')
                write_msg(
                    'Almost everything has been done. Take a deep breath, check for opened '
                    'pull requests and once done, we can move forward!')
                write_msg("\n{}\n".format('\n'.join(PULL_REQUESTS)))
                PULL_REQUESTS.append('=============')
                input('Press ENTER to continue...')
                write_msg('=> Publishing crates...')
                for crate in consts.CRATE_LIST:
                    if specified_crate is not None and crate[
                            'crate'] != specified_crate:
                        continue
                    publish_crate(crate["repository"], crate["path"], temp_dir,
                                  crate['crate'])
                write_msg('Done!')

                write_msg('=> Creating PR for examples repository')
                create_pull_request("examples", "pending", "master", token)
                write_msg('Done!')

                write_msg("=> Generating tags...")
                for repo in repositories:
                    generate_new_tag(repo, temp_dir, specified_crate)
                write_msg('Done!')

        if badges_only is False:
            write_msg(
                '=> Preparing doc repo (too much dark magic in here urg)...')
            cleanup_doc_repo(temp_dir)
            write_msg('Done!')

            write_msg('=> Building docs...')
            for repo in repositories:
                if repo != "sys":  # Maybe we should generate docs for sys crates as well?
                    write_msg('-> Building docs for {}...'.format(repo))
                    build_docs(repo, temp_dir)
            end_docs_build(temp_dir)
            write_msg('Done!')

            write_msg('=> Committing{} docs to the "{}" branch...'.format(
                " and pushing" if no_push is False else "",
                consts.CRATE_TMP_BRANCH))
            commit(consts.DOC_REPO, temp_dir, "Regen docs")
            if no_push is False:
                push(consts.DOC_REPO, temp_dir, consts.CRATE_TMP_BRANCH)
                create_pull_request(consts.DOC_REPO, consts.CRATE_TMP_BRANCH,
                                    "gh-pages", token)
                write_msg("New pull request(s):\n\n{}\n".format(
                    '\n'.join(PULL_REQUESTS)))
            write_msg('Done!')

        if doc_only is False:
            write_msg('=> Updating blog...')
            if update_badges(consts.BLOG_REPO, temp_dir,
                             specified_crate) is False:
                write_error("Error when trying to update badges...")
            elif no_push is False:
                commit_and_push(consts.BLOG_REPO, temp_dir, "Update versions",
                                consts.MASTER_TMP_BRANCH)
                create_pull_request(consts.BLOG_REPO, consts.MASTER_TMP_BRANCH,
                                    "master", token)
            write_msg('Done!')

        write_msg('Seems like most things are done! Now remains:')
        write_msg(
            " * Check generated docs for all crates (don't forget to enable features!)."
        )
        input(
            'Press ENTER to leave (once done, the temporary directory "{}" will be destroyed)'
            .format(temp_dir))
Пример #21
0
def build_blog_post(repositories, temp_dir, token):
    content = '''---
layout: post
author: {}
title: {}
categories: [front, crates]
date: {}
---

* Write intro here *

### Changes

For the interested ones, here is the list of the (major) changes:

'''.format(input('Enter author name: '), input('Enter title: '),
           time.strftime("%Y-%m-%d %H:00:00 +0000"))
    contributors = []
    git = Github(token)
    oldest_date = None
    for repo in repositories:
        checkout_target_branch(repo, temp_dir, "crate")
        success, out, err = get_last_commit_date(repo, temp_dir)
        if not success:
            write_msg("Couldn't get PRs for '{}': {}".format(repo, err))
            continue
        max_date = datetime.date.fromtimestamp(int(out))
        if oldest_date is None or max_date < oldest_date:
            oldest_date = max_date
        write_msg("Gettings merged PRs from {}...".format(repo))
        merged_prs = git.get_pulls(repo,
                                   consts.ORGANIZATION,
                                   'closed',
                                   max_date,
                                   only_merged=True)
        write_msg("=> Got {} merged PRs".format(len(merged_prs)))
        if len(merged_prs) < 1:
            continue
        repo_url = '{}/{}/{}'.format(consts.GITHUB_URL, consts.ORGANIZATION,
                                     repo)
        content += '[{}]({}):\n\n'.format(repo, repo_url)
        content += write_merged_prs(merged_prs, contributors, repo_url)

    write_msg("Gettings merged PRs from gir...")
    merged_prs = git.get_pulls('gir',
                               consts.ORGANIZATION,
                               'closed',
                               oldest_date,
                               only_merged=True)
    write_msg("=> Got {} merged PRs".format(len(merged_prs)))
    if len(merged_prs) > 0:
        repo_url = '{}/{}/{}'.format(consts.GITHUB_URL, consts.ORGANIZATION,
                                     'gir')
        content += (
            'All this was possible thanks to the [gtk-rs/gir]({}) project as well:\n\n'
            .format(repo_url))
        content += write_merged_prs(merged_prs, contributors, repo_url)

    content += 'Thanks to all of our contributors for their (awesome!) work for this release:\n\n'
    content += '\n'.join([
        ' * [@{}]({}/{})'.format(contributor, consts.GITHUB_URL, contributor)
        for contributor in contributors
    ])
    content += '\n'

    file_name = join(
        join(temp_dir, consts.BLOG_REPO),
        '_posts/{}-new-release.md'.format(time.strftime("%Y-%m-%d")))
    try:
        with open(file_name, 'w') as outfile:
            outfile.write(content)
            write_msg('New blog post written into "{}".'.format(file_name))
        add_to_commit(consts.BLOG_REPO, temp_dir, [file_name])
        commit(consts.BLOG_REPO, temp_dir, "Add new blog post")
    except Exception as e:
        write_error('build_blog_post failed: {}'.format(e))
        write_msg(
            '\n=> Here is the blog post content:\n{}\n<='.format(content))
Пример #22
0
    def apply_config(self):
        utils.log("Applying settings to {}".format(utils.CONFIG_PATH))
        config = OrderedDict()

        overclock_preset = utils.get_setting('overclock_preset')
        utils.log("Using {} overclock settings".format(overclock_preset))
        if overclock_preset == 'Custom':
            for prop in utils.OVERCLOCK_PRESET_PROPERTIES:
                config[prop] = utils.get_property_setting(prop)
        elif overclock_preset in utils.OVERCLOCK_PRESETS:
            config = OrderedDict(
                zip(utils.OVERCLOCK_PRESET_PROPERTIES,
                    utils.OVERCLOCK_PRESETS[overclock_preset]))

        for prop in utils.OTHER_PROPERTIES:
            value = utils.get_property_setting(prop)
            if value is not None:
                config[prop] = value

        if ('force_turbo' in config and config['force_turbo'] == 1
                and 'over_voltage' in config and config['over_voltage'] > 0):
            if not xbmcgui.Dialog().yesno(
                    "OpenELEC RPi Config WARNING!!",
                    "Overvolting with dynamic overclock disabled",
                    "will void your warranty!!",
                    "Continue, or fix by enabling dynamic overclock?", "Fix",
                    "Continue"):
                utils.log("Enabling dynamic overclock")
                config['force_turbo'] = 0
            else:
                utils.log("Warranty warning was ignored")

        if 'max_usb_current' in config and config['max_usb_current'] == 1:
            if not xbmcgui.Dialog().yesno(
                    "OpenELEC RPi Config WARNING!",
                    "To output 1.2A from the USB ports",
                    "you will need to use a good 2A power supply.",
                    "Are you sure you want to set max_usb_current?"):
                config['max_usb_current'] = 0

        updated = False
        if os.path.isfile(utils.CONFIG_PATH):
            with open(utils.CONFIG_PATH, 'r') as f:
                config_txt = f.read()

            config_txt_new = config_txt

            for prop, value in config.iteritems():
                utils.log("==== {} ====".format(prop))
                config_property_re = re.compile(
                    utils.CONFIG_SUB_RE_STR.format(prop), re.MULTILINE)
                match = config_property_re.search(config_txt)
                if match:
                    comment = bool(match.group(1))
                    old_value = match.group(3)
                    if value is None:
                        utils.log("  Commenting out")
                        config_txt_new = config_property_re.sub(
                            utils.comment_out, config_txt_new)
                        updated = True
                    elif comment or str(value) != old_value:
                        utils.log("  Setting to {}".format(value))
                        config_txt_new = config_property_re.sub(
                            partial(utils.replace_value, value),
                            config_txt_new)
                        updated = True
                    else:
                        utils.log("  Unchanged ({})".format(value))
                elif value is not None:
                    utils.log("  Appending {}={}".format(prop, value))
                    config_txt_new += utils.property_value_str(prop,
                                                               value) + '\n'
                    updated = True
        else:
            utils.log("A new {} will be created".format(utils.CONFIG_PATH))
            config_txt_new = utils.add_property_values(config)
            updated = True

        reboot_needed = False
        if updated:
            reboot_needed = True
            with utils.remount():
                try:
                    utils.write_config(config_txt_new)
                except (OSError, IOError) as e:
                    reboot_needed = False
                    utils.write_error(utils.CONFIG_PATH, str(e))

        if reboot_needed:
            if utils.restart_countdown(
                    "Ready to reboot to apply changes in config.txt"):
                xbmc.restart()
            else:
                utils.log("Cancelled reboot")
        else:
            utils.log("No changes made")
Пример #23
0
def init_app():
    print("Starting servy init process")
    print("............................")
    credentials_path = get_credentials_path()
    while True:
        default_spreadsheet = input("Insert the spreadsheets name\n")
        if default_spreadsheet:
            try:
                append_default_spreadsheet(credentials_path, default_spreadsheet)
                break
            except FileNotFoundError:
                write_error("\n'credentials.json' does not exists\n")
                print("Enter/Paste the downloaded content. Ctrl-D to save it.")
                try:
                    credentials_content = []
                    while True:
                        try:
                            line = input()
                        except EOFError:
                            break
                        credentials_content.append(line)

                    with open(credentials_path, "w+") as f:
                        for line in credentials_content:
                            f.write(line + "\n")

                    append_default_spreadsheet(credentials_path, default_spreadsheet)
                    break
                except PermissionError:
                    write_error("Permission error\n`servy init` should be run using root permissions\n")
                    exit()
                except Exception as e:
                    write_error("An error occured while saving credentials\n")
                    exit()
                    
    ss = get_spreadsheet()
    if ss and ss.sheet1:
        resume_ss = input(
            "A spreadsheet with this name already exists. Do you want to use it? Y/N\n")
        if resume_ss == "Y":
            print("Spreadsheet in use: " + default_spreadsheet)
            print("The following users has read permission to this file")
            print_permissions(ss)
            return

    print("Insert the email you want to have access to the spreadsheet")
    while True:
        email = input("Insert email: ")
        if email:
            if not validate_email(email):
                write_error("Invalid email")
            else:
                break

    display_loading_message("Creating spreadsheet " + default_spreadsheet, "Created spreadsheet " + default_spreadsheet)
    try:
        if ss:
            delete_spreadsheet(ss)
        ws = create_spreadsheet(email)
        init_spreadsheet(ws)
        hide_loading_message_with_error(False)
    except:
        hide_loading_message_with_error(True)
Пример #24
0
    def apply_config(self):
        utils.log("Applying settings to {}".format(utils.CONFIG_PATH))
        config = OrderedDict()

        overclock_preset = utils.get_setting('overclock_preset')
        utils.log("Using {} overclock settings".format(overclock_preset))
        if overclock_preset == 'Custom':
            for prop in utils.OVERCLOCK_PRESET_PROPERTIES:
                config[prop] = utils.get_property_setting(prop)
        elif overclock_preset in utils.OVERCLOCK_PRESETS:
            config = OrderedDict(zip(utils.OVERCLOCK_PRESET_PROPERTIES,
                                     utils.OVERCLOCK_PRESETS[overclock_preset]))

        for prop in utils.OTHER_PROPERTIES:
            value = utils.get_property_setting(prop)
            if value is not None:
                config[prop] = value
                
        if ('force_turbo' in config and config['force_turbo'] == 1 and
            'over_voltage' in config and config['over_voltage'] > 0):
            if not xbmcgui.Dialog().yesno("OpenELEC RPi Config WARNING!!",
                                          "Overvolting with dynamic overclock disabled",
                                          "will void your warranty!!",
                                          "Continue, or fix by enabling dynamic overclock?",
                                          "Fix",
                                          "Continue"):
                utils.log("Enabling dynamic overclock") 
                config['force_turbo'] = 0
            else:
                utils.log("Warranty warning was ignored")

        if 'max_usb_current' in config and config['max_usb_current'] == 1:
            if not xbmcgui.Dialog().yesno("OpenELEC RPi Config WARNING!",
                                          "To output 1.2A from the USB ports",
                                          "you will need to use a good 2A power supply.",
                                          "Are you sure you want to set max_usb_current?"):
                config['max_usb_current'] = 0

        updated = False
        if os.path.isfile(utils.CONFIG_PATH):
            with open(utils.CONFIG_PATH, 'r') as f:
                config_txt = f.read()

            config_txt_new = config_txt

            for prop, value in config.iteritems():
                utils.log("==== {} ====".format(prop))
                config_property_re = re.compile(utils.CONFIG_SUB_RE_STR.format(prop), re.MULTILINE)
                match = config_property_re.search(config_txt)
                if match:
                    comment = bool(match.group(1))
                    old_value = match.group(3)
                    if value is None:
                        utils.log("  Commenting out")
                        config_txt_new = config_property_re.sub(utils.comment_out, config_txt_new)
                        updated = True
                    elif comment or str(value) != old_value:
                        utils.log("  Setting to {}".format(value))
                        config_txt_new = config_property_re.sub(partial(utils.replace_value, value),
                                                                config_txt_new)
                        updated = True
                    else:
                        utils.log("  Unchanged ({})".format(value))
                elif value is not None:
                    utils.log("  Appending {}={}".format(prop, value))
                    config_txt_new += utils.property_value_str(prop, value) + '\n'
                    updated = True
        else:
            utils.log("A new {} will be created".format(utils.CONFIG_PATH))
            config_txt_new = utils.add_property_values(config)
            updated = True

        reboot_needed = False
        if updated:
            reboot_needed = True
            with utils.remount():
                try:
                    utils.write_config(config_txt_new)
                except (OSError, IOError) as e:
                    reboot_needed = False
                    utils.write_error(utils.CONFIG_PATH, str(e))
        
        if reboot_needed:
            if utils.restart_countdown("Ready to reboot to apply changes in config.txt"):
                xbmc.restart()
            else:
                utils.log("Cancelled reboot")
        else:
            utils.log("No changes made")
Пример #25
0
def try_init(message):
    write_error(message)
    if input("Do you want to init the app now? Y/N \n") == "Y":
        init_app()
    else:
        exit()
Пример #26
0
    def parse_arguments(argv):
        # pylint: disable=too-many-branches,too-many-return-statements
        try:
            opts = getopt.getopt(argv,
                                 "ht:m:c:",
                                 ["help", "token=", "mode=", "no-push", "doc-only", "crate",
                                  "badges-only", "tags-only", "pick-update-type-for-crates",
                                  "pick-crates", "blog-only"])[0] # second argument is "args"
        except getopt.GetoptError:
            write_help()
            return None

        instance = Arguments()

        pick_update_type_for_crates = False

        for opt, arg in opts:
            if opt in ('-h', '--help'):
                write_help()
                return None
            if opt in ("-t", "--token"):
                instance.token = arg
            elif opt in ("-m", "--mode"):
                instance.mode = UpdateType.create_from_string(arg)
                if instance.mode is None:
                    write_error('{}: Invalid update type received. Accepted values: '
                                '(MINOR|MEDIUM|MAJOR)'.format(opt))
                    return None
            elif opt == "--no-push":
                instance.no_push = True
            elif opt == "--doc-only":
                instance.doc_only = True
            elif opt == "--badges-only":
                instance.badges_only = True
            elif opt in ('-c', '--crate'):
                instance.specified_crate = arg
            elif opt == '--tags-only':
                instance.tags_only = True
            elif opt == '--blog-only':
                instance.blog_only = True
            elif opt == '--pick-crates':
                instance.crates = []
            elif opt == '--pick-update-type-for-crates':
                pick_update_type_for_crates = True
            else:
                write_msg('"{}": unknown option'.format(opt))
                write_msg('Use "-h" or "--help" to see help')
                return None
        if instance.token is None and instance.no_push is False and instance.blog_only is False:
            # In this case, I guess it's not an issue to not have a github token...
            write_error('Missing token argument.')
            return None
        # To make pylint happy.
        only_checks = (instance.doc_only is False or
                       instance.badges_only is False or
                       instance.tags_only is False or
                       instance.blog_only is False)
        if (instance.mode is None and
                only_checks is False and
                pick_update_type_for_crates is False):
            write_error('Missing update type argument.')
            return None

        default_updates = {"sys": None, "non-sys": None}
        if len(instance.crates) == 0:
            for crate in consts.CRATE_LIST:
                if get_answer('Do you want to include "{}" in this release?') is True:
                    instance.crates.append(
                        {
                            'up-type': get_up_type(crate['crate'],
                                                   instance.mode,
                                                   pick_update_type_for_crates,
                                                   default_updates),
                            'crate': crate,
                        })
            if ask_updates_confirmation(instance.crates) is False:
                write_msg('OK! Aborting then!')
                return None
        else:
            instance.crates = [
                {
                    'up-type': get_up_type(crate['crate'],
                                           instance.mode,
                                           pick_update_type_for_crates,
                                           default_updates),
                    'crate': crate,
                } for crate in instance.crates]
            if (pick_update_type_for_crates is True and
                    ask_updates_confirmation(instance.crates) is False):
                write_msg('OK! Aborting then!')
                return None
        return instance
Пример #27
0
def build_docs(repo_name, temp_dir, extra_path, crate_name):
    # pylint: disable=too-many-locals
    path = join(join(temp_dir, repo_name), extra_path)
    features = get_features(join(path, 'Cargo.toml'))
    # We can't add "--no-deps" argument to cargo doc, otherwise we lose links to items of
    # other crates...
    #
    # Also, we run "cargo update" in case the lgpl-docs repository has been updated (so we get the
    # last version).
    command = [
        'bash', '-c',
        ('cd {} && cargo update && cargo rustdoc --no-default-features '
         '--features "{}"').format(path, features)
    ]
    if not exec_command_and_print_error(command):
        input(
            "Couldn't generate docs! Try to fix it and then press ENTER to continue..."
        )
    doc_folder = join(path, 'target/doc')
    try:
        file_list = ' '.join([
            '"{}"'.format(f) for f in listdir(doc_folder)
            if isfile(join(doc_folder, f))
        ])
    except Exception as err:
        write_error('Error occured in build docs: {}'.format(err))
        input(
            "It seems like the \"{}\" folder doesn't exist. Try to fix it then press ENTER..."
            .format(doc_folder))
    # Copy documentation files
    command = [
        'bash', '-c',
        'cd {} && cp -r "{}" {} "{}"'.format(doc_folder,
                                             crate_name.replace('-', '_'),
                                             file_list,
                                             join(temp_dir, consts.DOC_REPO))
    ]
    if not exec_command_and_print_error(command):
        input(
            "Couldn't copy docs! Try to fix it and then press ENTER to continue..."
        )
    # Copy source files
    destination = "{}/src".format(join(temp_dir, consts.DOC_REPO))
    command = [
        'bash', '-c',
        'cd {0} && mkdir -p "{1}" && cp -r "src/{2}" "{1}/"'.format(
            doc_folder, destination, crate_name.replace('-', '_'))
    ]
    if not exec_command_and_print_error(command):
        input(
            "Couldn't copy doc source files! Try to fix it and then press ENTER to continue..."
        )
    search_index = join(path, 'target/doc/search-index.js')
    lines = get_file_content(search_index).split('\n')
    before = True
    fill_extras = len(SEARCH_INDEX_BEFORE) == 0
    found = False
    for line in lines:
        if line.startswith('"'):
            before = False
            # We need to be careful in here if we're in a sys repository (which should never be the
            # case!).
            if line.startswith('"{}":'.format(crate_name.replace('-', '_'))):
                if line.endswith('}\\'):
                    line = line[:-1] + ',\\'
                SEARCH_INDEX.append(line)
                found = True
        elif fill_extras is True:
            if before is True:
                SEARCH_INDEX_BEFORE.append(line)
            else:
                SEARCH_INDEX_AFTER.append(line)
    if found is False:
        input(
            "Couldn't find \"{}\" in `{}`!\nTry to fix it and then press ENTER to continue..."
            .format(crate_name.replace('-', '_'), search_index))