openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
build_info.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 # use encoding=utf8
3 # SPDX-FileCopyrightText: Copyright (c) NumeriCor GmbH
4 # SPDX-License-Identifier: LicenseRef-APL-1.1
5 
6 """
7 Generate a C header file defining some information about the build.
8 """
9 
10 import os
11 import sys
12 import subprocess
13 import urllib.parse
14 
15 def run(cmd, env=None):
16  """
17  Run a command with subprocess and return the stdout.
18 
19  Avoiding use of subprocess.check_output to maintain backwards
20  compatibility.
21  """
22  proc = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE)
23  out = proc.communicate()
24  if proc.returncode != 0:
25  tpl = 'execution of command "{0}" failed'
26  raise Exception(tpl.format(' '.join(cmd)))
27  return out[0]
28 
29 def locale():
30  """
31  Determine the locale to use in SVN.
32  """
33 
34  de = None
35 
36  for line in run(['locale', '-a']).split('\n'):
37 
38  entry = line.strip()
39 
40  if entry.startswith('en'):
41  return entry
42 
43  if entry.startswith('de'):
44  de = entry
45 
46  # German a good fallback as 'revision' and 'relative url' are the same
47  if de is not None:
48  return de
49 
50  # If all else fails
51  return 'C'
52 
53 SVN_NAME_MAPPING = {'RĂ©vision': 'Revision'}
54 
55 def svn(directory='.'):
56  """
57  Get information about the SVN repository.
58 
59  Uses the --show-item syntax instead of parsing the normal svn info output
60  to avoid issues with language locales.
61  """
62 
63  start_wd = os.getcwd()
64 
65  os.chdir(directory)
66  result = run(['svn', 'info'], env={'LC_MESSAGES': locale()})
67  os.chdir(start_wd)
68 
69  info = {}
70 
71  for line in result.split('\n'):
72 
73  try:
74  name, value = line.split(': ')
75  except ValueError:
76  continue
77 
78  # Translate where necessary
79  name = SVN_NAME_MAPPING.get(name.strip(), name.strip())
80  name = name.lower().replace(' ', '-')
81 
82  info[name] = value.strip()
83 
84  if name == 'revision':
85  info['commit'] = info[name]
86 
87  return info
88 
89 def git(directory='.'):
90  start_wd = os.getcwd()
91  os.chdir(directory)
92  info = {}
93 
94  # get the git revision count
95  result = run(['git', 'rev-list', '--all', '--count'])
96  info['revision'] = str(int(result));
97 
98  # get commit hash
99  result = run(['git', 'rev-parse', 'HEAD'])
100  result = result[0:len(result)-1]
101  info['commit'] = result.decode('ascii')
102 
103  # get the git tag
104  result = run(['git', 'describe', '--tags', '--always'])
105  result = result[0:len(result)-1]
106  info['tag'] = result.decode('ascii')
107 
108  # get the git remote url
109  result = run(['git', 'remote', '-v'])
110 
111  for line in result.decode('ascii').split('\n'):
112  line = ' '.join(line.split())
113 
114  try:
115  alias, path, direction = line.split(' ')
116  except ValueError:
117  continue
118 
119  if alias == 'origin':
120  # drop user-info (e.g. CI job tokens) from the url
121  parts = urllib.parse.urlsplit(path)
122  info['url'] = urllib.parse.urlunsplit(parts._replace(netloc=parts.netloc.rpartition('@')[2]))
123 
124  # the subrepo is just '.'
125  info['subrepo'] = '.'
126 
127  os.chdir(start_wd)
128 
129  return info
130 
131 
132 
133 TEMPLATE = """// SPDX-FileCopyrightText: Copyright (c) NumeriCor GmbH
134 // SPDX-License-Identifier: LicenseRef-APL-1.1
135 
136 #ifndef __BUILD_INFO__
137 #define __BUILD_INFO__
138 
139 #define GIT_COMMIT_TAG "{tag}"
140 #define GIT_COMMIT_HASH "{commit}"
141 #define GIT_COMMIT_COUNT {revision}
142 #define GIT_PATH "{url}"
143 
144 #define SUBREPO_REVISIONS "{subrepo}"
145 
146 #define SUBREPO_COMMITS "{subrepocommit}"
147 
148 #endif
149 """
150 
151 def generate():
152 
153  # check whether we are in a git repo
154  if subprocess.call(["git", "branch"], stderr=subprocess.STDOUT, stdout=open(os.devnull, 'w')) == 0:
155  info = git(os.path.dirname(os.path.abspath(__file__)))
156 
157  # Get subrepo info
158  repo_versions = []
159  repo_commits = []
160 
161  # we currently have no sub-repos. still, we leave the mechanism in here for later
162  # repo_versions.append(('slimfem', git('../fem/slimfem')['revision']))
163  # repo_commits.append(( 'slimfem', git('../fem/slimfem')['commit']))
164 
165  info['subrepo'] = ','.join(['{0[0]}={0[1]}'.format(v) for v in repo_versions])
166 
167  # Assemble commit hashes / revisions
168  newline = '," \\\n' + ' ' * 24 + '"'
169  info['subrepocommit'] = newline.join(['{0[0]}={0[1]}'.format(v) for v in repo_commits])
170 
171  else:
172  info = {}
173  info['tag'] = "built outside a repository"
174  info['commit'] = "built outside a repository"
175  info['revision'] = 0
176  info['url'] = "https://git.opencarp.org/openCARP/openCARP.git"
177  info['subrepo'] = ""
178  info['subrepocommit'] = ""
179 
180  return TEMPLATE.format(**info)
181 
182 def print_build_info(filename):
183  """
184  print build info
185  """
186  git_info = generate()
187  update_file = True
188 
189  # check if there's a change of the build info if the file already exists
190  if os.path.isfile(filename):
191  with open(filename, 'r') as myfile:
192  info_h = myfile.read()
193  if info_h == git_info:
194  update_file = False
195 
196  # write build info file
197  if update_file:
198  f = open(filename, "w")
199  f.write(git_info)
200 
201 if __name__ == '__main__':
202  if(len(sys.argv) > 1):
203  filename = sys.argv[1]
204  else:
205  filename = 'build_info.h'
206  print_build_info(filename)
def generate()
Definition: build_info.py:151
def git(directory='.')
Definition: build_info.py:89
def svn(directory='.')
Definition: build_info.py:55
def locale()
Definition: build_info.py:29
def run(cmd, env=None)
Definition: build_info.py:15
def print_build_info(filename)
Definition: build_info.py:182