xref: /llvm-project/llvm/utils/gn/build/write_vcsrevision.py (revision b71edfaa4ec3c998aadb35255ce2f60bba2940b0)
10ff3cc20SNico Weber#!/usr/bin/env python3
2842a512aSNico Weber
3842a512aSNico Weber"""Gets the current revision and writes it to VCSRevision.h."""
4842a512aSNico Weber
5842a512aSNico Weberimport argparse
6842a512aSNico Weberimport os
7842a512aSNico Weberimport subprocess
8842a512aSNico Weberimport sys
9842a512aSNico Weber
10842a512aSNico Weber
11842a512aSNico WeberTHIS_DIR = os.path.abspath(os.path.dirname(__file__))
12842a512aSNico WeberLLVM_DIR = os.path.dirname(os.path.dirname(os.path.dirname(THIS_DIR)))
13842a512aSNico Weber
14842a512aSNico Weber
15842a512aSNico Weberdef which(program):
16842a512aSNico Weber    # distutils.spawn.which() doesn't find .bat files,
17842a512aSNico Weber    # https://bugs.python.org/issue2200
18842a512aSNico Weber    for path in os.environ["PATH"].split(os.pathsep):
19842a512aSNico Weber        candidate = os.path.join(path, program)
20842a512aSNico Weber        if os.path.isfile(candidate) and os.access(candidate, os.X_OK):
21842a512aSNico Weber            return candidate
22842a512aSNico Weber    return None
23842a512aSNico Weber
24842a512aSNico Weber
25842a512aSNico Weberdef main():
26842a512aSNico Weber    parser = argparse.ArgumentParser(description=__doc__)
27*b71edfaaSTobias Hieta    parser.add_argument(
28*b71edfaaSTobias Hieta        "-d",
29*b71edfaaSTobias Hieta        "--depfile",
30*b71edfaaSTobias Hieta        help="if set, writes a depfile that causes this script "
31*b71edfaaSTobias Hieta        "to re-run each time the current revision changes",
32*b71edfaaSTobias Hieta    )
33*b71edfaaSTobias Hieta    parser.add_argument(
34*b71edfaaSTobias Hieta        "--write-git-rev",
35*b71edfaaSTobias Hieta        action="store_true",
36*b71edfaaSTobias Hieta        help="if set, writes git revision, else writes #undef",
37*b71edfaaSTobias Hieta    )
38*b71edfaaSTobias Hieta    parser.add_argument(
39*b71edfaaSTobias Hieta        "--name",
40*b71edfaaSTobias Hieta        action="append",
41*b71edfaaSTobias Hieta        help="if set, writes a depfile that causes this script "
42*b71edfaaSTobias Hieta        "to re-run each time the current revision changes",
43*b71edfaaSTobias Hieta    )
44*b71edfaaSTobias Hieta    parser.add_argument("vcs_header", help="path to the output file to write")
45842a512aSNico Weber    args = parser.parse_args()
46842a512aSNico Weber
47*b71edfaaSTobias Hieta    vcsrevision_contents = ""
481645f5e4SNico Weber    if args.write_git_rev:
49*b71edfaaSTobias Hieta        git, use_shell = which("git"), False
50*b71edfaaSTobias Hieta        if not git:
51*b71edfaaSTobias Hieta            git = which("git.exe")
52*b71edfaaSTobias Hieta        if not git:
53*b71edfaaSTobias Hieta            git, use_shell = which("git.bat"), True
54*b71edfaaSTobias Hieta        git_dir = (
55*b71edfaaSTobias Hieta            subprocess.check_output(
56*b71edfaaSTobias Hieta                [git, "rev-parse", "--git-dir"], cwd=LLVM_DIR, shell=use_shell
57*b71edfaaSTobias Hieta            )
58*b71edfaaSTobias Hieta            .decode()
59*b71edfaaSTobias Hieta            .strip()
60*b71edfaaSTobias Hieta        )
61ffcd37c5SPeter Collingbourne        if not os.path.isdir(git_dir):
62ffcd37c5SPeter Collingbourne            print('.git dir not found at "%s"' % git_dir, file=sys.stderr)
63ffcd37c5SPeter Collingbourne            return 1
64ffcd37c5SPeter Collingbourne
65*b71edfaaSTobias Hieta        rev = (
66*b71edfaaSTobias Hieta            subprocess.check_output(
67*b71edfaaSTobias Hieta                [git, "rev-parse", "--short", "HEAD"], cwd=git_dir, shell=use_shell
68*b71edfaaSTobias Hieta            )
69*b71edfaaSTobias Hieta            .decode()
70*b71edfaaSTobias Hieta            .strip()
71*b71edfaaSTobias Hieta        )
72*b71edfaaSTobias Hieta        url = (
73*b71edfaaSTobias Hieta            subprocess.check_output(
74*b71edfaaSTobias Hieta                [git, "remote", "get-url", "origin"], cwd=git_dir, shell=use_shell
75*b71edfaaSTobias Hieta            )
76*b71edfaaSTobias Hieta            .decode()
77*b71edfaaSTobias Hieta            .strip()
78*b71edfaaSTobias Hieta        )
79e306255dSNico Weber        for name in args.name:
80e306255dSNico Weber            vcsrevision_contents += '#define %s_REVISION "%s"\n' % (name, rev)
81e306255dSNico Weber            vcsrevision_contents += '#define %s_REPOSITORY "%s"\n' % (name, url)
821645f5e4SNico Weber    else:
831645f5e4SNico Weber        for name in args.name:
84*b71edfaaSTobias Hieta            vcsrevision_contents += "#undef %s_REVISION\n" % name
85*b71edfaaSTobias Hieta            vcsrevision_contents += "#undef %s_REPOSITORY\n" % name
86842a512aSNico Weber
87842a512aSNico Weber    # If the output already exists and is identical to what we'd write,
88842a512aSNico Weber    # return to not perturb the existing file's timestamp.
89*b71edfaaSTobias Hieta    if (
90*b71edfaaSTobias Hieta        os.path.exists(args.vcs_header)
91*b71edfaaSTobias Hieta        and open(args.vcs_header).read() == vcsrevision_contents
92*b71edfaaSTobias Hieta    ):
93842a512aSNico Weber        return 0
94842a512aSNico Weber
95842a512aSNico Weber    # http://neugierig.org/software/blog/2014/11/binary-revisions.html
96842a512aSNico Weber    if args.depfile:
97842a512aSNico Weber        build_dir = os.getcwd()
98*b71edfaaSTobias Hieta        with open(args.depfile, "w") as depfile:
99*b71edfaaSTobias Hieta            depfile.write(
100*b71edfaaSTobias Hieta                "%s: %s\n"
101*b71edfaaSTobias Hieta                % (
102842a512aSNico Weber                    args.vcs_header,
103*b71edfaaSTobias Hieta                    os.path.relpath(os.path.join(git_dir, "logs", "HEAD"), build_dir),
104*b71edfaaSTobias Hieta                )
105*b71edfaaSTobias Hieta            )
106*b71edfaaSTobias Hieta    open(args.vcs_header, "w").write(vcsrevision_contents)
107842a512aSNico Weber
108842a512aSNico Weber
109*b71edfaaSTobias Hietaif __name__ == "__main__":
110842a512aSNico Weber    sys.exit(main())
111