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