Beispiel #1
0
def _get_increment_kwargs(git_dir, tag):
    """Calculate the sort of semver increment needed from git history.

    Every commit from HEAD to tag is consider for Sem-Ver metadata lines.
    See the pbr docs for their syntax.

    :return: a dict of kwargs for passing into SemanticVersion.increment.
    """
    result = {}
    if tag:
        version_spec = tag + "..HEAD"
    else:
        version_spec = "HEAD"
    changelog = git._run_git_command(['log', version_spec], git_dir)
    header_len = len('    sem-ver:')
    commands = [line[header_len:].strip() for line in changelog.split('\n')
                if line.lower().startswith('    sem-ver:')]
    symbols = set()
    for command in commands:
        symbols.update([symbol.strip() for symbol in command.split(',')])

    def _handle_symbol(symbol, symbols, impact):
        if symbol in symbols:
            result[impact] = True
            symbols.discard(symbol)
    _handle_symbol('bugfix', symbols, 'patch')
    _handle_symbol('feature', symbols, 'minor')
    _handle_symbol('deprecation', symbols, 'minor')
    _handle_symbol('api-break', symbols, 'major')
    for symbol in symbols:
        log.info('[pbr] Unknown Sem-Ver symbol %r' % symbol)
    # We don't want patch in the kwargs since it is not a keyword argument -
    # its the default minimum increment.
    result.pop('patch', None)
    return result
Beispiel #2
0
def _get_increment_kwargs(git_dir, tag):
    """Calculate the sort of semver increment needed from git history.

    Every commit from HEAD to tag is consider for Sem-Ver metadata lines.
    See the pbr docs for their syntax.

    :return: a dict of kwargs for passing into SemanticVersion.increment.
    """
    result = {}
    if tag:
        version_spec = tag + "..HEAD"
    else:
        version_spec = "HEAD"
    changelog = git._run_git_command(['log', version_spec], git_dir)
    header_len = len('    sem-ver:')
    commands = [line[header_len:].strip() for line in changelog.split('\n')
                if line.lower().startswith('    sem-ver:')]
    symbols = set()
    for command in commands:
        symbols.update([symbol.strip() for symbol in command.split(',')])

    def _handle_symbol(symbol, symbols, impact):
        if symbol in symbols:
            result[impact] = True
            symbols.discard(symbol)
    _handle_symbol('bugfix', symbols, 'patch')
    _handle_symbol('feature', symbols, 'minor')
    _handle_symbol('deprecation', symbols, 'minor')
    _handle_symbol('api-break', symbols, 'major')
    for symbol in symbols:
        log.info('[pbr] Unknown Sem-Ver symbol %r' % symbol)
    # We don't want patch in the kwargs since it is not a keyword argument -
    # its the default minimum increment.
    result.pop('patch', None)
    return result
Beispiel #3
0
def _get_version_from_git(pre_version=None):
    """Calculate a version string from git.

    If the revision is tagged, return that. Otherwise calculate a semantic
    version description of the tree.

    The number of revisions since the last tag is included in the dev counter
    in the version for untagged versions.

    :param pre_version: If supplied use this as the target version rather than
        inferring one from the last tag + commit messages.
    """
    git_dir = git._run_git_functions()
    if git_dir:
        try:
            tagged = git._run_git_command(["describe", "--exact-match"], git_dir, throw_on_error=True).replace("-", ".")
            target_version = version.SemanticVersion.from_pip_string(tagged)
        except Exception:
            if pre_version:
                # not released yet - use pre_version as the target
                target_version = version.SemanticVersion.from_pip_string(pre_version)
            else:
                # not released yet - just calculate from git history
                target_version = None
        result = _get_version_from_git_target(git_dir, target_version)
        return result.release_string()
    # If we don't know the version, return an empty string so at least
    # the downstream users of the value always have the same type of
    # object to work with.
    try:
        return unicode()
    except NameError:
        return ""
Beispiel #4
0
def _get_version_from_git(pre_version):
    """Return a version which is equal to the tag that's on the current
    revision if there is one, or tag plus number of additional revisions
    if the current revision has no tag.
    """

    git_dir = git._run_git_functions()
    if git_dir:
        if pre_version:
            try:
                return git._run_git_command(['describe', '--exact-match'],
                                            git_dir,
                                            throw_on_error=True).replace(
                                                '-', '.')
            except Exception:
                return "%s.dev%s" % (pre_version, _get_revno(git_dir))
        else:
            # git describe always is going to return one of three things
            # - a short-sha if there are no tags
            # - a tag, if there's one on the current revision
            # - a string of the form $last_tag-$revs_since_last_tag-g$short_sha
            raw_version = git._run_git_command(['describe', '--always'],
                                               git_dir)
            # First, if there are no -'s or .'s, then it's just a short sha.
            # Create a synthetic version for it.
            if '-' not in raw_version and '.' not in raw_version:
                return "0.0.0.post%s" % _get_revno(git_dir)
            # Now, we want to strip the short-sha prefix
            stripped_version = raw_version.split('-g')[0]
            # Finally, if we convert - to .post, which will turn the remaining
            # - which separates the version from the revcount into a PEP440
            # post string
            return stripped_version.replace('-', '.post')

    # If we don't know the version, return an empty string so at least
    # the downstream users of the value always have the same type of
    # object to work with.
    try:
        return unicode()
    except NameError:
        return ''
Beispiel #5
0
def _get_version_from_git(pre_version):
    """Return a version which is equal to the tag that's on the current
    revision if there is one, or tag plus number of additional revisions
    if the current revision has no tag.
    """

    git_dir = git._run_git_functions()
    if git_dir:
        if pre_version:
            try:
                return git._run_git_command(
                    ['describe', '--exact-match'], git_dir,
                    throw_on_error=True).replace('-', '.')
            except Exception:
                return "%s.dev%s" % (pre_version, _get_revno(git_dir))
        else:
            # git describe always is going to return one of three things
            # - a short-sha if there are no tags
            # - a tag, if there's one on the current revision
            # - a string of the form $last_tag-$revs_since_last_tag-g$short_sha
            raw_version = git._run_git_command(['describe', '--always'],
                                               git_dir)
            # First, if there are no -'s or .'s, then it's just a short sha.
            # Create a synthetic version for it.
            if '-' not in raw_version and '.' not in raw_version:
                return "0.0.0.post%s" % _get_revno(git_dir)
            # Now, we want to strip the short-sha prefix
            stripped_version = raw_version.split('-g')[0]
            # Finally, if we convert - to .post, which will turn the remaining
            # - which separates the version from the revcount into a PEP440
            # post string
            return stripped_version.replace('-', '.post')

    # If we don't know the version, return an empty string so at least
    # the downstream users of the value always have the same type of
    # object to work with.
    try:
        return unicode()
    except NameError:
        return ''
Beispiel #6
0
def generate_authors(*args, **kwargs):
    old_authors = 'AUTHORS.in'
    new_authors = 'authors.md'
    if os.path.isfile(new_authors) and not os.access(new_authors, os.W_OK):
        # If there's already an AUTHORS file and it's not writable, just use it
        return

    ignore_emails = '((jenkins|zuul)@review|infra@lists|jenkins@openstack)'
    git_dir = os.path.join('..', '.git')
    authors = []

    # don't include jenkins email address in AUTHORS file
    git_log_cmd = ['log', '--format=%aN <%aE>']
    authors += _run_git_command(git_log_cmd, git_dir).split('\n')
    authors = [a for a in authors if not re.search(ignore_emails, a)]

    # get all co-authors from commit messages
    co_authors_out = _run_git_command('log', git_dir)
    co_authors = re.findall('Co-authored-by:.+', co_authors_out,
                            re.MULTILINE)
    co_authors = [signed.split(":", 1)[1].strip()
                  for signed in co_authors if signed]

    authors += co_authors
    authors = sorted(set(authors))

    new_authors_str = bytearray()

    if os.path.exists(old_authors):
        with open(old_authors, "rb") as old_authors_fh:
            new_authors_str += old_authors_fh.read()
    new_authors_str += (os.linesep.join(authors) + os.linesep).encode('utf-8')

    if os.path.isfile(new_authors) and hashlib.sha256(new_authors_str).digest() == sha256_file(new_authors).digest():
        return

    with open(new_authors, 'wb') as f:
        f.write(new_authors_str)
Beispiel #7
0
def _get_revno(git_dir):
    """Return the commit count since the most recent tag.

    We use git-describe to find this out, but if there are no
    tags then we fall back to counting commits since the beginning
    of time.
    """
    raw_tag_info = git._get_raw_tag_info(git_dir)
    if raw_tag_info:
        return raw_tag_info

    # no tags found
    revlist = git._run_git_command(['rev-list', '--abbrev-commit', 'HEAD'],
                                   git_dir)
    return len(revlist.splitlines())
Beispiel #8
0
def _get_revno(git_dir):
    """Return the commit count since the most recent tag.

    We use git-describe to find this out, but if there are no
    tags then we fall back to counting commits since the beginning
    of time.
    """
    raw_tag_info = git._get_raw_tag_info(git_dir)
    if raw_tag_info:
        return raw_tag_info

    # no tags found
    revlist = git._run_git_command(
        ['rev-list', '--abbrev-commit', 'HEAD'], git_dir)
    return len(revlist.splitlines())
Beispiel #9
0
def _get_version_from_git(pre_version=None):
    """Calculate a version string from git.

    If the revision is tagged, return that. Otherwise calculate a semantic
    version description of the tree.

    The number of revisions since the last tag is included in the dev counter
    in the version for untagged versions.

    :param pre_version: If supplied use this as the target version rather than
        inferring one from the last tag + commit messages.
    """
    git_dir = git._run_git_functions()
    if git_dir:
        try:
            tagged = git._run_git_command(['describe', '--exact-match'],
                                          git_dir,
                                          throw_on_error=True).replace(
                                              '-', '.')
            target_version = version.SemanticVersion.from_pip_string(tagged)
        except Exception:
            if pre_version:
                # not released yet - use pre_version as the target
                target_version = version.SemanticVersion.from_pip_string(
                    pre_version)
            else:
                # not released yet - just calculate from git history
                target_version = None
        result = _get_version_from_git_target(git_dir, target_version)
        return result.release_string()
    # If we don't know the version, return an empty string so at least
    # the downstream users of the value always have the same type of
    # object to work with.
    try:
        return unicode()
    except NameError:
        return ''
Beispiel #10
0
 def get_tag(self):
     describe = git._run_git_command(['describe', '--always'], self.git_dir)
     return describe
Beispiel #11
0
    # This can also happen with py>3.8 on conda editable install
    raise ModuleNotFoundError('Must have pbr for python < 3.8')

git_dir = Path(__file__).parent.parent / '.git'

if has_pbr:
    try:
        info = version.VersionInfo(package_name)
        __version__ = __version__ or info.version_string()
        __git_sha__ = git.get_git_short_sha(git_dir)

    except Exception:  # Pbr throws very broad Exception, for some reason DistributionNotFound does not want to be caught
        git_dir = Path(__file__).parent.parent / '.git'
        try:
            tagged = git._run_git_command(['describe', '--tags'],
                                          git_dir,
                                          throw_on_error=True).replace(
                                              '-', '.')
            semantic_version = version.SemanticVersion.from_pip_string(tagged)
            __version__ = __version__ or semantic_version._long_version(None)
            __git_sha__ = git.get_git_short_sha(git_dir)
        except FileNotFoundError:
            # Git not installed
            __git_sha__ = None
else:
    __git_sha__ = None

VERSION_STRING = f'pyHDX version {__version__}'
VERSION_STRING_SHORT = f'pyHDX v{__version__}'
if __git_sha__ is not None:
    VERSION_STRING += f', development version {__git_sha__}'
    VERSION_STRING_SHORT += f' ({__git_sha__})'