Skip to content

Commit 7a6fd45

Browse files
committed
[dist] Save recipes version into dist_info.json
This way, we can later check if any recipe has been updated, so we can rebuild it if necessary
1 parent d657f9e commit 7a6fd45

File tree

1 file changed

+105
-27
lines changed

1 file changed

+105
-27
lines changed

pythonforandroid/distribution.py

Lines changed: 105 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
import json
44

55
from pythonforandroid import __version__
6-
from pythonforandroid.logger import (info, info_notify, warning, Err_Style, Err_Fore)
6+
from pythonforandroid.logger import (
7+
info, debug, info_notify, warning, Err_Style, Err_Fore
8+
)
79
from pythonforandroid.util import current_directory, BuildInterruptingException
10+
from pythonforandroid.recipe import Recipe
811
from shutil import rmtree
912

1013

@@ -30,7 +33,11 @@ class Distribution(object):
3033
archs = []
3134
'''The arch targets that the dist is built for.'''
3235

33-
recipes = []
36+
recipes = {}
37+
'''A dictionary which holds recipes information. Each key is the name of
38+
the recipe, and the value is recipe's version'''
39+
40+
recipes_to_rebuild = set()
3441

3542
description = '' # A long description
3643

@@ -88,6 +95,8 @@ def get_distribution(cls, ctx, name=None, recipes=[],
8895

8996
req_archs = [arch.arch for arch in ctx.archs]
9097

98+
recipes_with_version = cls.get_recipes_with_version(ctx, recipes)
99+
91100
# 0) Check if a dist with that name already exists
92101
if name is not None and name:
93102
possible_dists = [d for d in possible_dists if d.name == name]
@@ -106,10 +115,38 @@ def get_distribution(cls, ctx, name=None, recipes=[],
106115
]
107116
):
108117
continue
109-
for recipe in recipes:
110-
if recipe not in dist.recipes:
118+
checked_dist_recipes = set()
119+
for recipe_name, recipe_version in recipes_with_version.items():
120+
if recipe_name not in dist.recipes.keys():
111121
break
122+
debug('Checking version for {} recipe: {} VS {}'.format(
123+
recipe_name, dist.recipes[recipe_name], recipe_version)
124+
)
125+
if dist.recipes[recipe_name] != recipe_version:
126+
warning(
127+
'Recipe {} has a newer version, '
128+
'adding it to recipes_to_rebuild'.format(recipe_name)
129+
)
130+
dist.recipes_to_rebuild.add(recipe_name)
131+
checked_dist_recipes.add(recipe_name)
112132
else:
133+
# Check that the dist recipes has not changed (without
134+
# considering the ones we already computed above)
135+
for recipe_name, recipe_version in dist.recipes.items():
136+
if recipe_name in dist.recipes_to_rebuild:
137+
continue
138+
try:
139+
test_recipe = Recipe.get_recipe(recipe_name, ctx)
140+
except ValueError:
141+
# we don't have a recipe so skipping it
142+
continue
143+
if test_recipe.version != recipe_version:
144+
warning(
145+
'Recipe {} has a newer version,'
146+
' adding to rebuild'.format(recipe_name)
147+
)
148+
dist.recipes_to_rebuild.add(recipe_name)
149+
113150
_possible_dists.append(dist)
114151
possible_dists = _possible_dists
115152

@@ -125,16 +162,25 @@ def get_distribution(cls, ctx, name=None, recipes=[],
125162
for dist in possible_dists:
126163
if force_build:
127164
continue
128-
if (set(dist.recipes) == set(recipes) or
129-
(set(recipes).issubset(set(dist.recipes)) and
130-
not require_perfect_match)):
165+
if set(dist.recipes.keys()) == set(recipes) or (
166+
set(recipes).issubset(set(dist.recipes.keys()))
167+
and not require_perfect_match
168+
):
131169
info_notify('{} has compatible recipes, using this one'
132170
.format(dist.name))
133171
if dist.p4a_version != __version__:
134172
# We build this dist with a different version of p4a, so
135173
# we mark it as a dist that requires a clean build environ
136174
# (to avoid old cached builds issues)
137175
dist.needs_clean_build = True
176+
elif dist.recipes_to_rebuild:
177+
dist.needs_build = True
178+
info_notify(
179+
'Some of the recipes has new versions,'
180+
' we will update them:\n\t- {}'.format(
181+
'\n\t- '.join(dist.recipes_to_rebuild)
182+
)
183+
)
138184
return dist
139185

140186
assert len(possible_dists) < 2
@@ -180,7 +226,7 @@ def get_distribution(cls, ctx, name=None, recipes=[],
180226

181227
dist.name = name
182228
dist.dist_dir = join(ctx.dist_dir, dist.name)
183-
dist.recipes = recipes
229+
dist.recipes = recipes_with_version
184230
dist.archs = req_archs
185231
dist.ndk_api = ctx.ndk_api
186232
dist.android_api = ctx.android_api
@@ -232,38 +278,70 @@ def get_distributions(cls, ctx, extra_dist_dirs=[]):
232278
dists.append(dist)
233279
return dists
234280

281+
@classmethod
282+
def get_recipes_with_version(cls, ctx, recipes_names):
283+
recipes_with_version = {}
284+
for name in recipes_names:
285+
try:
286+
version = Recipe.get_recipe(name, ctx).version
287+
except ValueError:
288+
# we don't have a recipe (it's a pure python module, and we
289+
# don't know the version, so we set it to None)
290+
version = None
291+
recipes_with_version[name] = version
292+
return recipes_with_version
293+
235294
def save_info(self, dirn):
236295
'''
237296
Save information about the distribution in its dist_dir.
238297
'''
239298
with current_directory(dirn):
240299
info('Saving distribution info')
300+
# Add version to recipes, so we can detect
301+
# any change and rebuild them if necessary
302+
recipes_with_version = self.get_recipes_with_version(
303+
self.ctx, self.ctx.recipe_build_order + self.ctx.python_modules
304+
)
305+
py_version = self.ctx.python_recipe.major_minor_version_string
241306
with open('dist_info.json', 'w') as fileh:
242-
json.dump({'dist_name': self.ctx.dist_name,
243-
'bootstrap': self.ctx.bootstrap.name,
244-
'archs': [arch.arch for arch in self.ctx.archs],
245-
'ndk_api': self.ctx.ndk_api,
246-
'android_api': self.ctx.android_api,
247-
'use_setup_py': self.ctx.use_setup_py,
248-
'recipes': self.ctx.recipe_build_order + self.ctx.python_modules,
249-
'hostpython': self.ctx.hostpython,
250-
'python_version': self.ctx.python_recipe.major_minor_version_string,
251-
'p4a_version': __version__},
252-
fileh)
307+
json.dump(
308+
{
309+
'dist_name': self.ctx.dist_name,
310+
'bootstrap': self.ctx.bootstrap.name,
311+
'archs': [arch.arch for arch in self.ctx.archs],
312+
'ndk_api': self.ctx.ndk_api,
313+
'android_api': self.ctx.android_api,
314+
'use_setup_py': self.ctx.use_setup_py,
315+
'recipes': recipes_with_version,
316+
'hostpython': self.ctx.hostpython,
317+
'python_version': py_version,
318+
'p4a_version': __version__,
319+
},
320+
fileh,
321+
indent=4,
322+
sort_keys=True,
323+
)
253324

254325

255326
def pretty_log_dists(dists, log_func=info):
256327
infos = []
257328
for dist in dists:
258329
ndk_api = 'unknown' if dist.ndk_api is None else dist.ndk_api
259-
infos.append('{Fore.GREEN}{Style.BRIGHT}{name}{Style.RESET_ALL}: min API {ndk_api}, '
260-
'includes recipes ({Fore.GREEN}{recipes}'
261-
'{Style.RESET_ALL}), built for archs ({Fore.BLUE}'
262-
'{archs}{Style.RESET_ALL})'.format(
263-
ndk_api=ndk_api,
264-
name=dist.name, recipes=', '.join(dist.recipes),
265-
archs=', '.join(dist.archs) if dist.archs else 'UNKNOWN',
266-
Fore=Err_Fore, Style=Err_Style))
330+
infos.append(
331+
'{Fore.GREEN}{Style.BRIGHT}{name}{Style.RESET_ALL}: '
332+
'min API {ndk_api}, '
333+
'includes recipes ({Fore.GREEN}{recipes}{Style.RESET_ALL}), '
334+
'recipes to rebuild({Fore.GREEN}{to_rebuild}{Style.RESET_ALL}), '
335+
'built for archs ({Fore.BLUE}{archs}{Style.RESET_ALL})'.format(
336+
ndk_api=ndk_api,
337+
name=dist.name,
338+
recipes=", ".join("{}".format(k) for k in dist.recipes.keys()),
339+
to_rebuild=", ".join(dist.recipes_to_rebuild),
340+
archs=', '.join(dist.archs) if dist.archs else 'UNKNOWN',
341+
Fore=Err_Fore,
342+
Style=Err_Style,
343+
)
344+
)
267345

268346
for line in infos:
269347
log_func('\t' + line)

0 commit comments

Comments
 (0)