ya2 · news · projects · code · about

gettext: --no-location
[pmachines.git] / ya2 / build / build.py
1 '''Tools for making the builds.'''
2 from os import walk, chdir, getcwd
3 from os.path import join, exists, dirname, getmtime, sep
4 from subprocess import PIPE, run
5 from time import strftime
6 from pathlib import Path
7 from hashlib import md5
8
9
10 # TODO refactor: make class BuilderTools
11
12
13 def exec_cmd(cmd, check=True):
14 '''Synchronously executes a command and returns its output.'''
15 # ret = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate()
16 # return ret[0].decode('utf-8').strip()
17 proc = run(cmd, shell=True, stdout=PIPE, stderr=PIPE, universal_newlines=True, check=check)
18 return proc.stdout.strip() + proc.stderr.strip()
19
20
21 def _branch():
22 '''Returns the current branch.'''
23 git_branch = exec_cmd('git symbolic-ref HEAD').split('/')[-1].strip()
24 print(f'git_branch result: {git_branch}')
25 branches = ['master', 'rc', 'stable']
26 if git_branch in branches:
27 print(f'git_branch: {git_branch}')
28 return git_branch
29 root = str(Path(dirname(dirname(__file__))).parent) + '/'
30 if 'itch' in __file__.split(sep):
31 root = str(Path(dirname(__file__))) + '/'
32 if __file__ == '/app/bin/pmachines': # flatpak
33 root = '/app/bin/'
34 for __branch in branches:
35 try:
36 print(f'try: {root}' + 'assets/build_version.txt')
37 with open(root + 'assets/build_version.txt', encoding='utf8') as fver:
38 __ver = fver.read()
39 print(f'ver: {__ver}')
40 # if __branch in __ver:
41 b2c = {'master': 'a', 'rc': 'r', 'stable': '.'}
42 if __ver[1] == b2c[__branch]:
43 return __branch
44 except FileNotFoundError:
45 print(f'file not found: {root}' + 'assets/build_version.txt')
46 return ''
47
48
49 def _commit():
50 '''Returns the current branch.'''
51 git_commit = exec_cmd('git rev-parse HEAD')[:7]
52 print(f'git_commit result: {git_commit}')
53 if not git_commit.startswith("Can't r"):
54 return git_commit
55 root = str(Path(dirname(dirname(__file__))).parent) + '/'
56 if 'itch' in __file__.split(sep):
57 root = str(Path(dirname(__file__))) + '/'
58 if __file__ == '/app/bin/pmachines': # flatpak
59 root = '/app/bin/'
60 try:
61 print(f'try: {root}' + 'assets/build_version.txt')
62 with open(root + 'assets/build_version.txt', encoding='utf8') as fver:
63 __ver = fver.read()
64 print(f'ver: {__ver}')
65 return __ver.split('-')[1]
66 except FileNotFoundError:
67 print(f'file not found: {root}' + 'assets/build_version.txt')
68 return ''
69
70
71 def _version():
72 '''Computes the version of the current build.'''
73 day = strftime('%y%m%d')
74 root = str(Path(dirname(dirname(__file__))).parent) + '/'
75 if __file__ == '/app/bin/pmachines': # flatpak
76 root = '/app/bin/'
77 if _branch() == 'stable':
78 pref, _ver = '', ''
79 if exists(root + 'assets/version.txt'):
80 with open(root + 'assets/version.txt', encoding='utf8') as fver:
81 pref = fver.read().strip() + '-' # + _branch() + '-'
82 _ver = fver.read().strip()
83 ret_ver = _ver or ('0.' + day)
84 else:
85 # try: we want an error!
86 pref = {'master': 'a', 'rc': 'rc', '': 'runtime'}[_branch()]
87 # except KeyError:
88 # pref = 'notfound'
89 ret_ver = f'0{pref}{day}'
90 pref = ret_ver
91 bld_ver = pref + '-' + _commit()
92 try:
93 with open(root + 'assets/build_version.txt', 'w', encoding='utf8') as fver:
94 fver.write(bld_ver)
95 except OSError:
96 print("we can't write inside flatpaks, but we don't need it")
97 return ret_ver
98
99
100 class FindFileNamesArgs:
101
102 def __init__(self, extensions, excluding_directories=None,
103 excluding_files_ending_with=None, root_path='.'):
104 self.extensions = extensions
105 self.excluding_directories = excluding_directories
106 self.excluding_files_ending_with = excluding_files_ending_with
107 self.root_path = root_path
108
109
110 def find_file_names(find_info):
111 #TODO avoid FindFileNamesArgs, write multiple functions with different
112 # behaviors: this is a function which does more than one thing
113 _extensions = find_info.extensions
114 excl_dirs = find_info.excluding_directories
115 excl_ends_with = find_info.excluding_files_ending_with
116 root_path = find_info.root_path
117 return [join(root, fname)
118 for root, _, fnames in walk(root_path)
119 for fname in __files_ext(fnames, _extensions)
120 if not any(e_d in root.split('/') for e_d in excl_dirs or []) and
121 not any(fname.endswith(e_e) for e_e in excl_ends_with or [])]
122
123
124 def __files_ext(fnames, _extensions):
125 return [fname for fname in fnames
126 if any(fname.endswith('.' + ext) for ext in _extensions)]
127
128
129 def __to_be_built_single(src, tgt):
130 if getmtime(tgt) > getmtime(src):
131 print(f'{tgt} is newer than {src}: do not build')
132 return False
133 with open(src, 'rb') as fsrc:
134 src_content = fsrc.read()
135 with open(tgt, 'rb') as ftgt:
136 tgt_content = ftgt.read()
137 hash_src = md5(src_content).hexdigest()
138 hash_tgt = md5(tgt_content).hexdigest()
139 cache = {}
140 lines = []
141 if exists('hash_cache.txt'):
142 with open('hash_cache.txt', encoding='utf8') as fhash:
143 lines = fhash.readlines()
144 for line in lines:
145 line_spl = line.split()
146 _hash = line_spl[-1]
147 fname = ' '.join(line_spl[:-1])
148 cache[fname] = _hash
149 if src in cache and tgt in cache:
150 if hash_src == cache[src] and \
151 hash_tgt == cache[tgt]:
152 print(f'{tgt} and {src} are in the cache: do not build')
153 return False
154 print(f'{src} and {tgt} are not up-to-date: building...')
155 return True
156
157
158 def to_be_built(tgt, srcs):
159 '''Should tgt be built (i.e. is it older?) from sources srcs?'''
160 if not exists(tgt):
161 print(tgt + ' does not exist: building...')
162 return True
163 return any(__to_be_built_single(src, tgt) for src in srcs)
164
165
166 class InsideDir:
167 '''Context manager for working inside a directory.'''
168
169 def __init__(self, dir_):
170 self.dir = dir_
171 self.old_dir = getcwd()
172
173 def __enter__(self):
174 chdir(self.dir)
175
176 def __exit__(self, exc_type, exc_val, exc_tb):
177 chdir(self.old_dir)
178
179
180 # bld_dpath = 'build/'
181 # branch = _branch()
182 # ver = _version()
183 # win_fpath = '{dst_dir}{appname}-' + f'{branch}-windows.exe'
184 # osx_fpath = '{dst_dir}{appname}-%s-osx.zip' % branch
185 # flatpak_fpath = '{dst_dir}{appname}-%s-flatpak' % branch
186 # appimage_fpath = '{dst_dir}{appname}-' + f'{branch}-appimage'
187 # docs_fpath = '{dst_dir}{appname}-%s-docs.tar.gz' % branch