summaryrefslogtreecommitdiff
path: root/tools/read-version
blob: 6dca659e0f2e41a1151550f91da11fec470779a8 (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
#!/usr/bin/env python

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 is_gitdir(_tdir) and which("git"):
    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,
}

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