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