Cleanup: pass 'rctf' rectangle to 2D box drawing functions
[blender.git] / build_files / buildbot / buildbot_utils.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20
21 import argparse
22 import os
23 import re
24 import subprocess
25 import sys
26
27
28 def is_tool(name):
29     """Check whether `name` is on PATH and marked as executable."""
30
31     # from whichcraft import which
32     from shutil import which
33
34     return which(name) is not None
35
36
37 class Builder:
38     def __init__(self, name, branch, codesign):
39         self.name = name
40         self.branch = branch
41         self.is_release_branch = re.match("^blender-v(.*)-release$", branch) is not None
42         self.codesign = codesign
43
44         # Buildbot runs from build/ directory
45         self.blender_dir = os.path.abspath(os.path.join('..', 'blender.git'))
46         self.build_dir = os.path.abspath(os.path.join('..', 'build'))
47         self.install_dir = os.path.abspath(os.path.join('..', 'install'))
48         self.upload_dir = os.path.abspath(os.path.join('..', 'install'))
49
50         # Detect platform
51         if name.startswith('mac'):
52             self.platform = 'mac'
53             self.command_prefix = []
54         elif name.startswith('linux'):
55             self.platform = 'linux'
56             if is_tool('scl'):
57                 self.command_prefix = ['scl', 'enable', 'devtoolset-9', '--']
58             else:
59                 self.command_prefix = []
60         elif name.startswith('win'):
61             self.platform = 'win'
62             self.command_prefix = []
63         else:
64             raise ValueError('Unkonw platform for builder ' + self.platform)
65
66         # Always 64 bit now
67         self.bits = 64
68
69
70 def create_builder_from_arguments():
71     parser = argparse.ArgumentParser()
72     parser.add_argument('builder_name')
73     parser.add_argument('branch', default='master', nargs='?')
74     parser.add_argument("--codesign", action="store_true")
75     args = parser.parse_args()
76     return Builder(args.builder_name, args.branch, args.codesign)
77
78
79 class VersionInfo:
80     def __init__(self, builder):
81         # Get version information
82         buildinfo_h = os.path.join(builder.build_dir, "source", "creator", "buildinfo.h")
83         blender_h = os.path.join(builder.blender_dir, "source", "blender", "blenkernel", "BKE_blender_version.h")
84
85         version_number = int(self._parse_header_file(blender_h, 'BLENDER_VERSION'))
86         version_number_patch = int(self._parse_header_file(blender_h, 'BLENDER_VERSION_PATCH'))
87         version_numbers = (version_number // 100, version_number % 100, version_number_patch)
88         self.short_version = "%d.%02d" % (version_numbers[0], version_numbers[1])
89         self.version = "%d.%02d.%d" % version_numbers
90         self.version_cycle = self._parse_header_file(blender_h, 'BLENDER_VERSION_CYCLE')
91         self.version_cycle_number = self._parse_header_file(blender_h, 'BLENDER_VERSION_CYCLE_NUMBER')
92         self.hash = self._parse_header_file(buildinfo_h, 'BUILD_HASH')[1:-1]
93
94         if self.version_cycle == "release":
95             # Final release
96             self.full_version = self.version
97             self.is_development_build = False
98         elif self.version_cycle == "rc":
99             # Release candidate
100             version_cycle = self.version_cycle + self.version_cycle_number
101             self.full_version = self.version + version_cycle
102             self.is_development_build = False
103         else:
104             # Development build
105             self.full_version = self.version + '-' + self.hash
106             self.is_development_build = True
107
108     def _parse_header_file(self, filename, define):
109         import re
110         regex = re.compile(r"^#\s*define\s+%s\s+(.*)" % define)
111         with open(filename, "r") as file:
112             for l in file:
113                 match = regex.match(l)
114                 if match:
115                     return match.group(1)
116         return None
117
118
119 def call(cmd, env=None, exit_on_error=True):
120     print(' '.join(cmd))
121
122     # Flush to ensure correct order output on Windows.
123     sys.stdout.flush()
124     sys.stderr.flush()
125
126     retcode = subprocess.call(cmd, env=env)
127     if exit_on_error and retcode != 0:
128         sys.exit(retcode)
129     return retcode