Esempio n. 1
0
def call(context: Context):
    command_context = get_command_context(context=context,
                                          object_arg=context.args['<object>'])

    if context.repo is not None:
        if context.args['--inplace']:
            build_context = context
            build_command_context = command_context
        else:
            temp_dir = TemporaryDirectory()

            exported_repo = repotools.git_export(
                context=context.repo,
                target_dir=temp_dir.name,
                object=command_context.selected_commit)
            build_context = Context.create(
                {
                    **context.args,
                    **{
                        '--root': exported_repo.dir,
                        '--config': context.args['--config'],  # no override here
                        '--batch': context.batch,
                        '--dry-run': context.dry_run,
                        '--verbose': context.verbose,
                        '--pretty': context.pretty,
                    }
                },
                context.result)
            build_command_context = get_command_context(
                context=build_context,
                object_arg=build_context.args['<object>'])

        check_requirements(
            command_context=build_command_context,
            ref=build_command_context.selected_ref,
            branch_classes=None,
            modifiable=True,
            with_upstream=True,  # not context.config.push_to_local
            in_sync_with_upstream=True,
            fail_message=_("Build failed."),
            allow_unversioned_changes=False)
    else:
        build_context = context
        build_command_context = command_context

    selected_stages = list()

    for stage_type in const.BUILD_STAGE_TYPES:
        if build_context.args[stage_type.replace('_', '-')]:
            selected_stages.append(stage_type)

    execute_build_steps(build_command_context, selected_stages)

    return context.result
Esempio n. 2
0
def pre_push(context: Context) -> Result:
    result = Result()

    for line in sys.stdin.readlines():
        tokens = line.split(' ')
        if len(tokens) != 4:
            raise ValueError()
        cli.print(line)

        local_ref = tokens[0]
        local_sha1 = tokens[1]
        remote_ref = tokens[2]
        remote_sha1 = tokens[3]

        command_context = common.get_command_context(context=context,
                                                     object_arg=remote_ref)

        common.check_requirements(command_context=command_context,
                                  ref=command_context.selected_ref,
                                  branch_classes=None,
                                  modifiable=True,
                                  with_upstream=False,
                                  in_sync_with_upstream=False,
                                  fail_message=_("Push rejected."),
                                  throw=False)

    return result
Esempio n. 3
0
def pre_commit(context: Context) -> Result:
    result = Result()

    command_context = common.get_command_context(context=context,
                                                 object_arg='HEAD')

    target_ref = repotools.git_get_current_branch(context.repo)

    common.check_requirements(command_context=command_context,
                              ref=target_ref,
                              branch_classes=None,
                              modifiable=True,
                              with_upstream=False,
                              in_sync_with_upstream=False,
                              fail_message=_("Commit rejected."),
                              throw=False)

    return result
Esempio n. 4
0
def call(context: Context) -> Result:
    command_context = get_command_context(
        context=context,
        object_arg=context.args['<work-branch>']
    )

    check_in_repo(command_context)

    object_arg = context.args['<object>']
    args = context.args['<git-arg>']

    if object_arg is not None:
        selected_branch = get_branch_by_branch_name_or_version_tag(context, object_arg,
                                                                   BranchSelection.BRANCH_PREFER_LOCAL)
        if selected_branch is None:
            command_context.fail(os.EX_USAGE,
                                 _("Log failed."),
                                 _("Failed to resolve an object for token {object}.")
                                 .format(object=repr(object_arg))
                                 )
    else:
        selected_branch = None

    log_command = ['log']
    if context.pretty:
        log_command.append('--pretty')
    if context.dry_run:
        log_command.append('--dry-run')
    if context.verbose:
        log_command.append('--verbose')
    if selected_branch is not None:
        log_command.append(selected_branch)

    proc = repotools.git_interactive(context.repo, *(log_command + args))
    proc.wait()

    return context.result
Esempio n. 5
0
def call(context) -> Result:
    command_context = get_command_context(context=context,
                                          object_arg=context.args['<object>'])

    check_in_repo(command_context)

    unique_codes = set()
    unique_version_codes = list()

    upstreams = repotools.git_get_upstreams(context.repo)
    branch_info_dict = dict()

    if context.args['--all'] > 0:
        selected_refs = repotools.git_list_refs(
            context.repo,
            repotools.create_ref_name(const.REMOTES_PREFIX,
                                      context.config.remote_name))
    else:
        selected_refs = [
            command_context.selected_ref or command_context.current_branch
        ]

    for branch_ref in selected_refs:
        branch_match = context.release_branch_matcher.fullmatch(
            branch_ref.name)
        if branch_match:
            branch_version = context.release_branch_matcher.to_version(
                branch_ref.name)

            branch_version_string = get_branch_version_component_for_version(
                context, branch_version)

            discontinuation_tags, discontinuation_tag_name = get_discontinuation_tags(
                context, branch_ref)

            update_branch_info(context, branch_info_dict, upstreams,
                               branch_ref)

            branch_info = branch_info_dict.get(branch_ref.name)
            discontinued = len(discontinuation_tags)

            if discontinued:
                status_color = colors.partial(colors.color, fg='gray')
                status_error_color = colors.partial(colors.color, fg='red')
                status_local_color = colors.partial(colors.color, fg='blue')
                status_remote_color = colors.partial(colors.color, fg='green')
            else:
                status_color = colors.partial(colors.color,
                                              fg='white',
                                              style='bold')
                status_error_color = colors.partial(colors.color,
                                                    fg='red',
                                                    style='bold')
                status_local_color = colors.partial(colors.color,
                                                    fg='blue',
                                                    style='bold')
                status_remote_color = colors.partial(colors.color,
                                                     fg='green',
                                                     style='bold')

            error_color = colors.partial(colors.color,
                                         fg='white',
                                         bg='red',
                                         style='bold')

            cli.fcwrite(sys.stdout, status_color,
                        "version: " + branch_version_string + ' [')
            if branch_info.local is not None:
                i = 0
                for local in branch_info.local:
                    local_branch_color = status_local_color
                    if not branch_info.upstream.short_name.endswith(
                            '/' + local.short_name):
                        command_context.error(
                            os.EX_DATAERR,
                            _("Local and upstream branch have a mismatching short name."
                              ), None)
                        local_branch_color = error_color
                    if i:
                        cli.fcwrite(sys.stdout, status_color, ', ')
                    if context.verbose:
                        cli.fcwrite(sys.stdout, local_branch_color, local.name)
                    else:
                        cli.fcwrite(sys.stdout, local_branch_color,
                                    local.short_name)
                    i += 1
            if branch_info.upstream is not None:
                if branch_info.local is not None and len(branch_info.local):
                    cli.fcwrite(sys.stdout, status_color, ' => ')
                if context.verbose:
                    cli.fcwrite(sys.stdout, status_remote_color,
                                branch_info.upstream.name)
                else:
                    cli.fcwrite(sys.stdout, status_remote_color,
                                branch_info.upstream.short_name)
            cli.fcwrite(sys.stdout, status_color, "]")
            if discontinued:
                cli.fcwrite(sys.stdout, status_color,
                            ' (' + _('discontinued') + ')')

            cli.fcwriteln(sys.stdout, status_color)

            commit_tags = repotools.git_get_branch_tags(
                context=context.repo,
                base_branch=context.config.release_branch_base,
                branch=branch_ref.name,
                tag_filter=None,
                commit_tag_comparator=None)

            for commit, tags in commit_tags:
                for tag in tags:
                    if context.version_tag_matcher.group_unique_code is not None:
                        tag_match = context.version_tag_matcher.fullmatch(
                            tag.name)
                        if tag_match is not None:
                            unique_code = tag_match.group(
                                context.version_tag_matcher.group_unique_code)
                            version_string = unique_code

                            unique_version_codes.append(int(unique_code))

                            if unique_code in unique_codes:
                                command_context.error(
                                    os.EX_DATAERR,
                                    _("Invalid sequential version tag {tag}.").
                                    format(tag=tag.name),
                                    _("The code element of version {version_string} is not unique."
                                      ).format(version_string=version_string))
                            else:
                                unique_codes.add(unique_code)

                            cli.fcwriteln(sys.stdout, status_color,
                                          "  code: " + version_string)

                    # print the version tag
                    version_string = context.version_tag_matcher.format(
                        tag.name)
                    if version_string:
                        version_info = semver.parse_version_info(
                            version_string)
                        if version_info.major == branch_version.major and version_info.minor == branch_version.minor:
                            cli.fcwriteln(sys.stdout, status_color,
                                          "    " + version_string)
                        else:
                            command_context.error(
                                os.EX_DATAERR,
                                _("Invalid version tag {tag}.").format(
                                    tag=repr(tag.name)),
                                _("The major.minor part of the new version {new_version}"
                                  " does not match the branch version {branch_version}."
                                  ).format(new_version=repr(version_string),
                                           branch_version=repr(
                                               branch_version_string)))
                            cli.fcwriteln(sys.stdout, status_error_color,
                                          "    " + version_string)

    unique_version_codes.sort(
        key=utils.cmp_to_key(lambda a, b: version.cmp_alnum_token(a, b)))

    last_unique_code = None
    for unique_code in unique_version_codes:
        if not (last_unique_code is None or unique_code > last_unique_code):
            command_context.error(
                os.EX_DATAERR,
                _("Version {version} breaks the sequence.").format(
                    version=unique_code), None)
        last_unique_code = unique_code

    return context.result
Esempio n. 6
0
def call(context: Context) -> Result:
    command_context = get_command_context(
        context=context, object_arg=context.args['<base-object>'])

    check_in_repo(command_context)

    check_requirements(
        command_context=command_context,
        ref=command_context.selected_ref,
        branch_classes=None,
        modifiable=True,
        with_upstream=True,  # not context.config.push_to_local
        in_sync_with_upstream=True,
        fail_message=_("Version creation failed."))

    selected_work_branch = context.args.get('<work-branch>')
    if selected_work_branch is not None:
        selected_work_branch = repotools.create_ref_name(selected_work_branch)
        if not selected_work_branch.startswith(const.LOCAL_BRANCH_PREFIX):
            selected_work_branch = const.LOCAL_BRANCH_PREFIX + selected_work_branch
        branch_match = context.work_branch_matcher.fullmatch(
            selected_work_branch)
        if branch_match is None:
            context.fail(
                os.EX_USAGE,
                _("Invalid work branch: {branch}.").format(
                    branch=repr(selected_work_branch)), None)
        groups = branch_match.groupdict()

        branch_supertype = groups['prefix']
        branch_type = groups['type']
        branch_short_name = groups['name']
    else:
        branch_supertype = context.args['<supertype>']
        branch_type = context.args['<type>']
        branch_short_name = context.args['<name>']

    if branch_supertype not in [
            const.BRANCH_PREFIX_DEV, const.BRANCH_PREFIX_PROD
    ]:
        context.fail(
            os.EX_USAGE,
            _("Invalid branch super type: {supertype}.").format(
                supertype=repr(branch_supertype)), None)

    work_branch_name = repotools.create_ref_name(branch_supertype, branch_type,
                                                 branch_short_name)
    work_branch_ref_name = repotools.create_ref_name(const.LOCAL_BRANCH_PREFIX,
                                                     work_branch_name)
    work_branch_class = get_branch_class(context, work_branch_ref_name)

    if True:
        work_branch_info = get_branch_info(command_context,
                                           work_branch_ref_name)
        if work_branch_info is not None:
            context.fail(
                os.EX_USAGE,
                _("The branch {branch} already exists locally or remotely.").
                format(branch=repr(work_branch_name)), None)

    allowed_base_branch_class = const.BRANCHING[work_branch_class]

    base_branch, base_branch_class = select_ref(
        command_context.result, command_context.selected_branch,
        BranchSelection.BRANCH_PREFER_LOCAL)
    if not command_context.selected_explicitly and branch_supertype == const.BRANCH_PREFIX_DEV:
        base_branch_info = get_branch_info(
            command_context,
            repotools.create_ref_name(const.LOCAL_BRANCH_PREFIX,
                                      context.config.release_branch_base))
        base_branch, base_branch_class = select_ref(
            command_context.result, base_branch_info,
            BranchSelection.BRANCH_PREFER_LOCAL)

    if allowed_base_branch_class != base_branch_class:
        context.fail(
            os.EX_USAGE,
            _("The branch {branch} is not a valid base for {supertype} branches."
              ).format(branch=repr(base_branch.name),
                       supertype=repr(branch_supertype)), None)

    if base_branch is None:
        context.fail(os.EX_USAGE, _("Base branch undetermined."), None)

    if context.verbose:
        cli.print("branch_name: " + command_context.selected_ref.name)
        cli.print("work_branch_name: " + work_branch_name)
        cli.print("base_branch_name: " + base_branch.name)

    if not context.dry_run and not command_context.has_errors():
        index_status = git(context.repo, ['diff-index', 'HEAD', '--'])
        if index_status == 1:
            context.fail(
                os.EX_USAGE, _("Branch creation aborted."),
                _("You have staged changes in your workspace.\n"
                  "Unstage, commit or stash them and try again."))
        elif index_status != 0:
            context.fail(os.EX_DATAERR, _("Failed to determine index status."),
                         None)

        git_or_fail(
            context.repo, command_context.result, [
                'update-ref', work_branch_ref_name,
                command_context.selected_commit, ''
            ],
            _("Failed to create branch {branch_name}.").format(
                branch_name=work_branch_name))
        git_or_fail(
            context.repo, command_context.result,
            ['checkout', work_branch_name],
            _("Failed to checkout branch {branch_name}.").format(
                branch_name=work_branch_name))

    return context.result
Esempio n. 7
0
def call(context: Context) -> Result:
    arg_work_branch = context.args.get('<work-branch>')
    if arg_work_branch is None:
        branch_prefix = context.args['<supertype>']
        branch_type = context.args['<type>']
        branch_name = context.args['<name>']

        if branch_prefix is not None or branch_type is not None or branch_name is not None:
            arg_work_branch = repotools.create_ref_name(branch_prefix, branch_type, branch_name)

    command_context = get_command_context(
        context=context,
        object_arg=arg_work_branch
    )

    check_in_repo(command_context)

    base_command_context = get_command_context(
        context=context,
        object_arg=context.args['<base-object>']
    )

    check_requirements(command_context=command_context,
                       ref=command_context.selected_ref,
                       branch_classes=[BranchClass.WORK_DEV, BranchClass.WORK_PROD],
                       modifiable=True,
                       with_upstream=True,  # not context.config.push_to_local
                       in_sync_with_upstream=True,
                       fail_message=_("Version creation failed.")
                       )

    work_branch = None
    selected_ref_match = context.work_branch_matcher.fullmatch(command_context.selected_ref.name)
    if selected_ref_match is not None:
        work_branch = WorkBranch()
        work_branch.prefix = selected_ref_match.group('prefix')
        work_branch.type = selected_ref_match.group('type')
        work_branch.name = selected_ref_match.group('name')
    else:
        if command_context.selected_explicitly:
            context.fail(os.EX_USAGE,
                         _("The ref {branch} does not refer to a work branch.")
                         .format(branch=repr(command_context.selected_ref.name)),
                         None)

    work_branch_info = get_branch_info(command_context, work_branch.local_ref_name())
    if work_branch_info is None:
        context.fail(os.EX_USAGE,
                     _("The branch {branch} does neither exist locally nor remotely.")
                     .format(branch=repr(work_branch.branch_name())),
                     None)

    work_branch_ref, work_branch_class = select_ref(command_context.result,
                                                    work_branch_info,
                                                    BranchSelection.BRANCH_PREFER_LOCAL)

    allowed_base_branch_class = const.BRANCHING[work_branch_class]

    base_branch_info = get_branch_info(base_command_context,
                                       base_command_context.selected_ref)

    base_branch_ref, base_branch_class = select_ref(command_context.result,
                                                    base_branch_info,
                                                    BranchSelection.BRANCH_PREFER_LOCAL)
    if not base_command_context.selected_explicitly:
        if work_branch.prefix == const.BRANCH_PREFIX_DEV:
            base_branch_info = get_branch_info(base_command_context,
                                               repotools.create_ref_name(const.LOCAL_BRANCH_PREFIX,
                                                                         context.config.release_branch_base))
            base_branch_ref, base_branch_class = select_ref(command_context.result,
                                                            base_branch_info,
                                                            BranchSelection.BRANCH_PREFER_LOCAL)
        elif work_branch.prefix == const.BRANCH_PREFIX_PROD:
            # discover closest merge base in release branches

            release_branches = repotools.git_list_refs(context.repo,
                                                       repotools.create_ref_name(const.REMOTES_PREFIX,
                                                                                 context.config.remote_name,
                                                                                 'release'))
            release_branches = list(release_branches)
            release_branches.sort(reverse=True, key=utils.cmp_to_key(lambda ref_a, ref_b: semver.compare(
                context.release_branch_matcher.format(ref_a.name),
                context.release_branch_matcher.format(ref_b.name)
            )))
            for release_branch_ref in release_branches:
                merge_base = repotools.git_merge_base(context.repo, base_branch_ref, work_branch_ref.name)
                if merge_base is not None:
                    base_branch_info = get_branch_info(base_command_context, release_branch_ref)

                    base_branch_ref, base_branch_class = select_ref(command_context.result,
                                                                    base_branch_info,
                                                                    BranchSelection.BRANCH_PREFER_LOCAL)
                    break

    if allowed_base_branch_class != base_branch_class:
        context.fail(os.EX_USAGE,
                     _("The branch {branch} is not a valid base for {supertype} branches.")
                     .format(branch=repr(base_branch_ref.name),
                             supertype=repr(work_branch.prefix)),
                     None)

    if base_branch_ref is None:
        context.fail(os.EX_USAGE,
                     _("Base branch undetermined."),
                     None)

    if context.verbose:
        cli.print("branch_name: " + command_context.selected_ref.name)
        cli.print("work_branch_name: " + work_branch_ref.name)
        cli.print("base_branch_name: " + base_branch_ref.name)

    # check, if already merged
    merge_base = repotools.git_merge_base(context.repo, base_branch_ref, work_branch_ref.name)
    if work_branch_ref.obj_name == merge_base:
        cli.print(_("Branch {branch} is already merged.")
                  .format(branch=repr(work_branch_ref.name)))
        return context.result

    # check for staged changes
    index_status = git(context.repo, ['diff-index', 'HEAD', '--'])
    if index_status == 1:
        context.fail(os.EX_USAGE,
                     _("Branch creation aborted."),
                     _("You have staged changes in your workspace.\n"
                       "Unstage, commit or stash them and try again."))
    elif index_status != 0:
        context.fail(os.EX_DATAERR,
                     _("Failed to determine index status."),
                     None)

    if not context.dry_run and not command_context.has_errors():
        # perform merge
        local_branch_ref_name = repotools.create_local_branch_ref_name(base_branch_ref.name)
        local_branch_name = repotools.create_local_branch_name(base_branch_ref.name)
        if local_branch_ref_name == base_branch_ref.name:
            git_or_fail(context.repo, command_context.result,
                        ['checkout', local_branch_name],
                        _("Failed to checkout branch {branch_name}.")
                        .format(branch_name=repr(base_branch_ref.short_name))
                        )
        else:
            git_or_fail(context.repo, command_context.result,
                        ['checkout', '-b', local_branch_name, base_branch_ref.name],
                        _("Failed to checkout branch {branch_name}.")
                        .format(branch_name=repr(base_branch_ref.short_name))
                        )

        git_or_fail(context.repo, command_context.result,
                    ['merge', '--no-ff', work_branch_ref],
                    _("Failed to merge work branch.\n"
                      "Rebase {work_branch} on {base_branch} and try again")
                    .format(work_branch=repr(work_branch_ref.short_name),
                            base_branch=repr(base_branch_ref.short_name))
                    )

        git_or_fail(context.repo, command_context.result,
                    ['push', context.config.remote_name, local_branch_name],
                    _("Failed to push branch {branch_name}.")
                    .format(branch_name=repr(base_branch_ref.short_name))
                    )

    return context.result
def call(context: Context) -> Result:
    result: Result = context.result
    object_arg = context.args['<object>']

    reintegrate = cli.get_boolean_opt(context.args, '--reintegrate')

    command_context = get_command_context(context=context,
                                          object_arg=context.args['<object>'])

    check_in_repo(command_context)

    base_branch_ref = repotools.get_branch_by_name(
        context.repo, {context.config.remote_name},
        context.config.release_branch_base,
        BranchSelection.BRANCH_PREFER_LOCAL)

    release_branch = command_context.selected_ref

    release_branch_info = get_branch_info(command_context, release_branch)

    check_requirements(
        command_context=command_context,
        ref=release_branch,
        branch_classes=[BranchClass.RELEASE],
        modifiable=True,
        with_upstream=True,  # not context.config.push_to_local
        in_sync_with_upstream=True,
        fail_message=_("Build failed."))

    if release_branch is None:
        command_context.fail(
            os.EX_USAGE, _("Branch discontinuation failed."),
            _("Failed to resolve an object for token {object}.").format(
                object=repr(object_arg)))

    discontinuation_tags, discontinuation_tag_name = get_discontinuation_tags(
        context, release_branch)

    if discontinuation_tag_name is None:
        command_context.fail(
            os.EX_USAGE, _("Branch discontinuation failed."),
            _("{branch} cannot be discontinued.").format(
                branch=repr(release_branch.name)))

    if context.verbose:
        cli.print("discontinuation tags:")
        for discontinuation_tag in discontinuation_tags:
            print(' - ' + discontinuation_tag.name)
        pass

    if len(discontinuation_tags):
        command_context.fail(
            os.EX_USAGE, _("Branch discontinuation failed."),
            _("The branch {branch} is already discontinued.").format(
                branch=repr(release_branch.name)))
    # show info and prompt for confirmation
    print("discontinued_branch : " + cli.if_none(release_branch.name))

    if reintegrate is None:
        prompt_result = prompt(
            context=context,
            message=_("Branches may be reintegrated upon discontinuation."),
            prompt=_("Do you want to reintegrate {branch} into {base_branch}?"
                     ).format(branch=repr(release_branch.short_name),
                              base_branch=repr(base_branch_ref.short_name)),
        )
        command_context.add_subresult(prompt_result)
        if command_context.has_errors():
            return context.result

        reintegrate = prompt_result.value

    if not command_context.has_errors():
        # run merge on local clone

        clone_result = clone_repository(context,
                                        context.config.release_branch_base)
        clone_context: Context = create_temp_context(context, result,
                                                     clone_result.value.dir)
        clone_context.config.remote_name = 'origin'

        changes = list()

        if reintegrate:
            git_or_fail(
                clone_context.repo, command_context.result,
                ['checkout', base_branch_ref.short_name],
                _("Failed to checkout branch {branch_name}.").format(
                    branch_name=repr(base_branch_ref.short_name)))

            git_or_fail(
                clone_context.repo, command_context.result,
                ['merge', '--no-ff', release_branch_info.upstream.name],
                _("Failed to merge work branch.\n"
                  "Rebase {work_branch} on {base_branch} and try again"
                  ).format(work_branch=repr(release_branch.short_name),
                           base_branch=repr(base_branch_ref.short_name)))
            changes.append(
                _("{branch} reintegrated into {base_branch}").format(
                    branch=repr(release_branch.name),
                    base_branch=repr(base_branch_ref.name)))

        changes.append(_("Discontinuation tag"))
        prompt_result = prompt_for_confirmation(
            context=context,
            fail_title=_("Failed to discontinue {branch}.").format(
                branch=repr(release_branch.name)),
            message=(" - " +
                     (os.linesep + " - ").join([_("Changes to be pushed:")] +
                                               changes)),
            prompt=_("Continue?"),
        )
        command_context.add_subresult(prompt_result)
        if command_context.has_errors() or not prompt_result.value:
            return context.result

        push_command = ['push', '--atomic']
        if context.dry_run:
            push_command.append('--dry-run')
        if context.verbose:
            push_command.append('--verbose')
        push_command.append(context.config.remote_name)

        push_command.append(
            base_branch_ref.name + ':' + repotools.create_ref_name(
                const.LOCAL_BRANCH_PREFIX, base_branch_ref.short_name))
        push_command.append('--force-with-lease=' + repotools.create_ref_name(
            const.LOCAL_TAG_PREFIX, discontinuation_tag_name) + ':')
        push_command.append(
            repotools.ref_target(release_branch) + ':' +
            repotools.create_ref_name(const.LOCAL_TAG_PREFIX,
                                      discontinuation_tag_name))

        git_or_fail(clone_context.repo, command_context.result, push_command)

        fetch_all_and_ff(context.repo, command_context.result,
                         context.config.remote_name)

    return context.result
Esempio n. 9
0
def call(context: Context, operation: Callable[[VersionConfig, Optional[str], Optional[int]], Result]) -> Result:
    command_context = get_command_context(
        context=context,
        object_arg=context.args['<object>']
    )

    check_in_repo(command_context)

    # determine the type of operation to be performed and run according subroutines
    if operation == scheme_procedures.version_bump_major \
            or operation == scheme_procedures.version_bump_minor:

        check_requirements(command_context=command_context,
                           ref=command_context.selected_ref,
                           branch_classes=[BranchClass.DEVELOPMENT_BASE],
                           modifiable=True,
                           with_upstream=True,  # not context.config.push_to_local
                           in_sync_with_upstream=True,
                           fail_message=_("Version creation failed.")
                           )

        tag_result = create_version_branch(command_context, operation)
        command_context.add_subresult(tag_result)

    elif operation == scheme_procedures.version_bump_patch \
            or operation == scheme_procedures.version_bump_qualifier \
            or operation == scheme_procedures.version_bump_prerelease \
            or operation == scheme_procedures.version_bump_to_release:

        check_requirements(command_context=command_context,
                           ref=command_context.selected_ref,
                           branch_classes=[BranchClass.RELEASE],
                           modifiable=True,
                           with_upstream=True,  # not context.config.push_to_local
                           in_sync_with_upstream=True,
                           fail_message=_("Version creation failed.")
                           )

        tag_result = create_version_tag(command_context, operation)
        command_context.add_subresult(tag_result)

    elif isinstance(operation, scheme_procedures.VersionSet):
        check_requirements(command_context=command_context,
                           ref=command_context.selected_ref,
                           branch_classes=None,
                           modifiable=True,
                           with_upstream=True,  # not context.config.push_to_local
                           in_sync_with_upstream=True,
                           fail_message=_("Version creation failed.")
                           )

        version_result = operation(context.config.version_config, None, get_global_sequence_number(context))
        command_context.add_subresult(version_result)
        new_version = version_result.value
        if new_version is None:
            command_context.fail(os.EX_USAGE,
                                 _("Illegal argument."),
                                 _("Failed to parse version.")
                                 )
        new_version_info = semver.parse_version_info(new_version)

        branch_name = get_branch_name_for_version(context, new_version_info)

        release_branch = repotools.get_branch_by_name(context.repo, {context.config.remote_name}, branch_name,
                                                      BranchSelection.BRANCH_PREFER_LOCAL)
        if release_branch is None:
            tag_result = create_version_branch(command_context, operation)
            command_context.add_subresult(tag_result)
        else:
            selected_ref = release_branch
            tag_result = create_version_tag(command_context, operation)
            command_context.add_subresult(tag_result)

    if not command_context.has_errors() \
            and context.config.pull_after_bump \
            and not context.config.push_to_local:
        fetch_all_and_ff(context.repo, command_context.result, context.config.remote_name)

    return context.result