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