def _add_repo(self, config_root, portdir_overlay): self.repo_conf = portage.repository.config self.repo_name = self.repo_conf.RepoConfig._read_valid_repo_name( portdir_overlay)[0] self.layout_conf_data = self.repo_conf.parse_layout_conf( portdir_overlay)[0] if self.layout_conf_data['repo-name']: self.repo_name = self.layout_conf_data['repo-name'] tmp_conf_file = io.StringIO( textwrap.dedent(""" [%s] location = %s """) % (self.repo_name, portdir_overlay)) # Ensure that the repository corresponding to $PWD overrides a # repository of the same name referenced by the existing PORTDIR # or PORTDIR_OVERLAY settings. self.repoman_settings['PORTDIR_OVERLAY'] = "%s %s" % ( self.repoman_settings.get( 'PORTDIR_OVERLAY', ''), portage._shell_quote(portdir_overlay)) self.repositories = self.repo_conf.load_repository_config( self.repoman_settings, extra_files=[tmp_conf_file]) # We have to call the config constructor again so that attributes # dependent on config.repositories are initialized correctly. self.repoman_settings = portage.config(config_root=config_root, local_config=False, repositories=self.repositories)
def _repoman_init(argv): config_root = os.environ.get("PORTAGE_CONFIGROOT") repoman_settings = portage.config(config_root=config_root, local_config=False) repoman_settings.valid_versions = VALID_VERSIONS if repoman_settings.get("NOCOLOR", "").lower() in ("yes", "true") or \ repoman_settings.get('TERM') == 'dumb' or \ not sys.stdout.isatty(): nocolor() options, arguments = parse_args( argv, repoman_settings.get("REPOMAN_DEFAULT_OPTS", "")) if options.version: print("Repoman", VERSION, "(portage-%s)" % portage.VERSION) return _repoman_main_vars(None, 0, None, None, None, None, None) logger = logging.getLogger() if options.verbosity > 0: logger.setLevel(LOGLEVEL - 10 * options.verbosity) else: logger.setLevel(LOGLEVEL) # Set this to False when an extraordinary issue (generally # something other than a QA issue) makes it impossible to # commit (like if Manifest generation fails). can_force = ExtendedFuture(True) repo_settings, vcs_settings, scanner, qadata = _create_scanner( options, can_force, config_root, repoman_settings) return _repoman_main_vars(can_force, None, options, qadata, repo_settings, scanner, vcs_settings)
def _add_repo(self, config_root, portdir_overlay): self.repo_conf = portage.repository.config self.repo_name = self.repo_conf._read_repo_name(portdir_overlay, quiet=True) tmp_conf_file = io.StringIO(textwrap.dedent(""" [%s] location = %s """) % (self.repo_name, portdir_overlay)) # Ensure that the repository corresponding to $PWD overrides a # repository of the same name referenced by the existing PORTDIR # or PORTDIR_OVERLAY settings. self.repoman_settings['PORTDIR_OVERLAY'] = "%s %s" % ( self.repoman_settings.get('PORTDIR_OVERLAY', ''), portage._shell_quote(portdir_overlay)) self.repositories = self.repo_conf.load_repository_config( self.repoman_settings, extra_files=[tmp_conf_file]) # We have to call the config constructor again so that attributes # dependent on config.repositories are initialized correctly. self.repoman_settings = portage.config( config_root=config_root, local_config=False, repositories=self.repositories)
def repoman_main(argv): config_root = os.environ.get("PORTAGE_CONFIGROOT") repoman_settings = portage.config(config_root=config_root, local_config=False) repoman_settings.valid_versions = VALID_VERSIONS if repoman_settings.get("NOCOLOR", "").lower() in ("yes", "true") or \ repoman_settings.get('TERM') == 'dumb' or \ not sys.stdout.isatty(): nocolor() options, arguments = parse_args( sys.argv, repoman_settings.get("REPOMAN_DEFAULT_OPTS", "")) if options.version: print("Repoman", VERSION, "(portage-%s)" % portage.VERSION) sys.exit(0) logger = logging.getLogger() if options.verbosity > 0: logger.setLevel(LOGLEVEL - 10 * options.verbosity) else: logger.setLevel(LOGLEVEL) # Set this to False when an extraordinary issue (generally # something other than a QA issue) makes it impossible to # commit (like if Manifest generation fails). can_force = ExtendedFuture(True) portdir, portdir_overlay, mydir = utilities.FindPortdir(repoman_settings) if portdir is None: sys.exit(1) myreporoot = os.path.basename(portdir_overlay) myreporoot += mydir[len(portdir_overlay):] # avoid a circular parameter repo_settings vcs_settings = VCSSettings(options, repoman_settings) qadata = QAData() logging.debug("repoman_main: RepoSettings init") repo_settings = RepoSettings(config_root, portdir, portdir_overlay, repoman_settings, vcs_settings, options, qadata) repoman_settings = repo_settings.repoman_settings repoman_settings.valid_versions = VALID_VERSIONS # Now set repo_settings vcs_settings.repo_settings = repo_settings # set QATracker qacats, qawarnings vcs_settings.qatracker.qacats = repo_settings.qadata.qacats vcs_settings.qatracker.qawarnings = repo_settings.qadata.qawarnings logging.debug("repoman_main: vcs_settings done") logging.debug("repoman_main: qadata: %s", repo_settings.qadata) if 'digest' in repoman_settings.features and options.digest != 'n': options.digest = 'y' logging.debug("vcs: %s" % (vcs_settings.vcs, )) logging.debug("repo config: %s" % (repo_settings.repo_config, )) logging.debug("options: %s" % (options, )) # It's confusing if these warnings are displayed without the user # being told which profile they come from, so disable them. env = os.environ.copy() env['FEATURES'] = env.get('FEATURES', '') + ' -unknown-features-warn' # Perform the main checks scanner = Scanner(repo_settings, myreporoot, config_root, options, vcs_settings, mydir, env) scanner.scan_pkgs(can_force) if options.if_modified == "y" and len(scanner.effective_scanlist) < 1: logging.warning( "--if-modified is enabled, but no modified packages were found!") result = { # fail will be true if we have failed in at least one non-warning category 'fail': 0, # warn will be true if we tripped any warnings 'warn': 0, # full will be true if we should print a "repoman full" informational message 'full': options.mode != 'full', } for x in qadata.qacats: if x not in vcs_settings.qatracker.fails: continue result['warn'] = 1 if x not in qadata.qawarnings: result['fail'] = 1 if result['fail'] or \ (result['warn'] and not (options.quiet or options.mode == "scan")): result['full'] = 0 commitmessage = None if options.commitmsg: commitmessage = options.commitmsg elif options.commitmsgfile: # we don't need the actual text of the commit message here # the filename will do for the next code block commitmessage = options.commitmsgfile # Save QA output so that it can be conveniently displayed # in $EDITOR while the user creates a commit message. # Otherwise, the user would not be able to see this output # once the editor has taken over the screen. qa_output = io.StringIO() style_file = ConsoleStyleFile(sys.stdout) if options.mode == 'commit' and \ (not commitmessage or not commitmessage.strip()): style_file.write_listener = qa_output console_writer = StyleWriter(file=style_file, maxcol=9999) console_writer.style_listener = style_file.new_styles f = formatter.AbstractFormatter(console_writer) format_outputs = { 'column': format_qa_output_column, 'default': format_qa_output } format_output = format_outputs.get(options.output_style, format_outputs['default']) format_output(f, vcs_settings.qatracker.fails, result['full'], result['fail'], options, qadata.qawarnings) style_file.flush() del console_writer, f, style_file # early out for manifest generation if options.mode == "manifest": return 1 if result['fail'] else 0 qa_output = qa_output.getvalue() qa_output = qa_output.splitlines(True) # output the results actions = Actions(repo_settings, options, scanner, vcs_settings) if actions.inform(can_force.get(), result): # perform any other actions actions.perform(qa_output) sys.exit(0)
def check(self, **kwargs): '''Perform profile dependant dependancy checks @param arches: @param pkg: Package in which we check (object). @param ebuild: Ebuild which we check (object). @param baddepsyntax: boolean @param unknown_pkgs: set of tuples (type, atom.unevaluated_atom) @returns: dictionary ''' ebuild = kwargs.get('ebuild').get() pkg = kwargs.get('pkg').get() unknown_pkgs, baddepsyntax = _depend_checks(ebuild, pkg, self.portdb, self.qatracker, self.repo_metadata) relevant_profiles = [] for keyword, arch, groups in _gen_arches(ebuild, self.options, self.repo_settings, self.profiles): if arch not in self.profiles: # A missing profile will create an error further down # during the KEYWORDS verification. continue if self.include_arches is not None: if arch not in self.include_arches: continue relevant_profiles.extend( (keyword, groups, prof) for prof in self.profiles[arch]) relevant_profiles.sort(key=sort_key) for keyword, groups, prof in relevant_profiles: is_stable_profile = prof.status == "stable" is_dev_profile = prof.status == "dev" and \ self.options.include_dev is_exp_profile = prof.status == "exp" and \ self.options.include_exp_profiles == 'y' if not (is_stable_profile or is_dev_profile or is_exp_profile): continue dep_settings = self.caches['arch'].get(prof.sub_path) if dep_settings is None: dep_settings = portage.config( config_profile_path=prof.abs_path, config_incrementals=self.repoman_incrementals, config_root=self.repo_settings.config_root, local_config=False, _unmatched_removal=self.options.unmatched_removal, env=self.env, repositories=self.repo_settings.repoman_settings. repositories) dep_settings.categories = self.repo_settings.repoman_settings.categories if self.options.without_mask: dep_settings._mask_manager_obj = \ copy.deepcopy(dep_settings._mask_manager) dep_settings._mask_manager._pmaskdict.clear() self.caches['arch'][prof.sub_path] = dep_settings xmatch_cache_key = (prof.sub_path, tuple(groups)) xcache = self.caches['arch_xmatch'].get(xmatch_cache_key) if xcache is None: self.portdb.melt() self.portdb.freeze() xcache = self.portdb.xcache xcache.update(self.caches['shared_xmatch']) self.caches['arch_xmatch'][xmatch_cache_key] = xcache self.repo_settings.trees[ self.repo_settings.root]["porttree"].settings = dep_settings self.portdb.settings = dep_settings self.portdb.xcache = xcache dep_settings["ACCEPT_KEYWORDS"] = " ".join(groups) # just in case, prevent config.reset() from nuking these. dep_settings.backup_changes("ACCEPT_KEYWORDS") # This attribute is used in dbapi._match_use() to apply # use.stable.{mask,force} settings based on the stable # status of the parent package. This is required in order # for USE deps of unstable packages to be resolved correctly, # since otherwise use.stable.{mask,force} settings of # dependencies may conflict (see bug #456342). dep_settings._parent_stable = dep_settings._isStable(pkg) # Handle package.use*.{force,mask) calculation, for use # in dep_check. dep_settings.useforce = dep_settings._use_manager.getUseForce( pkg, stable=dep_settings._parent_stable) dep_settings.usemask = dep_settings._use_manager.getUseMask( pkg, stable=dep_settings._parent_stable) if not baddepsyntax: ismasked = not ebuild.archs or \ pkg.cpv not in self.portdb.xmatch("match-visible", Atom("%s::%s" % (pkg.cp, self.repo_settings.repo_config.name))) if ismasked: if not self.have['pmasked']: self.have['pmasked'] = bool( dep_settings._getMaskAtom(pkg.cpv, ebuild.metadata)) if self.options.ignore_masked: continue # we are testing deps for a masked package; give it some lee-way suffix = "masked" matchmode = "minimum-all-ignore-profile" else: suffix = "" matchmode = "minimum-visible" if not self.have['dev_keywords']: self.have['dev_keywords'] = \ bool(self.dev_keywords.intersection(ebuild.keywords)) if prof.status == "dev": suffix = suffix + "indev" for mytype in Package._dep_keys: mykey = "dependency.bad" + suffix myvalue = ebuild.metadata[mytype] if not myvalue: continue success, atoms = portage.dep_check( myvalue, self.portdb, dep_settings, use="all", mode=matchmode, trees=self.repo_settings.trees) if success: if atoms: # Don't bother with dependency.unknown for # cases in which *DEPEND.bad is triggered. for atom in atoms: # dep_check returns all blockers and they # aren't counted for *DEPEND.bad, so we # ignore them here. if not atom.blocker: unknown_pkgs.discard( (mytype, atom.unevaluated_atom)) if not prof.sub_path: # old-style virtuals currently aren't # resolvable with empty profile, since # 'virtuals' mappings are unavailable # (it would be expensive to search # for PROVIDE in all ebuilds) atoms = [ atom for atom in atoms if not (atom.cp.startswith('virtual/') and not self.portdb.cp_list(atom.cp)) ] # we have some unsolvable deps # remove ! deps, which always show up as unsatisfiable all_atoms = [ str(atom.unevaluated_atom) for atom in atoms if not atom.blocker ] # if we emptied out our list, continue: if not all_atoms: continue # Filter out duplicates. We do this by hand (rather # than use a set) so the order is stable and better # matches the order that's in the ebuild itself. atoms = [] for atom in all_atoms: if atom not in atoms: atoms.append(atom) if self.options.output_style in ['column']: self.qatracker.add_error( mykey, "%s: %s: %s(%s) %s" % (ebuild.relative_path, mytype, keyword, prof, repr(atoms))) else: self.qatracker.add_error( mykey, "%s: %s: %s(%s)\n%s" % (ebuild.relative_path, mytype, keyword, prof, pformat(atoms, indent=6))) else: if self.options.output_style in ['column']: self.qatracker.add_error( mykey, "%s: %s: %s(%s) %s" % (ebuild.relative_path, mytype, keyword, prof, repr(atoms))) else: self.qatracker.add_error( mykey, "%s: %s: %s(%s)\n%s" % (ebuild.relative_path, mytype, keyword, prof, pformat(atoms, indent=6))) if not baddepsyntax and unknown_pkgs: type_map = {} for mytype, atom in unknown_pkgs: type_map.setdefault(mytype, set()).add(atom) for mytype, atoms in type_map.items(): self.qatracker.add_error( "dependency.unknown", "%s: %s: %s" % (ebuild.relative_path, mytype, ", ".join(sorted(atoms)))) return False
def repoman_main(argv): config_root = os.environ.get("PORTAGE_CONFIGROOT") repoman_settings = portage.config(config_root=config_root, local_config=False) repoman_settings.valid_versions = VALID_VERSIONS if repoman_settings.get("NOCOLOR", "").lower() in ("yes", "true") or \ repoman_settings.get('TERM') == 'dumb' or \ not sys.stdout.isatty(): nocolor() options, arguments = parse_args( sys.argv, repoman_settings.get("REPOMAN_DEFAULT_OPTS", "")) if options.version: print("Repoman", VERSION, "(portage-%s)" % portage.VERSION) sys.exit(0) logger = logging.getLogger() if options.verbosity > 0: logger.setLevel(LOGLEVEL - 10 * options.verbosity) else: logger.setLevel(LOGLEVEL) # Set this to False when an extraordinary issue (generally # something other than a QA issue) makes it impossible to # commit (like if Manifest generation fails). can_force = ExtendedFuture(True) portdir, portdir_overlay, mydir = utilities.FindPortdir(repoman_settings) if portdir is None: sys.exit(1) myreporoot = os.path.basename(portdir_overlay) myreporoot += mydir[len(portdir_overlay):] # avoid a circular parameter repo_settings vcs_settings = VCSSettings(options, repoman_settings) qadata = QAData() logging.debug("repoman_main: RepoSettings init") repo_settings = RepoSettings( config_root, portdir, portdir_overlay, repoman_settings, vcs_settings, options, qadata) repoman_settings = repo_settings.repoman_settings repoman_settings.valid_versions = VALID_VERSIONS # Now set repo_settings vcs_settings.repo_settings = repo_settings # set QATracker qacats, qawarnings vcs_settings.qatracker.qacats = repo_settings.qadata.qacats vcs_settings.qatracker.qawarnings = repo_settings.qadata.qawarnings logging.debug("repoman_main: vcs_settings done") logging.debug("repoman_main: qadata: %s", repo_settings.qadata) if 'digest' in repoman_settings.features and options.digest != 'n': options.digest = 'y' logging.debug("vcs: %s" % (vcs_settings.vcs,)) logging.debug("repo config: %s" % (repo_settings.repo_config,)) logging.debug("options: %s" % (options,)) # It's confusing if these warnings are displayed without the user # being told which profile they come from, so disable them. env = os.environ.copy() env['FEATURES'] = env.get('FEATURES', '') + ' -unknown-features-warn' # Perform the main checks scanner = Scanner(repo_settings, myreporoot, config_root, options, vcs_settings, mydir, env) scanner.scan_pkgs(can_force) if options.if_modified == "y" and len(scanner.effective_scanlist) < 1: logging.warning("--if-modified is enabled, but no modified packages were found!") result = { # fail will be true if we have failed in at least one non-warning category 'fail': 0, # warn will be true if we tripped any warnings 'warn': 0, # full will be true if we should print a "repoman full" informational message 'full': options.mode != 'full', } # early out for manifest generation if options.mode == "manifest": sys.exit(result['fail']) for x in qadata.qacats: if x not in vcs_settings.qatracker.fails: continue result['warn'] = 1 if x not in qadata.qawarnings: result['fail'] = 1 if result['fail'] or \ (result['warn'] and not (options.quiet or options.mode == "scan")): result['full'] = 0 commitmessage = None if options.commitmsg: commitmessage = options.commitmsg elif options.commitmsgfile: # we don't need the actual text of the commit message here # the filename will do for the next code block commitmessage = options.commitmsgfile # Save QA output so that it can be conveniently displayed # in $EDITOR while the user creates a commit message. # Otherwise, the user would not be able to see this output # once the editor has taken over the screen. qa_output = io.StringIO() style_file = ConsoleStyleFile(sys.stdout) if options.mode == 'commit' and \ (not commitmessage or not commitmessage.strip()): style_file.write_listener = qa_output console_writer = StyleWriter(file=style_file, maxcol=9999) console_writer.style_listener = style_file.new_styles f = formatter.AbstractFormatter(console_writer) format_outputs = { 'column': format_qa_output_column, 'default': format_qa_output } format_output = format_outputs.get( options.output_style, format_outputs['default']) format_output(f, vcs_settings.qatracker.fails, result['full'], result['fail'], options, qadata.qawarnings) style_file.flush() del console_writer, f, style_file qa_output = qa_output.getvalue() qa_output = qa_output.splitlines(True) # output the results actions = Actions(repo_settings, options, scanner, vcs_settings) if actions.inform(can_force.get(), result): # perform any other actions actions.perform(qa_output) sys.exit(0)
def _iter_tasks(self, loop, executor, ebuild, pkg): for keyword, groups, prof in ebuild.relevant_profiles: is_stable_profile = prof.status == "stable" is_dev_profile = prof.status == "dev" and \ self.options.include_dev is_exp_profile = prof.status == "exp" and \ self.options.include_exp_profiles == 'y' if not (is_stable_profile or is_dev_profile or is_exp_profile): continue dep_settings = self.caches['arch'].get(prof.sub_path) if dep_settings is None: dep_settings = portage.config( config_profile_path=prof.abs_path, config_incrementals=self.repoman_incrementals, config_root=self.repo_settings.config_root, local_config=False, _unmatched_removal=self.options.unmatched_removal, env=self.env, repositories=self.repo_settings.repoman_settings.repositories) if not prof.abs_path: self._populate_implicit_iuse(dep_settings, self.repo_settings.repo_config.eclass_db.porttrees) dep_settings.categories = self.repo_settings.repoman_settings.categories if self.options.without_mask: dep_settings._mask_manager_obj = \ copy.deepcopy(dep_settings._mask_manager) dep_settings._mask_manager._pmaskdict.clear() self.caches['arch'][prof.sub_path] = dep_settings xmatch_cache_key = (prof.sub_path, tuple(groups)) xcache = self.caches['arch_xmatch'].get(xmatch_cache_key) if xcache is None: self.portdb.melt() self.portdb.freeze() xcache = self.portdb.xcache xcache.update(self.caches['shared_xmatch']) self.caches['arch_xmatch'][xmatch_cache_key] = xcache self.repo_settings.trees[self.repo_settings.root]["porttree"].settings = dep_settings self.portdb.settings = dep_settings self.portdb.xcache = xcache dep_settings["ACCEPT_KEYWORDS"] = " ".join(groups) # just in case, prevent config.reset() from nuking these. dep_settings.backup_changes("ACCEPT_KEYWORDS") # This attribute is used in dbapi._match_use() to apply # use.stable.{mask,force} settings based on the stable # status of the parent package. This is required in order # for USE deps of unstable packages to be resolved correctly, # since otherwise use.stable.{mask,force} settings of # dependencies may conflict (see bug #456342). dep_settings._parent_stable = dep_settings._isStable(pkg) # Handle package.use*.{force,mask) calculation, for use # in dep_check. dep_settings.useforce = dep_settings._use_manager.getUseForce( pkg, stable=dep_settings._parent_stable) dep_settings.usemask = dep_settings._use_manager.getUseMask( pkg, stable=dep_settings._parent_stable) task = types.SimpleNamespace(ebuild=ebuild, prof=prof, keyword=keyword) target = functools.partial(self._task_subprocess, task, pkg, dep_settings) if self.options.jobs <= 1: yield (task, target()) else: task.future = asyncio.ensure_future(loop.run_in_executor(executor, target), loop=loop) yield self._task(task, loop=loop)
def check(self, **kwargs): '''Perform profile dependant dependency checks @param arches: @param pkg: Package in which we check (object). @param ebuild: Ebuild which we check (object). @param baddepsyntax: boolean @param unknown_pkgs: set of tuples (type, atom.unevaluated_atom) @returns: dictionary ''' ebuild = kwargs.get('ebuild').get() pkg = kwargs.get('pkg').get() unknown_pkgs, baddepsyntax = _depend_checks( ebuild, pkg, self.portdb, self.qatracker, self.repo_metadata, self.repo_settings.qadata) relevant_profiles = [] for keyword, arch, groups in _gen_arches(ebuild, self.options, self.repo_settings, self.profiles): if arch not in self.profiles: # A missing profile will create an error further down # during the KEYWORDS verification. continue if self.include_arches is not None: if arch not in self.include_arches: continue relevant_profiles.extend( (keyword, groups, prof) for prof in self.profiles[arch]) relevant_profiles.sort(key=sort_key) for keyword, groups, prof in relevant_profiles: is_stable_profile = prof.status == "stable" is_dev_profile = prof.status == "dev" and \ self.options.include_dev is_exp_profile = prof.status == "exp" and \ self.options.include_exp_profiles == 'y' if not (is_stable_profile or is_dev_profile or is_exp_profile): continue dep_settings = self.caches['arch'].get(prof.sub_path) if dep_settings is None: dep_settings = portage.config( config_profile_path=prof.abs_path, config_incrementals=self.repoman_incrementals, config_root=self.repo_settings.config_root, local_config=False, _unmatched_removal=self.options.unmatched_removal, env=self.env, repositories=self.repo_settings.repoman_settings.repositories) if not prof.abs_path: self._populate_implicit_iuse(dep_settings, self.repo_settings.repo_config.eclass_db.porttrees) dep_settings.categories = self.repo_settings.repoman_settings.categories if self.options.without_mask: dep_settings._mask_manager_obj = \ copy.deepcopy(dep_settings._mask_manager) dep_settings._mask_manager._pmaskdict.clear() self.caches['arch'][prof.sub_path] = dep_settings xmatch_cache_key = (prof.sub_path, tuple(groups)) xcache = self.caches['arch_xmatch'].get(xmatch_cache_key) if xcache is None: self.portdb.melt() self.portdb.freeze() xcache = self.portdb.xcache xcache.update(self.caches['shared_xmatch']) self.caches['arch_xmatch'][xmatch_cache_key] = xcache self.repo_settings.trees[self.repo_settings.root]["porttree"].settings = dep_settings self.portdb.settings = dep_settings self.portdb.xcache = xcache dep_settings["ACCEPT_KEYWORDS"] = " ".join(groups) # just in case, prevent config.reset() from nuking these. dep_settings.backup_changes("ACCEPT_KEYWORDS") # This attribute is used in dbapi._match_use() to apply # use.stable.{mask,force} settings based on the stable # status of the parent package. This is required in order # for USE deps of unstable packages to be resolved correctly, # since otherwise use.stable.{mask,force} settings of # dependencies may conflict (see bug #456342). dep_settings._parent_stable = dep_settings._isStable(pkg) # Handle package.use*.{force,mask) calculation, for use # in dep_check. dep_settings.useforce = dep_settings._use_manager.getUseForce( pkg, stable=dep_settings._parent_stable) dep_settings.usemask = dep_settings._use_manager.getUseMask( pkg, stable=dep_settings._parent_stable) if not baddepsyntax: ismasked = not ebuild.archs or \ pkg.cpv not in self.portdb.xmatch("match-visible", Atom("%s::%s" % (pkg.cp, self.repo_settings.repo_config.name))) if ismasked: if not self.have['pmasked']: self.have['pmasked'] = bool(dep_settings._getMaskAtom( pkg.cpv, ebuild.metadata)) if self.options.ignore_masked: continue # we are testing deps for a masked package; give it some lee-way suffix = "masked" matchmode = "minimum-all-ignore-profile" else: suffix = "" matchmode = "minimum-visible" if not self.have['dev_keywords']: self.have['dev_keywords'] = \ bool(self.dev_keywords.intersection(ebuild.keywords)) if prof.status == "dev": suffix = suffix + "indev" elif prof.status == "exp": suffix = suffix + "inexp" for mytype in Package._dep_keys: mykey = "dependency.bad" + suffix myvalue = ebuild.metadata[mytype] if not myvalue: continue success, atoms = portage.dep_check( myvalue, self.portdb, dep_settings, use="all", mode=matchmode, trees=self.repo_settings.trees) if success: if atoms: # Don't bother with dependency.unknown for # cases in which *DEPEND.bad is triggered. for atom in atoms: # dep_check returns all blockers and they # aren't counted for *DEPEND.bad, so we # ignore them here. if not atom.blocker: unknown_pkgs.discard( (mytype, atom.unevaluated_atom)) if not prof.sub_path: # old-style virtuals currently aren't # resolvable with empty profile, since # 'virtuals' mappings are unavailable # (it would be expensive to search # for PROVIDE in all ebuilds) atoms = [ atom for atom in atoms if not ( atom.cp.startswith('virtual/') and not self.portdb.cp_list(atom.cp))] # we have some unsolvable deps # remove ! deps, which always show up as unsatisfiable all_atoms = [ str(atom.unevaluated_atom) for atom in atoms if not atom.blocker] # if we emptied out our list, continue: if not all_atoms: continue # Filter out duplicates. We do this by hand (rather # than use a set) so the order is stable and better # matches the order that's in the ebuild itself. atoms = [] for atom in all_atoms: if atom not in atoms: atoms.append(atom) if self.options.output_style in ['column']: self.qatracker.add_error(mykey, "%s: %s: %s(%s) %s" % (ebuild.relative_path, mytype, keyword, prof, repr(atoms))) else: self.qatracker.add_error(mykey, "%s: %s: %s(%s)\n%s" % (ebuild.relative_path, mytype, keyword, prof, pformat(atoms, indent=6))) else: if self.options.output_style in ['column']: self.qatracker.add_error(mykey, "%s: %s: %s(%s) %s" % (ebuild.relative_path, mytype, keyword, prof, repr(atoms))) else: self.qatracker.add_error(mykey, "%s: %s: %s(%s)\n%s" % (ebuild.relative_path, mytype, keyword, prof, pformat(atoms, indent=6))) if not baddepsyntax and unknown_pkgs: type_map = {} for mytype, atom in unknown_pkgs: type_map.setdefault(mytype, set()).add(atom) for mytype, atoms in type_map.items(): self.qatracker.add_error( "dependency.unknown", "%s: %s: %s" % (ebuild.relative_path, mytype, ", ".join(sorted(atoms)))) return False