def run(self, config, args): cookbook = CookBook(config) recipe_name = args.recipe[0] all_deps = args.all graph = args.graph if all_deps: recipes = cookbook.list_recipe_deps(recipe_name) else: recipes = [ cookbook.get_recipe(x) for x in cookbook.get_recipe(recipe_name).list_deps() ] if len(recipes) == 0: m.message(_('%s has 0 dependencies') % recipe_name) return if not graph: for recipe in recipes: # Don't print the recipe we asked for if recipe.name == recipe_name: continue m.message(recipe.name) else: def print_dep(cookbook, recipe, level=0, already_shown=[]): m.message("%s%s" % (" " * 3 * level, recipe.name)) already_shown.append(recipe) for r in [cookbook.get_recipe(x) for x in recipe.list_deps()]: if not r in already_shown: print_dep(cookbook, r, level + 1, already_shown) elif not r.name == recipe.name: m.message("%s(%s)" % (" " * 3 * (level + 1), r.name)) print_dep(cookbook, cookbook.get_recipe(recipe_name))
def run(self, config, args): cookbook = CookBook(config) recipe_name = args.recipe[0] all_deps = args.all graph = args.graph if all_deps: recipes = cookbook.list_recipe_deps(recipe_name) else: recipes = [cookbook.get_recipe(x) for x in cookbook.get_recipe(recipe_name).list_deps()] if len(recipes) == 0: m.message(_('%s has 0 dependencies') % recipe_name) return if not graph: for recipe in recipes: # Don't print the recipe we asked for if recipe.name == recipe_name: continue m.message(recipe.name) else: def print_dep(cookbook, recipe, level=0, already_shown=[]): m.message("%s%s" %( " " * 3 * level, recipe.name)) already_shown.append(recipe) for r in [cookbook.get_recipe(x) for x in recipe.list_deps()]: if not r in already_shown: print_dep(cookbook, r, level + 1, already_shown) elif not r.name == recipe.name: m.message("%s(%s)" % ( " " * 3 * (level + 1), r.name)) print_dep(cookbook, cookbook.get_recipe(recipe_name))
def run(self, config, args): cookbook = CookBook(config) recipe_name = args.recipe[0] recursive = args.recursive recipe = cookbook.get_recipe(recipe_name) if recursive: ordered_recipes = cookbook.list_recipe_deps(recipe_name) else: ordered_recipes = [recipe] for recipe in ordered_recipes: if cookbook.recipe_needs_build(recipe.name): raise FatalError(_("Recipe %s is not built yet" % recipe.name)) for recipe in ordered_recipes: # call step function stepfunc = None try: stepfunc = getattr(recipe, 'check') except: m.message('%s has no check step, skipped' % recipe.name) if stepfunc: try: stepfunc() except FatalError as e: raise e except Exception as ex: raise FatalError(_("Error running %s checks: %s") % (recipe.name, ex))
def run(self, config, args): cookbook = CookBook(config) if args.recipe == 'all': recipes = cookbook.get_recipes_list() else: recipes = [cookbook.get_recipe(args.recipe)] if len(recipes) == 0: m.message(_("No recipes found")) tagname = args.tagname tagdescription = args.tagdescription force = args.force for recipe in recipes: if recipe.stype != SourceType.GIT and \ recipe.stype != SourceType.GIT_TARBALL: m.message(_("Recipe '%s' has a custom source repository, " "skipping") % recipe.name) continue recipe.fetch(checkout=False) tags = git.list_tags(recipe.repo_dir) exists = (tagname in tags) if exists: if not force: m.warning(_("Recipe '%s' tag '%s' already exists, " "not updating" % (recipe.name, tagname))) continue git.delete_tag(recipe.repo_dir, tagname) commit = 'origin/sdk-%s' % recipe.version git.create_tag(recipe.repo_dir, tagname, tagdescription, commit)
def run(self, config, args): cookbook = CookBook(config) recipe_name = args.recipe[0] recursive = args.recursive recipe = cookbook.get_recipe(recipe_name) if recursive: ordered_recipes = cookbook.list_recipe_deps(recipe_name) else: ordered_recipes = [recipe] for recipe in ordered_recipes: if cookbook.recipe_needs_build(recipe.name): raise FatalError(_("Recipe %s is not built yet" % recipe.name)) for recipe in ordered_recipes: # call step function stepfunc = None try: stepfunc = getattr(recipe, 'check') except: m.message('%s has no check step, skipped' % recipe.name) if stepfunc: try: if asyncio.iscoroutinefunction(stepfunc): run_until_complete(stepfunc()) else: stepfunc() except FatalError as e: raise e except Exception as ex: raise FatalError( _("Error running %s checks: %s") % (recipe.name, ex))
def run(self, config, args): cookbook = CookBook(config) failed = [] p_name = args.package[0] store = PackagesStore(config) p = store.get_package(p_name) ordered_recipes = map(lambda x: cookbook.get_recipe(x), p.recipes_dependencies()) for recipe in ordered_recipes: if cookbook.recipe_needs_build(recipe.name): raise CommandError(_("Recipe %s is not built yet" % recipe.name)) for recipe in ordered_recipes: # call step function stepfunc = None try: stepfunc = getattr(recipe, 'check') except: m.message('%s has no check step, skipped' % recipe.name) if stepfunc: try: m.message('Running checks for recipe %s' % recipe.name) stepfunc() except Exception, ex: failed.append(recipe.name) m.warning(_("%s checks failed: %s") % (recipe.name, ex))
def list_gstreamer_1_0_plugins_by_category(config): cookbook = CookBook(config) plugins = defaultdict(list) for r in [ 'gstreamer-1.0', 'gst-plugins-base-1.0', 'gst-plugins-good-1.0', 'gst-plugins-bad-1.0', 'gst-plugins-ugly-1.0', 'gst-libav-1.0', 'gst-editing-services-1.0', 'gst-rtsp-server-1.0' ]: r = cookbook.get_recipe(r) for attr_name in dir(r): if attr_name.startswith('files_plugins_'): cat_name = attr_name[len('files_plugins_'):] plugins_list = getattr(r, attr_name) elif attr_name.startswith('platform_files_plugins_'): cat_name = attr_name[len('platform_files_plugins_'):] plugins_dict = getattr(r, attr_name) plugins_list = plugins_dict.get(config.target_platform, []) else: continue for e in plugins_list: if not e.startswith('lib/gstreamer-'): continue c = e.split('/') if len(c) != 3: continue e = c[2] if e.startswith('libgst'): e = e[6:-8] else: e = e[3:-8] plugins[cat_name].append(e) return plugins
def run(self, config, args): cookbook = CookBook(config) if args.recipe == 'all': recipes = cookbook.get_recipes_list() else: recipes = [cookbook.get_recipe(args.recipe)] if len(recipes) == 0: m.message(_("No recipes found")) tagname = args.tagname tagdescription = args.tagdescription force = args.force for recipe in recipes: if recipe.stype != SourceType.GIT and \ recipe.stype != SourceType.GIT_TARBALL: m.message( _("Recipe '%s' has a custom source repository, " "skipping") % recipe.name) continue recipe.fetch(checkout=False) tags = git.list_tags(recipe.repo_dir) exists = (tagname in tags) if exists: if not force: m.warning( _("Recipe '%s' tag '%s' already exists, " "not updating" % (recipe.name, tagname))) continue git.delete_tag(recipe.repo_dir, tagname) commit = 'origin/sdk-%s' % recipe.version git.create_tag(recipe.repo_dir, tagname, tagdescription, commit)
def run(self, config, args): cookbook = CookBook(config) failed = [] p_name = args.package[0] store = PackagesStore(config) p = store.get_package(p_name) ordered_recipes = map(lambda x: cookbook.get_recipe(x), p.recipes_dependencies()) for recipe in ordered_recipes: if cookbook.recipe_needs_build(recipe.name): raise CommandError( _("Recipe %s is not built yet" % recipe.name)) for recipe in ordered_recipes: # call step function stepfunc = None try: stepfunc = getattr(recipe, 'check') except: m.message('%s has no check step, skipped' % recipe.name) if stepfunc: try: m.message('Running checks for recipe %s' % recipe.name) stepfunc() except Exception as ex: failed.append(recipe.name) m.warning(_("%s checks failed: %s") % (recipe.name, ex)) if failed: raise CommandError( _("Error running %s checks on:\n " + "\n ".join(failed)) % p_name)
def list_gstreamer_plugins_by_category(config): cookbook = CookBook(config) # For plugins named differently replacements = {'decodebin2': 'uridecodebin', 'playbin': 'playback', 'encodebin': 'encoding', 'souphttpsrc': 'soup', 'siren': 'gstsiren', 'sdpelem': 'sdp', 'rtpmanager': 'gstrtpmanager', 'scaletempoplugin' : 'scaletempo', 'mpegdemux': 'mpegdemux2', 'rmdemux': 'realmedia'} plugins = defaultdict(list) for r in ['gstreamer', 'gst-plugins-base', 'gst-plugins-good', 'gst-plugins-bad', 'gst-plugins-ugly', 'gst-ffmpeg', 'gst-rtsp-server']: r = cookbook.get_recipe(r) for attr_name in dir(r): if attr_name.startswith('files_plugins_'): cat_name = attr_name[len('files_plugins_'):] plugins_list = getattr(r, attr_name) elif attr_name.startswith('platform_files_plugins_'): cat_name = attr_name[len('platform_files_plugins_'):] plugins_dict = getattr(r, attr_name) plugins_list = plugins_dict.get(config.target_platform, []) else: continue for e in plugins_list: if not e.startswith('lib/gstreamer-'): continue plugins[cat_name].append(e[25:-8]) return plugins, replacements
def list_gstreamer_1_0_plugins_by_category(config): cookbook = CookBook(config) plugins = defaultdict(list) for r in ['gstreamer-1.0', 'gst-plugins-base-1.0', 'gst-plugins-good-1.0', 'gst-plugins-bad-1.0', 'gst-plugins-ugly-1.0', 'gst-libav-1.0', 'gst-editing-services-1.0', 'gst-rtsp-server-1.0']: r = cookbook.get_recipe(r) for attr_name in dir(r): if attr_name.startswith('files_plugins_'): cat_name = attr_name[len('files_plugins_'):] plugins_list = getattr(r, attr_name) elif attr_name.startswith('platform_files_plugins_'): cat_name = attr_name[len('platform_files_plugins_'):] plugins_dict = getattr(r, attr_name) plugins_list = plugins_dict.get(config.target_platform, []) else: continue for e in plugins_list: if not e.startswith('lib/gstreamer-'): continue c = e.split('/') if len(c) != 3: continue e = c[2] # we only care about files with the replaceable %(mext)s extension if not e.endswith ('%(mext)s'): continue if e.startswith('libgst'): e = e[6:-8] else: e = e[3:-8] plugins[cat_name].append(e) return plugins
def run(self, config, args): cookbook = CookBook(config) recipe_name = args.recipe[0] all_deps = args.all if all_deps: recipes = cookbook.list_recipe_deps(recipe_name) else: recipes = [cookbook.get_recipe(x) for x in cookbook.get_recipe(recipe_name).list_deps()] if len(recipes) == 0: m.message(_('%s has 0 dependencies') % recipe_name) return for recipe in recipes: # Don't print the recipe we asked for if recipe.name == recipe_name: continue m.message(recipe.name)
def run(self, config, args): name = args.name[0] version = args.version[0] filename = os.path.join(config.recipes_dir, '%s.recipe' % name) if not args.force and os.path.exists(filename): m.warning( _("Recipe '%s' (%s) already exists, " "use -f to replace" % (name, filename))) return template_args = {} template = RECEIPT_TPL template_args['name'] = name template_args['version'] = version if args.licenses: licenses = args.licenses.split(',') self.validate_licenses(licenses) template += LICENSES_TPL template_args['licenses'] = ', '.join( ['License.' + self.supported_licenses[l] \ for l in licenses]) if args.commit: template += COMMIT_TPL template_args['commit'] = args.commit if args.origin: template += ORIGIN_TPL template_args['origin'] = args.origin if args.deps: template += DEPS_TPL deps = args.deps.split(',') cookbook = CookBook(config) for dname in deps: try: recipe = cookbook.get_recipe(dname) except RecipeNotFoundError as ex: raise UsageError( _("Error creating recipe: " "dependant recipe %s does not exist") % dname) template_args['deps'] = deps try: f = open(filename, 'w') f.write(template % template_args) f.close() m.action( _("Recipe '%s' successfully created in %s") % (name, filename)) except IOError as ex: raise FatalError(_("Error creating recipe: %s") % ex)
def run(self, config, args): cookbook = CookBook(config) recipe_name = args.recipe[0] all_deps = args.all if all_deps: recipes = cookbook.list_recipe_deps(recipe_name) else: recipes = [ cookbook.get_recipe(x) for x in cookbook.get_recipe(recipe_name).list_deps() ] if len(recipes) == 0: m.message(_('%s has 0 dependencies') % recipe_name) return for recipe in recipes: # Don't print the recipe we asked for if recipe.name == recipe_name: continue m.message(recipe.name)
def run(self, config, args): name = args.name[0] version = args.version[0] filename = os.path.join(config.recipes_dir, '%s.recipe' % name) if not args.force and os.path.exists(filename): m.warning(_("Recipe '%s' (%s) already exists, " "use -f to replace" % (name, filename))) return template_args = {} template = RECEIPT_TPL template_args['name'] = name template_args['version'] = version if args.licenses: licenses = args.licenses.split(',') self.validate_licenses(licenses) template += LICENSES_TPL template_args['licenses'] = ', '.join( ['License.' + self.supported_licenses[l] \ for l in licenses]) if args.commit: template += COMMIT_TPL template_args['commit'] = args.commit if args.origin: template += ORIGIN_TPL template_args['origin'] = args.origin if args.deps: template += DEPS_TPL deps = args.deps.split(',') cookbook = CookBook(config) for dname in deps: try: recipe = cookbook.get_recipe(dname) except RecipeNotFoundError as ex: raise UsageError(_("Error creating recipe: " "dependant recipe %s does not exist") % dname) template_args['deps'] = deps try: f = open(filename, 'w') f.write(template % template_args) f.close() m.action(_("Recipe '%s' successfully created in %s") % (name, filename)) except IOError as ex: raise FatalError(_("Error creating recipe: %s") % ex)
def list_gstreamer_1_0_plugins_by_category(config): cookbook = CookBook(config) # For plugins named differently replacements = { 'decodebin': 'playback', 'playbin': 'playback', 'uridecodebin': 'playback', 'sdpelem': 'sdp', 'encodebin': 'encoding', 'souphttpsrc': 'soup', 'siren': 'gstsiren', 'scaletempoplugin': 'scaletempo', 'rmdemux': 'realmedia', 'camerabin2': 'camerabin' } plugins = defaultdict(list) for r in [ 'gstreamer-1.0', 'gst-plugins-base-1.0', 'gst-plugins-good-1.0', 'gst-plugins-bad-1.0', 'gst-plugins-ugly-1.0', 'gst-libav-1.0', 'gst-editing-services-1.0', 'gst-rtsp-server-1.0' ]: r = cookbook.get_recipe(r) for attr_name in dir(r): if attr_name.startswith('files_plugins_'): cat_name = attr_name[len('files_plugins_'):] plugins_list = getattr(r, attr_name) elif attr_name.startswith('platform_files_plugins_'): cat_name = attr_name[len('platform_files_plugins_'):] plugins_dict = getattr(r, attr_name) plugins_list = plugins_dict.get(config.target_platform, []) else: continue for e in plugins_list: if not e.startswith('lib/gstreamer-'): continue c = e.split('/') if len(c) != 3: continue e = c[2] if e.startswith('libgst'): e = e[6:-8] else: e = e[3:-8] plugins[cat_name].append(e) return plugins, replacements
def run(self, config, args): cookbook = CookBook(config) recipe_name = args.recipe[0] recipe = cookbook.get_recipe(recipe_name) # call step function stepfunc = None try: stepfunc = getattr(recipe, "clean") except: print "%s has no clean step, skipped" % recipe.name if stepfunc: try: stepfunc() except FatalError, e: raise e except Exception, ex: raise FatalError(_("Error running %s checks: %s") % (recipe.name, ex))
def run(self, config, args): cookbook = CookBook(config) recipe_name = args.recipe[0] recipe = cookbook.get_recipe(recipe_name) # call step function stepfunc = None try: stepfunc = getattr(recipe, 'clean') except: print('%s has no clean step, skipped' % recipe.name) if stepfunc: try: stepfunc() except FatalError as e: raise e except Exception as ex: raise FatalError( _("Error running %s checks: %s") % (recipe.name, ex))
def _get(self): tools = Build_Tools(self.config) store = PackagesStore(self.config) cookbook = CookBook(self.config) names = tools.BUILD_TOOLS names += tools.PLAT_BUILD_TOOLS.get(self.config.platform, []) recipes ={} path = os.path.join(self.config.packages_dir,'custom.py') d={} parse_file(path,d ) version = d['GStreamer'].version for name in names: recipes[name] = cookbook.get_recipe(name).version pkgname ='build-tools' tarball = '%s-%s-%s-%s'%( pkgname, self.config.platform, self.config.arch, version ) return { 'name':pkgname, 'version': version, 'prefix':self.config.build_tools_prefix, 'deps':[], 'platform':self.config.platform, 'arch':self.config.arch, 'tarball':{ 'runtime':{ 'filename':tarball +'.tar.bz2'} }, 'recipes': recipes }
def list_gstreamer_1_0_plugins_by_category(config): cookbook = CookBook(config) # For plugins named differently replacements = {'decodebin': 'playback', 'playbin': 'playback', 'uridecodebin': 'playback', 'sdpelem': 'sdp', 'encodebin': 'encoding', 'souphttpsrc': 'soup', 'siren': 'gstsiren', 'scaletempoplugin' : 'scaletempo', 'rmdemux': 'realmedia', 'camerabin2': 'camerabin'} plugins = defaultdict(list) for r in ['gstreamer-1.0', 'gst-plugins-base-1.0', 'gst-plugins-good-1.0', 'gst-plugins-bad-1.0', 'gst-plugins-ugly-1.0', 'gst-libav-1.0', 'gst-editing-services-1.0', 'gst-rtsp-server-1.0', 'gst-omx', 'gst-rpicamsrc']: r = cookbook.get_recipe(r) for attr_name in dir(r): if attr_name.startswith('files_plugins_'): cat_name = attr_name[len('files_plugins_'):] plugins_list = getattr(r, attr_name) elif attr_name.startswith('platform_files_plugins_'): cat_name = attr_name[len('platform_files_plugins_'):] plugins_dict = getattr(r, attr_name) plugins_list = plugins_dict.get(config.target_platform, []) else: continue for e in plugins_list: if not e.startswith('lib/gstreamer-'): continue c = e.split('/') if len(c) != 3: continue e = c[2] if e.startswith('libgst'): e = e[6:-8] else: e = e[3:-8] plugins[cat_name].append(e) return plugins, replacements
class PackageTest(unittest.TestCase): def setUp(self): self.config = Config() self.config.cache_file = '/dev/null' self.cookbook = CookBook(self.config, False) def testSetGetConfig(self): self.assertEqual(self.config, self.cookbook.get_config()) self.cookbook.set_config(None) self.assertIsNone(self.cookbook._config) def testCacheMissing(self): status = {'test': 'test'} self.cookbook.set_status(status) self.cookbook._restore_cache() self.assertEqual(self.cookbook.status, {}) def testSaveCache(self): tmp = tempfile.NamedTemporaryFile() status = {'test': 'test'} self.cookbook.set_status(status) self.cookbook.get_config().cache_file = tmp.name self.cookbook.save() with open(self.cookbook._cache_file(self.config), 'rb') as f: loaded_status = pickle.load(f) self.assertEqual(status, loaded_status) def testLoad(self): tmp = tempfile.NamedTemporaryFile() status = {'test': 'test'} self.cookbook.get_config().cache_file = tmp.name with open(tmp.name, 'wb') as f: pickle.dump(status, f) self.cookbook._restore_cache() self.assertEqual(status, self.cookbook.status) def testAddGetRecipe(self): recipe = Recipe1(self.config) self.assertRaises(RecipeNotFoundError, self.cookbook.get_recipe, recipe.name) self.cookbook.add_recipe(recipe) self.assertEqual(recipe, self.cookbook.recipes[recipe.name]) self.assertEqual(recipe, self.cookbook.get_recipe(recipe.name)) self.assertEqual(self.cookbook.get_recipes_list(), [recipe]) def testGetRecipesStatus(self): recipe = Recipe1(self.config) self.cookbook._restore_cache() self.assertEqual(self.cookbook.status, {}) self.cookbook.add_recipe(recipe) self.assertEqual(len(self.cookbook.status), 0) status = self.cookbook._recipe_status(recipe.name) self.assertEqual(len(self.cookbook.status), 1) self.assertEqual(status.steps, []) status.steps.append('1') status = self.cookbook._recipe_status(recipe.name) self.assertEqual(len(self.cookbook.status), 1) self.assertEqual(status.steps[0], '1') def testUpdateStatus(self): recipe = Recipe1(self.config) self.cookbook.add_recipe(recipe) self.cookbook._restore_cache() self.cookbook.update_step_status(recipe.name, 'fetch') status = self.cookbook._recipe_status(recipe.name) self.assertEqual(status.steps, ['fetch']) self.cookbook.update_step_status(recipe.name, 'build') status = self.cookbook._recipe_status(recipe.name) self.assertEqual(status.steps, ['fetch', 'build']) self.cookbook.update_step_status(recipe.name, 'install') status = self.cookbook._recipe_status(recipe.name) self.assertEqual(status.steps, ['fetch', 'build', 'install']) for step in ['fetch', 'build', 'install']: self.assertTrue(self.cookbook.step_done(recipe.name, step)) def testBuildStatus(self): recipe = Recipe1(self.config) self.cookbook.add_recipe(recipe) self.cookbook._restore_cache() self.cookbook.update_build_status(recipe.name, '1.0') self.assertTrue(self.cookbook.status[recipe.name].needs_build) self.assertEqual(self.cookbook.status[recipe.name].built_version, '1.0') self.cookbook.update_build_status(recipe.name, None) self.assertFalse(self.cookbook.status[recipe.name].needs_build) self.assertEqual(self.cookbook.status[recipe.name].built_version, None) def testResetRecipeStatus(self): recipe = Recipe1(self.config) self.cookbook.add_recipe(recipe) self.cookbook._restore_cache() self.cookbook.reset_recipe_status(recipe.name) status = self.cookbook._recipe_status(recipe.name) self.assertEqual(status.steps, []) self.assertTrue(self.cookbook.status[recipe.name].needs_build)
class Package(object): def __init__(self,config ): self.config = config self.store = PackagesStore(config) self.cookbook = CookBook(config) self.packages_ = None def _recipes(self,package): ''' return the recipes (name:version) dict included in the package (not include in deps packages) ''' all = package.recipes_dependencies() rdeps=[] for pkg in self.store.get_package_deps( package.name): rdeps.extend( pkg.recipes_dependencies()) rnames = list(set(all).difference(set(rdeps))) recipes ={} for name in rnames: recipes[name] = self.cookbook.get_recipe(name).version return recipes def get_recipes(self,package): ''' return the recipes (name:version) dict included in the package (not include in deps packages) ''' if isinstance (package,SDKPackage): recipes={} for p in self.store.get_package_deps(package): recipes.update( self._recipes( p) ) return recipes return self._recipes(package) def get_packages_deps(self,package): ''' return the packages of the SDK/package dependent. ''' dependencies = [] if isinstance (package,SDKPackage): if hasattr(package, 'dependencies'): dependencies = package.dependencies return [] else: dependencies = [p.name for p in self.store.get_package_deps(package.name, False)] deps = {} for name in dependencies: version = self.store.get_package(name).version deps[name] = version return deps def _pkg(self,package): t = DistTarball(self.config,package,self.store) tarball={} for ptype in [PackageType.DEVEL,PackageType.RUNTIME]: TNAME={PackageType.DEVEL:'devel',PackageType.RUNTIME:'runtime'} tarball[TNAME[ptype]]={ 'filename':t._get_name(ptype) } profile = { 'name':package.name, 'version':package.version, 'platform':self.config.target_platform, 'arch':self.config.target_arch, 'recipes': self.get_recipes(package), 'dependencies': self.get_packages_deps(package), #'deps': [p.name for p in self.store.get_package_deps(package.name, True)], #'direct.deps': [p.name for p in self.store.get_package_deps(package.name, False)], 'tarball': tarball } if self.config.build_type == 'debug': profile['debug'] = True return profile def get(self,name): if self.packages_ is None: self.packages() return self.packages_[name] def packages(self): if self.packages_ is None: self.packages_ = {} for pkg in self.store.get_packages_list(): #if isinstance (pkg,SDKPackage): # continue self.packages_[pkg.name] = self._pkg( pkg ) return self.packages_
class Graph(Command): doc = N_('Create a graph of dependencies using dot from graphviz') name = 'graph' def __init__(self): Command.__init__(self, [ ArgparseArgument( 'name', nargs=1, help=_('name of the recipe or package to generate deps from')), ArgparseArgument('-r', '--recipe', action='store_true', help=_('generate deps for the given recipe')), ArgparseArgument('-p', '--package', action='store_true', help=_('generate deps for the given package')), ArgparseArgument( '-pr', '--package-recipes', action='store_true', help=_('generate recipe deps for the given package')), ArgparseArgument('-o', '--output', nargs=1, help=_('output file for the SVG graph')), ]) def run(self, config, args): if args.recipe + args.package + args.package_recipes == 0: m.error( 'Error: You need to specify either recipe, package or package-recipes ' 'mode to generate the dependency graph') return if args.recipe + args.package + args.package_recipes > 1: m.error( 'Error: You can only specify recipe, package or package-recipes but not more than one' ) return if not shutil.which('dot'): m.error( 'Error: dot command not found. Please install graphviz it using ' 'your package manager. e.g. apt/dnf/brew install graphviz') return label = '' if args.recipe: self.graph_type = GraphType.RECIPE label = 'recipe' elif args.package: self.graph_type = GraphType.PACKAGE label = 'package' elif args.package_recipes: self.graph_type = GraphType.PACKAGE_RECIPES label = 'package\'s recipes' if self.graph_type == GraphType.RECIPE or self.graph_type == GraphType.PACKAGE_RECIPES: self.cookbook = CookBook(config) if self.graph_type == GraphType.PACKAGE or self.graph_type == GraphType.PACKAGE_RECIPES: self.package_store = PackagesStore(config) name = args.name[0] output = args.output[0] if args.output else name + '.svg' tmp = tempfile.NamedTemporaryFile() dot = 'digraph {{\n\tlabel="{} {}";\n{}}}\n'.format( name, label, self._dot_gen(name, self.graph_type)) with open(tmp.name, 'w') as f: f.write(dot) shell.new_call(['dot', '-Tsvg', tmp.name, '-o', output]) m.message("Dependency graph for %s generated at %s" % (name, output)) def _dot_gen(self, name, graph_type, already_parsed=[]): already_parsed.append(name) if graph_type == GraphType.RECIPE: deps = self.cookbook.get_recipe(name).list_deps() elif graph_type == GraphType.PACKAGE: deps = [p.name for p in self.package_store.get_package_deps(name)] elif graph_type == GraphType.PACKAGE_RECIPES: deps = self.package_store.get_package(name).recipes_dependencies() graph_type = GraphType.RECIPE line = '' for dep in deps: line += '\t"{}" -> "{}";\n'.format(name, dep) if dep not in already_parsed: line += self._dot_gen(dep, graph_type, already_parsed) return line
class PackageTest(unittest.TestCase): def setUp(self): self.config = Config() self.config.cache_file = '/dev/null' self.cookbook = CookBook(self.config, False) def testSetGetConfig(self): self.assertEquals(self.config, self.cookbook.get_config()) self.cookbook.set_config(None) self.assertIsNone(self.cookbook._config) def testCacheMissing(self): status = {'test': 'test'} self.cookbook.set_status(status) self.cookbook._restore_cache() self.assertEquals(self.cookbook.status, {}) def testSaveCache(self): tmp = tempfile.NamedTemporaryFile() status = {'test': 'test'} self.cookbook.set_status(status) self.cookbook.get_config().cache_file = tmp.name self.cookbook.save() with open(self.cookbook._cache_file(self.config), 'rb') as f: loaded_status = pickle.load(f) self.assertEquals(status, loaded_status) def testLoad(self): tmp = tempfile.NamedTemporaryFile() status = {'test': 'test'} self.cookbook.get_config().cache_file = tmp.name with open(tmp.name, 'wb') as f: pickle.dump(status, f) self.cookbook._restore_cache() self.assertEquals(status, self.cookbook.status) def testAddGetRecipe(self): recipe = Recipe1(self.config) self.failUnlessRaises(RecipeNotFoundError, self.cookbook.get_recipe, recipe.name) self.cookbook.add_recipe(recipe) self.assertEquals(recipe, self.cookbook.recipes[recipe.name]) self.assertEquals(recipe, self.cookbook.get_recipe(recipe.name)) self.assertEquals(self.cookbook.get_recipes_list(), [recipe]) def testGetRecipesStatus(self): recipe = Recipe1(self.config) self.cookbook._restore_cache() self.assertEquals(self.cookbook.status, {}) self.cookbook.add_recipe(recipe) self.assertEquals(len(self.cookbook.status), 0) status = self.cookbook._recipe_status(recipe.name) self.assertEquals(len(self.cookbook.status), 1) self.assertEquals(status.steps, []) status.steps.append('1') status = self.cookbook._recipe_status(recipe.name) self.assertEquals(len(self.cookbook.status), 1) self.assertEquals(status.steps[0], '1') def testUpdateStatus(self): recipe = Recipe1(self.config) self.cookbook.add_recipe(recipe) self.cookbook._restore_cache() self.cookbook.update_step_status(recipe.name, 'fetch') status = self.cookbook._recipe_status(recipe.name) self.assertEquals(status.steps, ['fetch']) self.cookbook.update_step_status(recipe.name, 'build') status = self.cookbook._recipe_status(recipe.name) self.assertEquals(status.steps, ['fetch', 'build']) self.cookbook.update_step_status(recipe.name, 'install') status = self.cookbook._recipe_status(recipe.name) self.assertEquals(status.steps, ['fetch', 'build', 'install']) for step in ['fetch', 'build', 'install']: self.assertTrue(self.cookbook.step_done(recipe.name, step)) def testBuildStatus(self): recipe = Recipe1(self.config) self.cookbook.add_recipe(recipe) self.cookbook._restore_cache() self.cookbook.update_build_status(recipe.name, True) self.assertTrue(self.cookbook.status[recipe.name].needs_build) self.cookbook.update_build_status(recipe.name, False) self.assertFalse(self.cookbook.status[recipe.name].needs_build) def testResetRecipeStatus(self): recipe = Recipe1(self.config) self.cookbook.add_recipe(recipe) self.cookbook._restore_cache() self.cookbook.reset_recipe_status(recipe.name) status = self.cookbook._recipe_status(recipe.name) self.assertEquals(status.steps, []) self.assertTrue(self.cookbook.status[recipe.name].needs_build)