summaryrefslogtreecommitdiff
path: root/tools/read-version
blob: 02c906438ca3e56b5f26e80268c22f871be7c3cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env python3

import os
import json
import subprocess
import sys

if "avoid-pep8-E402-import-not-top-of-file":
    _tdir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
    sys.path.insert(0, _tdir)
    from cloudinit import version as ci_version


def tiny_p(cmd, capture=True):
    # python 2.6 doesn't have check_output
    stdout = subprocess.PIPE
    stderr = subprocess.PIPE
    sp = subprocess.Popen(cmd, stdout=stdout,
                          stderr=stderr, stdin=None,
                          universal_newlines=True)
    (out, err) = sp.communicate()
    ret = sp.returncode
    if ret not in [0]:
        raise RuntimeError("Failed running %s [rc=%s] (%s, %s)" %
                           (cmd, ret, out, err))
    return out


def which(program):
    # Return path of program for execution if found in path
    def is_exe(fpath):
        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

    _fpath, _ = os.path.split(program)
    if _fpath:
        if is_exe(program):
            return program
    else:
        for path in os.environ.get("PATH", "").split(os.pathsep):
            path = path.strip('"')
            exe_file = os.path.join(path, program)
            if is_exe(exe_file):
                return exe_file

    return None


def is_gitdir(path):
    # Return boolean indicating if path is a git tree.
    git_meta = os.path.join(path, '.git')
    if os.path.isdir(git_meta):
        return True
    if os.path.exists(git_meta):
        # in a git worktree, .git is a file with 'gitdir: x'
        with open(git_meta, "rb") as fp:
            if b'gitdir:' in fp.read():
                return True
    return False


use_long = '--long' in sys.argv or os.environ.get('CI_RV_LONG')
use_tags = '--tags' in sys.argv or os.environ.get('CI_RV_TAGS')
output_json = '--json' in sys.argv

src_version = ci_version.version_string()
version_long = None

# If we're performing CI for a new release branch (which our tooling creates
# with an "upstream/" prefix), then we don't want to enforce strict version
# matching because we know it will fail.
is_release_branch_ci = (
    os.environ.get("TRAVIS_PULL_REQUEST_BRANCH", "").startswith("upstream/")
)
if is_gitdir(_tdir) and which("git") and not is_release_branch_ci:
    flags = []
    if use_tags:
        flags = ['--tags']
    cmd = ['git', 'describe', '--abbrev=8', '--match=[0-9]*'] + flags

    try:
        version = tiny_p(cmd).strip()
    except RuntimeError:
        version = None

    if version is None or not version.startswith(src_version):
        sys.stderr.write("git describe version (%s) differs from "
                         "cloudinit.version (%s)\n" % (version, src_version))
        sys.stderr.write(
            "Please get the latest upstream tags.\n"
            "As an example, this can be done with the following:\n"
            "$ git remote add upstream https://git.launchpad.net/cloud-init\n"
            "$ git fetch upstream --tags\n"
        )
        sys.exit(1)

    version_long = tiny_p(cmd + ["--long"]).strip()
else:
    version = src_version
    version_long = None

# version is X.Y.Z[+xxx.gHASH]
# version_long is None or X.Y.Z-xxx-gHASH
release = version.partition("-")[0]
extra = None
commit = None
distance = None

if version_long:
    info = version_long.partition("-")[2]
    extra = "-" + info
    distance, commit = info.split("-")
    # remove the 'g' from gHASH
    commit = commit[1:]

data = {
    'release': release,
    'version': version,
    'version_long': version_long,
    'extra': extra,
    'commit': commit,
    'distance': distance,
    'is_release_branch_ci': is_release_branch_ci,
}

if output_json:
    sys.stdout.write(json.dumps(data, indent=1) + "\n")
else:
    sys.stdout.write(release + "\n")

sys.exit(0)

# vi: ts=4 expandtab