Example #1
0
def prompt_for_confirmation(context: Context, fail_title: str, message: str,
                            prompt: str):
    result = Result()

    if context.batch:
        result.value = context.assume_yes
        if not result.value:
            sys.stdout.write(prompt + ' -' + os.linesep)
            result.fail(const.EX_ABORTED, fail_title,
                        _("Operation aborted in batch mode."))
    else:
        if message is not None:
            cli.warn(message)
        sys.stderr.flush()
        sys.stdout.flush()

        if context.assume_yes:
            sys.stdout.write(prompt + ' y' + os.linesep)
            result.value = True
        else:
            result.value = cli.query_yes_no(sys.stdout, prompt, "no")

        if result.value is not True:
            result.error(const.EX_ABORTED_BY_USER, fail_title,
                         _("Operation aborted."), False)

    return result
def version_bump_prerelease(version_config: VersionConfig,
                            version: Optional[str], global_seq: Optional[int]):
    result = Result()
    version_info = semver.parse_version_info(
        version) if version is not None else semver.parse_version_info("0.0.0")

    if version_info.prerelease:
        prerelease_version_elements = version_info.prerelease.split(".")
        if len(prerelease_version_elements
               ) > 0 and prerelease_version_elements[0].upper() == "SNAPSHOT":
            if len(prerelease_version_elements) == 1:
                result.error(
                    os.EX_DATAERR,
                    _("The pre-release increment has been skipped."),
                    _("In order to retain Maven compatibility, "
                      "the pre-release component of snapshot versions must not be versioned."
                      ))
            else:
                result.error(
                    os.EX_DATAERR,
                    _("Failed to increment the pre-release component of version {version}."
                      ).format(version=repr(version)),
                    _("Snapshot versions must not have a pre-release version.")
                )
            result.value = version
        elif len(prerelease_version_elements) == 1:
            if version_config.versioning_scheme != VersioningScheme.SEMVER_WITH_SEQ:
                result.error(
                    os.EX_DATAERR,
                    _("Failed to increment the pre-release component of version {version}."
                      ).format(version=repr(version)),
                    _("The qualifier {qualifier} must already be versioned.").
                    format(qualifier=repr(prerelease_version_elements[0])))
        result.value = semver.bump_prerelease(version)
    else:
        result.error(
            os.EX_DATAERR,
            _("Failed to increment the pre-release component of version {version}."
              ).format(version=repr(version)),
            _("Pre-release increments cannot be performed on release versions."
              ))

    if result.has_errors():
        result.value = None
    elif result.value is not None and not semver.compare(
            result.value, version) > 0:
        result.value = None

    if not result.value:
        result.error(
            os.EX_SOFTWARE,
            _("Failed to increment the pre-release of version {version} for unknown reasons."
              ).format(version=repr(version)), None)
    return result
Example #3
0
def update_project_property_file(context: Context, prev_properties: dict,
                                 new_version: str, new_sequential_version: int,
                                 commit_out: CommitInfo):
    result = Result()
    result.value = False

    if context.config.property_file is not None:
        property_reader = PropertyIO.get_instance_by_filename(
            context.config.property_file)
        if property_reader is None:
            result.fail(
                os.EX_DATAERR,
                _("Property file not supported: {path}\n"
                  "Currently supported:\n"
                  "{listing}").format(path=repr(context.config.property_file),
                                      listing='\n'.join(
                                          ' - ' + type
                                          for type in ['*.properties'])), None)

        properties = update_project_properties(context, prev_properties,
                                               new_version,
                                               new_sequential_version)

        property_reader.write_file(context.config.property_file, properties)
        commit_out.add_file(context.config.property_file)
        result.value = True
    else:
        properties = None

    var_separator = ' : '

    if properties is not None:

        def log_property(properties: dict, key: str):
            if key is not None:
                commit_out.add_message(
                    '#properties[' + utils.quote(key, '"') + ']' +
                    var_separator + cli.if_none(properties.get(key), "null"))

        for property_key in [
                context.config.version_property,
                context.config.sequence_number_property
        ]:
            log_property(properties, property_key)

    if context.verbose and result.value != 0:
        print("properties have changed")
        print("commit message:")
        print(commit_out.message)

    return result
Example #4
0
def validate_version(config: VersionConfig, version_string):
    result = Result()

    try:
        version_info = semver.parse_version_info(version_string)
        if version_info.prerelease is not None:
            if version_info.prerelease is not None and not re.match(r'[a-zA-Z][a-zA-Z0-9]*\.\d',
                                                                    version_info.prerelease):
                result.error(os.EX_DATAERR,
                             "Invalid version format.",
                             "The pre-release component must contain a type name with a version number.\n"
                             "The required version format is:\n"
                             + const.TEXT_VERSION_STRING_FORMAT)
            prerelease_version_elements = version_info.prerelease.split(".")
            prerelease_type = prerelease_version_elements[0]
            prerelease_version = prerelease_version_elements[1]

            if config.qualifiers is not None and prerelease_type not in config.qualifiers:
                result.error(os.EX_DATAERR,
                             "Invalid version.",
                             "The pre-release type \"" + prerelease_type + "\" is invalid, must be one of: "
                             + ','.join(config.qualifiers) + ".\n"
                             + "Configuration property: " + const.CONFIG_VERSION_TYPES)
        result.value = version_string
    except ValueError:
        result.error(os.EX_DATAERR,
                     "Failed to parse the version.",
                     "The required version format is:\n"
                     + const.TEXT_VERSION_STRING_FORMAT)

    return result
 def __call__(self, version_config: VersionConfig,
              old_version: Optional[str], global_seq: Optional[int]):
     result = Result()
     result.add_subresult(
         version.validate_version(version_config, self.__new_version))
     result.value = self.__new_version
     return result
def version_bump_to_release(version_config: VersionConfig,
                            version: Optional[str], global_seq: Optional[int]):
    result = Result()
    version_info = semver.parse_version_info(
        version) if version is not None else semver.parse_version_info("0.0.0")

    if version_config.versioning_scheme == VersioningScheme.SEMVER_WITH_SEQ:
        result.error(
            os.EX_USAGE,
            _("Failed to increment version to release: {version}.").format(
                version=repr(version)),
            _("Sequential versions cannot be release versions."))
        return result

    if not version_info.prerelease:
        result.error(
            os.EX_DATAERR,
            _("Failed to increment version to release: {version}.").format(
                version=repr(version)),
            _("Only pre-release versions can be incremented to a release version."
              ))

    if not result.has_errors():
        result.value = semver.format_version(version_info.major,
                                             version_info.minor,
                                             version_info.patch, None, None)
    return result
def version_bump_qualifier(version_config: VersionConfig,
                           version: Optional[str], global_seq: Optional[int]):
    result = Result()
    version_info = semver.parse_version_info(
        version) if version is not None else semver.parse_version_info("0.0.0")

    new_qualifier = None

    if not version_config.qualifiers:
        result.error(
            os.EX_USAGE,
            _("Failed to increment the pre-release qualifier of version {version}."
              ).format(version=repr(version)),
            _("The version scheme does not contain qualifiers"))
        return result

    if version_info.prerelease:
        prerelease_version_elements = version_info.prerelease.split(".")
        qualifier = prerelease_version_elements[0]
        qualifier_index = version_config.qualifiers.index(
            qualifier) if qualifier in version_config.qualifiers else -1
        if qualifier_index < 0:
            result.error(
                os.EX_DATAERR,
                _("Failed to increment the pre-release qualifier of version {version}."
                  ).format(version=repr(version)),
                _("The current qualifier is invalid: {qualifier}").format(
                    qualifier=repr(qualifier)))
        else:
            qualifier_index += 1
            if qualifier_index < len(version_config.qualifiers):
                new_qualifier = version_config.qualifiers[qualifier_index]
            else:
                result.error(
                    os.EX_DATAERR,
                    _("Failed to increment the pre-release qualifier {qualifier} of version {version}."
                      ).format(qualifier=qualifier, version=repr(version)),
                    _("There are no further qualifiers with higher precedence, configured qualifiers are:\n"
                      "{listing}\n"
                      "The sub command 'bump-to-release' may be used for a final bump."
                      ).format(listing='\n'.join(
                          ' - ' + repr(qualifier)
                          for qualifier in version_config.qualifiers)))
    else:
        result.error(
            os.EX_DATAERR,
            _("Failed to increment the pre-release qualifier of version {version}."
              ).format(version=version),
            _("Pre-release increments cannot be performed on release versions."
              ))

    if not result.has_errors() and new_qualifier is not None:
        result.value = semver.format_version(version_info.major,
                                             version_info.minor,
                                             version_info.patch,
                                             new_qualifier + ".1", None)
    return result
Example #8
0
def download_file(source_uri: str, dest_file: str, hash_hex: str):
    from urllib import request
    import hashlib

    result = Result()

    hash = bytes.fromhex(hash_hex)

    download = False

    if not os.path.exists(dest_file):
        cli.print("file does not exist: " + dest_file)
        download = True
    elif hash_file(hashlib.sha256(), dest_file) != hash:
        cli.print("file hash does not match: " + dest_file)
        download = True
    else:
        cli.print("keeping file: " + dest_file + ", sha256 matched: " +
                  hash_hex)

    if download:
        cli.print("downloading: " + source_uri + " to " + dest_file)
        request.urlretrieve(url=str(source_uri), filename=dest_file + "~")
        filesystem.replace_file(dest_file + "~", dest_file)

        if hash is not None:
            actual_hash = hash_file(hashlib.sha256(), dest_file)
            if actual_hash != hash:
                result.error(
                    os.EX_IOERR, _("File verification failed."),
                    _("The file {file} is expected to hash to {expected_hash},\n"
                      "The actual hash is: {actual_hash}").format(
                          file=repr(dest_file),
                          expected_hash=repr(hash_hex),
                          actual_hash=repr(actual_hash.hex()),
                      ))

    if not result.has_errors():
        result.value = dest_file

    return result
def version_bump_patch(version_config: VersionConfig, version: Optional[str],
                       global_seq: Optional[int]):
    result = Result()

    try:
        global_seq = filter_sequence_number(version_config, version,
                                            global_seq)
    except ValueError as e:
        result.error(os.EX_DATAERR, "version increment failed", str(e))

    if not result.has_errors():
        version_info = semver.parse_version_info(
            semver.bump_patch(version)
        ) if version is not None else semver.parse_version_info("0.0.0")
        pre_release = True

        result.value = semver.format_version(
            version_info.major, version_info.minor, version_info.patch,
            (version_config.qualifiers[0] +
             ".1" if pre_release else None) if version_config.versioning_scheme
            != VersioningScheme.SEMVER_WITH_SEQ else global_seq + 1, None)
    return result
Example #10
0
def clone_repository(context: Context, branch: str) -> Result:
    """
    :rtype: Result
    """
    result = Result()

    remote = repotools.git_get_remote(context.repo, context.config.remote_name)
    if remote is None:
        result.fail(
            os.EX_DATAERR, _("Failed to clone repo."),
            _("The remote {remote} does not exist.").format(
                remote=repr(context.config.remote_name)))

    tempdir_path = tempfile.mkdtemp(prefix=os.path.basename(context.repo.dir) +
                                    ".gitflow-clone.")
    try:
        if os.path.exists(tempdir_path):
            os.chmod(path=tempdir_path, mode=0o700)
            if os.path.isdir(tempdir_path):
                if os.listdir(tempdir_path):
                    result.fail(
                        os.EX_DATAERR, _("Failed to clone repo."),
                        _("Directory is not empty: {path}").format(
                            path=tempdir_path))
            else:
                result.fail(
                    os.EX_DATAERR, _("Failed to clone repo."),
                    _("File is not a directory: {path}").format(
                        path=tempdir_path))
        else:
            result.fail(
                os.EX_DATAERR, _("Failed to clone repo."),
                _("File does not exist: {path}").format(path=tempdir_path))

        if context.config.push_to_local:
            returncode, out, err = repotools.git_raw(git=context.repo.git,
                                                     args=[
                                                         'clone', '--branch',
                                                         branch, '--shared',
                                                         context.repo.dir,
                                                         tempdir_path
                                                     ],
                                                     verbose=context.verbose)
        else:
            returncode, out, err = repotools.git_raw(git=context.repo.git,
                                                     args=[
                                                         'clone', '--branch',
                                                         branch, '--reference',
                                                         context.repo.dir,
                                                         remote.url,
                                                         tempdir_path
                                                     ],
                                                     verbose=context.verbose)

        if returncode != os.EX_OK:
            result.error(os.EX_DATAERR, _("Failed to clone the repository."),
                         _("An unexpected error occurred."))
    except:
        result.error(os.EX_DATAERR, _("Failed to clone the repository."),
                     _("An unexpected error occurred."))
    finally:
        context.add_subresult(result)

    if not result.has_errors():
        repo = RepoContext()
        repo.git = context.repo.git
        repo.dir = tempdir_path
        repo.verbose = context.repo.verbose
        result.value = repo
    else:
        shutil.rmtree(path=tempdir_path)

    return result