def sign_manifest(self, myupdates, myremoved, mymanifests): try: for x in sorted(vcs_files_to_cps( chain(myupdates, myremoved, mymanifests), self.scanner.repolevel, self.scanner.reposplit, self.scanner.categories)): self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x) manifest_path = os.path.join(self.repoman_settings["O"], "Manifest") if not need_signature(manifest_path): continue gpgsign(manifest_path, self.repoman_settings, self.options) except portage.exception.PortageException as e: portage.writemsg("!!! %s\n" % str(e)) portage.writemsg("!!! Disabled FEATURES='sign'\n") self.repo_settings.sign_manifests = False
def sign_manifest(self, myupdates, myremoved, mymanifests): try: for x in sorted( vcs_files_to_cps(chain(myupdates, myremoved, mymanifests), self.scanner.repolevel, self.scanner.reposplit, self.scanner.categories)): self.repoman_settings["O"] = os.path.join( self.repo_settings.repodir, x) manifest_path = os.path.join(self.repoman_settings["O"], "Manifest") if not need_signature(manifest_path): continue gpgsign(manifest_path, self.repoman_settings, self.options) except portage.exception.PortageException as e: portage.writemsg("!!! %s\n" % str(e)) portage.writemsg("!!! Disabled FEATURES='sign'\n") self.repo_settings.sign_manifests = False
def perform(self, qa_output): myunadded, mydeleted = self._vcs_unadded() myautoadd = self._vcs_autoadd(myunadded) self._vcs_deleted(mydeleted) changes = self.get_vcs_changed(mydeleted) mynew, mychanged, myremoved, no_expansion, expansion = changes # Manifests need to be regenerated after all other commits, so don't commit # them now even if they have changed. mymanifests = set() myupdates = set() for f in mychanged + mynew: if "Manifest" == os.path.basename(f): mymanifests.add(f) else: myupdates.add(f) myupdates.difference_update(myremoved) myupdates = list(myupdates) mymanifests = list(mymanifests) myheaders = [] commitmessage = self.options.commitmsg if self.options.commitmsgfile: try: f = io.open(_unicode_encode(self.options.commitmsgfile, encoding=_encodings['fs'], errors='strict'), mode='r', encoding=_encodings['content'], errors='replace') commitmessage = f.read() f.close() del f except (IOError, OSError) as e: if e.errno == errno.ENOENT: portage.writemsg("!!! File Not Found:" " --commitmsgfile='%s'\n" % self.options.commitmsgfile) else: raise if not commitmessage or not commitmessage.strip(): commitmessage = self.get_new_commit_message(qa_output) commitmessage = commitmessage.rstrip() myupdates, broken_changelog_manifests = self.changelogs( myupdates, mymanifests, myremoved, mychanged, myautoadd, mynew, commitmessage) commit_footer = self.get_commit_footer() commitmessage += commit_footer print("* %s files being committed..." % green(str(len(myupdates))), end=' ') if self.vcs_settings.vcs not in ('cvs', 'svn'): # With git, bzr and hg, there's never any keyword expansion, so # there's no need to regenerate manifests and all files will be # committed in one big commit at the end. print() elif not self.repo_settings.repo_config.thin_manifest: self.thick_manifest(myupdates, myheaders, no_expansion, expansion) logging.info("myupdates: %s", myupdates) logging.info("myheaders: %s", myheaders) uq = UserQuery(self.options) if self.options.ask and uq.query('Commit changes?', True) != 'Yes': print("* aborting commit.") sys.exit(128 + signal.SIGINT) # Handle the case where committed files have keywords which # will change and need a priming commit before the Manifest # can be committed. if (myupdates or myremoved) and myheaders: self.priming_commit(myupdates, myremoved, commitmessage) # When files are removed and re-added, the cvs server will put /Attic/ # inside the $Header path. This code detects the problem and corrects it # so that the Manifest will generate correctly. See bug #169500. # Use binary mode in order to avoid potential character encoding issues. self.clear_attic(myheaders) if self.scanner.repolevel == 1: utilities.repoman_sez("\"You're rather crazy... " "doing the entire repository.\"\n") if self.vcs_settings.vcs in ('cvs', 'svn') and (myupdates or myremoved): for x in sorted( vcs_files_to_cps(chain(myupdates, myremoved, mymanifests), self.scanner.repolevel, self.scanner.reposplit, self.scanner.categories)): self.repoman_settings["O"] = os.path.join( self.repo_settings.repodir, x) digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb) elif broken_changelog_manifests: for x in broken_changelog_manifests: self.repoman_settings["O"] = os.path.join( self.repo_settings.repodir, x) digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb) if self.repo_settings.sign_manifests: self.sign_manifest(myupdates, myremoved, mymanifests) if self.vcs_settings.vcs == 'git': # It's not safe to use the git commit -a option since there might # be some modified files elsewhere in the working tree that the # user doesn't want to commit. Therefore, call git update-index # in order to ensure that the index is updated with the latest # versions of all new and modified files in the relevant portion # of the working tree. myfiles = mymanifests + myupdates myfiles.sort() update_index_cmd = ["git", "update-index"] update_index_cmd.extend(f.lstrip("./") for f in myfiles) if self.options.pretend: print("(%s)" % (" ".join(update_index_cmd), )) else: retval = spawn(update_index_cmd, env=os.environ) if retval != os.EX_OK: writemsg_level("!!! Exiting on %s (shell) " "error code: %s\n" % (self.vcs_settings.vcs, retval), level=logging.ERROR, noiselevel=-1) sys.exit(retval) self.add_manifest(mymanifests, myheaders, myupdates, myremoved, commitmessage) if self.options.quiet: return print() if self.vcs_settings.vcs: print("Commit complete.") else: print("repoman was too scared" " by not seeing any familiar version control file" " that he forgot to commit anything") utilities.repoman_sez( "\"If everyone were like you, I'd be out of business!\"\n") return
def changelogs(self, myupdates, mymanifests, myremoved, mychanged, myautoadd, mynew, changelog_msg): broken_changelog_manifests = [] if self.options.echangelog in ('y', 'force'): logging.info("checking for unmodified ChangeLog files") committer_name = utilities.get_committer_name( env=self.repoman_settings) for x in sorted( vcs_files_to_cps(chain(myupdates, mymanifests, myremoved), self.scanner.repolevel, self.scanner.reposplit, self.scanner.categories)): catdir, pkgdir = x.split("/") checkdir = self.repo_settings.repodir + "/" + x checkdir_relative = "" if self.scanner.repolevel < 3: checkdir_relative = os.path.join(pkgdir, checkdir_relative) if self.scanner.repolevel < 2: checkdir_relative = os.path.join(catdir, checkdir_relative) checkdir_relative = os.path.join(".", checkdir_relative) changelog_path = os.path.join(checkdir_relative, "ChangeLog") changelog_modified = changelog_path in self.scanner.changed.changelogs if changelog_modified and self.options.echangelog != 'force': continue # get changes for this package cdrlen = len(checkdir_relative) check_relative = lambda e: e.startswith(checkdir_relative) split_relative = lambda e: e[cdrlen:] clnew = list(map(split_relative, filter(check_relative, mynew))) clremoved = list( map(split_relative, filter(check_relative, myremoved))) clchanged = list( map(split_relative, filter(check_relative, mychanged))) # Skip ChangeLog generation if only the Manifest was modified, # as discussed in bug #398009. nontrivial_cl_files = set() nontrivial_cl_files.update(clnew, clremoved, clchanged) nontrivial_cl_files.difference_update(['Manifest']) if not nontrivial_cl_files and self.options.echangelog != 'force': continue new_changelog = utilities.UpdateChangeLog( checkdir_relative, committer_name, changelog_msg, os.path.join(self.repo_settings.repodir, 'skel.ChangeLog'), catdir, pkgdir, new=clnew, removed=clremoved, changed=clchanged, pretend=self.options.pretend) if new_changelog is None: writemsg_level("!!! Updating the ChangeLog failed\n", level=logging.ERROR, noiselevel=-1) sys.exit(1) # if the ChangeLog was just created, add it to vcs if new_changelog: myautoadd.append(changelog_path) # myautoadd is appended to myupdates below else: myupdates.append(changelog_path) if self.options.ask and not self.options.pretend: # regenerate Manifest for modified ChangeLog (bug #420735) self.repoman_settings["O"] = checkdir digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb) else: broken_changelog_manifests.append(x) if myautoadd: print(">>> Auto-Adding missing Manifest/ChangeLog file(s)...") add_cmd = [self.vcs_settings.vcs, "add"] add_cmd += myautoadd if self.options.pretend: portage.writemsg_stdout("(%s)\n" % " ".join(add_cmd), noiselevel=-1) else: if sys.hexversion < 0x3020000 and sys.hexversion >= 0x3000000 and \ not os.path.isabs(add_cmd[0]): # Python 3.1 _execvp throws TypeError for non-absolute executable # path passed as bytes (see http://bugs.python.org/issue8513). fullname = find_binary(add_cmd[0]) if fullname is None: raise portage.exception.CommandNotFound(add_cmd[0]) add_cmd[0] = fullname add_cmd = [_unicode_encode(arg) for arg in add_cmd] retcode = subprocess.call(add_cmd) if retcode != os.EX_OK: logging.error("Exiting on %s error code: %s\n" % (self.vcs_settings.vcs, retcode)) sys.exit(retcode) myupdates += myautoadd return myupdates, broken_changelog_manifests
def __init__(self, repo_settings, myreporoot, config_root, options, vcs_settings, mydir, env): '''Class __init__''' self.repo_settings = repo_settings self.config_root = config_root self.options = options self.vcs_settings = vcs_settings self.env = env # Repoman sets it's own ACCEPT_KEYWORDS and we don't want it to # behave incrementally. self.repoman_incrementals = tuple( x for x in portage.const.INCREMENTALS if x != 'ACCEPT_KEYWORDS') self.categories = [] for path in self.repo_settings.repo_config.eclass_db.porttrees: self.categories.extend(portage.util.grabfile( os.path.join(path, 'profiles', 'categories'))) self.repo_settings.repoman_settings.categories = frozenset( portage.util.stack_lists([self.categories], incremental=1)) self.categories = self.repo_settings.repoman_settings.categories self.portdb = repo_settings.portdb self.portdb.settings = self.repo_settings.repoman_settings # We really only need to cache the metadata that's necessary for visibility # filtering. Anything else can be discarded to reduce memory consumption. self.portdb._aux_cache_keys.clear() self.portdb._aux_cache_keys.update( ["EAPI", "IUSE", "KEYWORDS", "repository", "SLOT"]) self.reposplit = myreporoot.split(os.path.sep) self.repolevel = len(self.reposplit) if self.options.mode == 'commit': repochecks.commit_check(self.repolevel, self.reposplit) repochecks.conflict_check(self.vcs_settings, self.options) # Make startdir relative to the canonical repodir, so that we can pass # it to digestgen and it won't have to be canonicalized again. if self.repolevel == 1: startdir = self.repo_settings.repodir else: startdir = normalize_path(mydir) startdir = os.path.join( self.repo_settings.repodir, *startdir.split(os.sep)[-2 - self.repolevel + 3:]) # get lists of valid keywords, licenses, and use new_data = repo_metadata(self.portdb, self.repo_settings.repoman_settings) kwlist, liclist, uselist, profile_list, \ global_pmaskdict, liclist_deprecated = new_data self.repo_metadata = { 'kwlist': kwlist, 'liclist': liclist, 'uselist': uselist, 'profile_list': profile_list, 'pmaskdict': global_pmaskdict, 'lic_deprecated': liclist_deprecated, } self.repo_settings.repoman_settings['PORTAGE_ARCHLIST'] = ' '.join(sorted(kwlist)) self.repo_settings.repoman_settings.backup_changes('PORTAGE_ARCHLIST') self.profiles = setup_profile(profile_list) check_profiles(self.profiles, self.repo_settings.repoman_settings.archlist()) scanlist = scan(self.repolevel, self.reposplit, startdir, self.categories, self.repo_settings) self.dev_keywords = dev_profile_keywords(self.profiles) self.qatracker = QATracker() if self.options.echangelog is None and self.repo_settings.repo_config.update_changelog: self.options.echangelog = 'y' if self.vcs_settings.vcs is None: self.options.echangelog = 'n' self.check = {} # The --echangelog option causes automatic ChangeLog generation, # which invalidates changelog.ebuildadded and changelog.missing # checks. # Note: Some don't use ChangeLogs in distributed SCMs. # It will be generated on server side from scm log, # before package moves to the rsync server. # This is needed because they try to avoid merge collisions. # Gentoo's Council decided to always use the ChangeLog file. # TODO: shouldn't this just be switched on the repo, iso the VCS? is_echangelog_enabled = self.options.echangelog in ('y', 'force') self.vcs_settings.vcs_is_cvs_or_svn = self.vcs_settings.vcs in ('cvs', 'svn') self.check['changelog'] = not is_echangelog_enabled and self.vcs_settings.vcs_is_cvs_or_svn if self.options.mode == "manifest": pass elif self.options.pretend: print(green("\nRepoMan does a once-over of the neighborhood...")) else: print(green("\nRepoMan scours the neighborhood...")) self.changed = Changes(self.options) self.changed.scan(self.vcs_settings) self.have = { 'pmasked': False, 'dev_keywords': False, } # NOTE: match-all caches are not shared due to potential # differences between profiles in _get_implicit_iuse. self.caches = { 'arch': {}, 'arch_xmatch': {}, 'shared_xmatch': {"cp-list": {}}, } self.include_arches = None if self.options.include_arches: self.include_arches = set() self.include_arches.update(*[x.split() for x in self.options.include_arches]) # Disable the "ebuild.notadded" check when not in commit mode and # running `svn status` in every package dir will be too expensive. self.check['ebuild_notadded'] = not \ (self.vcs_settings.vcs == "svn" and self.repolevel < 3 and self.options.mode != "commit") self.effective_scanlist = scanlist if self.options.if_modified == "y": self.effective_scanlist = sorted(vcs_files_to_cps( chain(self.changed.changed, self.changed.new, self.changed.removed), self.repolevel, self.reposplit, self.categories)) self.live_eclasses = portage.const.LIVE_ECLASSES # initialize our checks classes here before the big xpkg loop self.manifester = Manifests(self.options, self.qatracker, self.repo_settings.repoman_settings) self.is_ebuild = IsEbuild(self.repo_settings.repoman_settings, self.repo_settings, self.portdb, self.qatracker) self.filescheck = FileChecks( self.qatracker, self.repo_settings.repoman_settings, self.repo_settings, self.portdb, self.vcs_settings) self.status_check = VCSStatus(self.vcs_settings, self.qatracker) self.fetchcheck = FetchChecks( self.qatracker, self.repo_settings, self.portdb, self.vcs_settings) self.pkgmeta = PkgMetadata(self.options, self.qatracker, self.repo_settings.repoman_settings) self.thirdparty = ThirdPartyMirrors(self.repo_settings.repoman_settings, self.qatracker) self.use_flag_checks = USEFlagChecks(self.qatracker, uselist) self.keywordcheck = KeywordChecks(self.qatracker, self.options) self.liveeclasscheck = LiveEclassChecks(self.qatracker) self.rubyeclasscheck = RubyEclassChecks(self.qatracker) self.eapicheck = EAPIChecks(self.qatracker, self.repo_settings) self.descriptioncheck = DescriptionChecks(self.qatracker) self.licensecheck = LicenseChecks(self.qatracker, liclist, liclist_deprecated) self.restrictcheck = RestrictChecks(self.qatracker)
def perform(self, qa_output): myunadded, mydeleted = self._vcs_unadded() myautoadd = self._vcs_autoadd(myunadded) self._vcs_deleted(mydeleted) changes = self.get_vcs_changed(mydeleted) mynew, mychanged, myremoved, no_expansion, expansion = changes # Manifests need to be regenerated after all other commits, so don't commit # them now even if they have changed. mymanifests = set() myupdates = set() for f in mychanged + mynew: if "Manifest" == os.path.basename(f): mymanifests.add(f) else: myupdates.add(f) myupdates.difference_update(myremoved) myupdates = list(myupdates) mymanifests = list(mymanifests) myheaders = [] commitmessage = self.options.commitmsg if self.options.commitmsgfile: try: f = io.open( _unicode_encode( self.options.commitmsgfile, encoding=_encodings['fs'], errors='strict'), mode='r', encoding=_encodings['content'], errors='replace') commitmessage = f.read() f.close() del f except (IOError, OSError) as e: if e.errno == errno.ENOENT: portage.writemsg( "!!! File Not Found:" " --commitmsgfile='%s'\n" % self.options.commitmsgfile) else: raise if not commitmessage or not commitmessage.strip(): commitmessage = self.get_new_commit_message(qa_output) commitmessage = commitmessage.rstrip() myupdates, broken_changelog_manifests = self.changelogs( myupdates, mymanifests, myremoved, mychanged, myautoadd, mynew, commitmessage) commit_footer = self.get_commit_footer() commitmessage += commit_footer print("* %s files being committed..." % green(str(len(myupdates))), end=' ') if self.vcs_settings.vcs not in ('cvs', 'svn'): # With git, bzr and hg, there's never any keyword expansion, so # there's no need to regenerate manifests and all files will be # committed in one big commit at the end. print() elif not self.repo_settings.repo_config.thin_manifest: self.thick_manifest(myupdates, myheaders, no_expansion, expansion) logging.info("myupdates: %s", myupdates) logging.info("myheaders: %s", myheaders) uq = UserQuery(self.options) if self.options.ask and uq.query('Commit changes?', True) != 'Yes': print("* aborting commit.") sys.exit(128 + signal.SIGINT) # Handle the case where committed files have keywords which # will change and need a priming commit before the Manifest # can be committed. if (myupdates or myremoved) and myheaders: self.priming_commit(myupdates, myremoved, commitmessage) # When files are removed and re-added, the cvs server will put /Attic/ # inside the $Header path. This code detects the problem and corrects it # so that the Manifest will generate correctly. See bug #169500. # Use binary mode in order to avoid potential character encoding issues. self.clear_attic(myheaders) if self.scanner.repolevel == 1: utilities.repoman_sez( "\"You're rather crazy... " "doing the entire repository.\"\n") if self.vcs_settings.vcs in ('cvs', 'svn') and (myupdates or myremoved): for x in sorted(vcs_files_to_cps( chain(myupdates, myremoved, mymanifests), self.scanner.repolevel, self.scanner.reposplit, self.scanner.categories)): self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x) digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb) elif broken_changelog_manifests: for x in broken_changelog_manifests: self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x) digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb) if self.repo_settings.sign_manifests: self.sign_manifest(myupdates, myremoved, mymanifests) if self.vcs_settings.vcs == 'git': # It's not safe to use the git commit -a option since there might # be some modified files elsewhere in the working tree that the # user doesn't want to commit. Therefore, call git update-index # in order to ensure that the index is updated with the latest # versions of all new and modified files in the relevant portion # of the working tree. myfiles = mymanifests + myupdates myfiles.sort() update_index_cmd = ["git", "update-index"] update_index_cmd.extend(f.lstrip("./") for f in myfiles) if self.options.pretend: print("(%s)" % (" ".join(update_index_cmd),)) else: retval = spawn(update_index_cmd, env=os.environ) if retval != os.EX_OK: writemsg_level( "!!! Exiting on %s (shell) " "error code: %s\n" % (self.vcs_settings.vcs, retval), level=logging.ERROR, noiselevel=-1) sys.exit(retval) self.add_manifest(mymanifests, myheaders, myupdates, myremoved, commitmessage) if self.options.quiet: return print() if self.vcs_settings.vcs: print("Commit complete.") else: print( "repoman was too scared" " by not seeing any familiar version control file" " that he forgot to commit anything") utilities.repoman_sez( "\"If everyone were like you, I'd be out of business!\"\n") return
def changelogs(self, myupdates, mymanifests, myremoved, mychanged, myautoadd, mynew, changelog_msg): broken_changelog_manifests = [] if self.options.echangelog in ('y', 'force'): logging.info("checking for unmodified ChangeLog files") committer_name = utilities.get_committer_name(env=self.repoman_settings) for x in sorted(vcs_files_to_cps( chain(myupdates, mymanifests, myremoved), self.scanner.repolevel, self.scanner.reposplit, self.scanner.categories)): catdir, pkgdir = x.split("/") checkdir = self.repo_settings.repodir + "/" + x checkdir_relative = "" if self.scanner.repolevel < 3: checkdir_relative = os.path.join(pkgdir, checkdir_relative) if self.scanner.repolevel < 2: checkdir_relative = os.path.join(catdir, checkdir_relative) checkdir_relative = os.path.join(".", checkdir_relative) changelog_path = os.path.join(checkdir_relative, "ChangeLog") changelog_modified = changelog_path in self.scanner.changed.changelogs if changelog_modified and self.options.echangelog != 'force': continue # get changes for this package cdrlen = len(checkdir_relative) check_relative = lambda e: e.startswith(checkdir_relative) split_relative = lambda e: e[cdrlen:] clnew = list(map(split_relative, filter(check_relative, mynew))) clremoved = list(map(split_relative, filter(check_relative, myremoved))) clchanged = list(map(split_relative, filter(check_relative, mychanged))) # Skip ChangeLog generation if only the Manifest was modified, # as discussed in bug #398009. nontrivial_cl_files = set() nontrivial_cl_files.update(clnew, clremoved, clchanged) nontrivial_cl_files.difference_update(['Manifest']) if not nontrivial_cl_files and self.options.echangelog != 'force': continue new_changelog = utilities.UpdateChangeLog( checkdir_relative, committer_name, changelog_msg, os.path.join(self.repo_settings.repodir, 'skel.ChangeLog'), catdir, pkgdir, new=clnew, removed=clremoved, changed=clchanged, pretend=self.options.pretend) if new_changelog is None: writemsg_level( "!!! Updating the ChangeLog failed\n", level=logging.ERROR, noiselevel=-1) sys.exit(1) # if the ChangeLog was just created, add it to vcs if new_changelog: myautoadd.append(changelog_path) # myautoadd is appended to myupdates below else: myupdates.append(changelog_path) if self.options.ask and not self.options.pretend: # regenerate Manifest for modified ChangeLog (bug #420735) self.repoman_settings["O"] = checkdir digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb) else: broken_changelog_manifests.append(x) if myautoadd: print(">>> Auto-Adding missing Manifest/ChangeLog file(s)...") add_cmd = [self.vcs_settings.vcs, "add"] add_cmd += myautoadd if self.options.pretend: portage.writemsg_stdout( "(%s)\n" % " ".join(add_cmd), noiselevel=-1) else: if sys.hexversion < 0x3020000 and sys.hexversion >= 0x3000000 and \ not os.path.isabs(add_cmd[0]): # Python 3.1 _execvp throws TypeError for non-absolute executable # path passed as bytes (see http://bugs.python.org/issue8513). fullname = find_binary(add_cmd[0]) if fullname is None: raise portage.exception.CommandNotFound(add_cmd[0]) add_cmd[0] = fullname add_cmd = [_unicode_encode(arg) for arg in add_cmd] retcode = subprocess.call(add_cmd) if retcode != os.EX_OK: logging.error( "Exiting on %s error code: %s\n" % (self.vcs_settings.vcs, retcode)) sys.exit(retcode) myupdates += myautoadd return myupdates, broken_changelog_manifests
def __init__(self, repo_settings, myreporoot, config_root, options, vcs_settings, mydir, env): '''Class __init__''' self.repo_settings = repo_settings self.config_root = config_root self.options = options self.vcs_settings = vcs_settings self.env = env # Repoman sets it's own ACCEPT_KEYWORDS and we don't want it to # behave incrementally. self.repoman_incrementals = tuple( x for x in portage.const.INCREMENTALS if x != 'ACCEPT_KEYWORDS') self.categories = [] for path in self.repo_settings.repo_config.eclass_db.porttrees: self.categories.extend(portage.util.grabfile( os.path.join(path, 'profiles', 'categories'))) self.repo_settings.repoman_settings.categories = frozenset( portage.util.stack_lists([self.categories], incremental=1)) self.categories = self.repo_settings.repoman_settings.categories metadata_dtd = None for path in reversed(self.repo_settings.repo_config.eclass_db.porttrees): path = os.path.join(path, 'metadata/dtd/metadata.dtd') if os.path.exists(path): metadata_dtd = path break self.portdb = repo_settings.portdb self.portdb.settings = self.repo_settings.repoman_settings # We really only need to cache the metadata that's necessary for visibility # filtering. Anything else can be discarded to reduce memory consumption. if self.options.mode != "manifest" and self.options.digest != "y": # Don't do this when generating manifests, since that uses # additional keys if spawn_nofetch is called (RESTRICT and # DEFINED_PHASES). self.portdb._aux_cache_keys.clear() self.portdb._aux_cache_keys.update( ["EAPI", "IUSE", "KEYWORDS", "repository", "SLOT"]) self.reposplit = myreporoot.split(os.path.sep) self.repolevel = len(self.reposplit) if self.options.mode == 'commit': repochecks.commit_check(self.repolevel, self.reposplit) repochecks.conflict_check(self.vcs_settings, self.options) # Make startdir relative to the canonical repodir, so that we can pass # it to digestgen and it won't have to be canonicalized again. if self.repolevel == 1: startdir = self.repo_settings.repodir else: startdir = normalize_path(mydir) startdir = os.path.join( self.repo_settings.repodir, *startdir.split(os.sep)[-2 - self.repolevel + 3:]) # get lists of valid keywords, licenses, and use new_data = repo_metadata(self.portdb, self.repo_settings.repoman_settings) kwlist, liclist, uselist, profile_list, \ global_pmaskdict, liclist_deprecated = new_data self.repo_metadata = { 'kwlist': kwlist, 'liclist': liclist, 'uselist': uselist, 'profile_list': profile_list, 'pmaskdict': global_pmaskdict, 'lic_deprecated': liclist_deprecated, } self.repo_settings.repoman_settings['PORTAGE_ARCHLIST'] = ' '.join(sorted(kwlist)) self.repo_settings.repoman_settings.backup_changes('PORTAGE_ARCHLIST') self.profiles = setup_profile(profile_list) check_profiles(self.profiles, self.repo_settings.repoman_settings.archlist()) scanlist = scan(self.repolevel, self.reposplit, startdir, self.categories, self.repo_settings) self.dev_keywords = dev_profile_keywords(self.profiles) self.qatracker = QATracker() if self.options.echangelog is None and self.repo_settings.repo_config.update_changelog: self.options.echangelog = 'y' if self.vcs_settings.vcs is None: self.options.echangelog = 'n' self.check = {} # The --echangelog option causes automatic ChangeLog generation, # which invalidates changelog.ebuildadded and changelog.missing # checks. # Note: Some don't use ChangeLogs in distributed SCMs. # It will be generated on server side from scm log, # before package moves to the rsync server. # This is needed because they try to avoid merge collisions. # Gentoo's Council decided to always use the ChangeLog file. # TODO: shouldn't this just be switched on the repo, iso the VCS? is_echangelog_enabled = self.options.echangelog in ('y', 'force') self.vcs_settings.vcs_is_cvs_or_svn = self.vcs_settings.vcs in ('cvs', 'svn') self.check['changelog'] = not is_echangelog_enabled and self.vcs_settings.vcs_is_cvs_or_svn if self.options.mode == "manifest" or self.options.quiet: pass elif self.options.pretend: print(green("\nRepoMan does a once-over of the neighborhood...")) else: print(green("\nRepoMan scours the neighborhood...")) self.changed = Changes(self.options) # bypass unneeded VCS operations if not needed if (self.options.if_modified == "y" or self.options.mode not in ("manifest", "manifest-check")): self.changed.scan(self.vcs_settings) self.have = { 'pmasked': False, 'dev_keywords': False, } # NOTE: match-all caches are not shared due to potential # differences between profiles in _get_implicit_iuse. self.caches = { 'arch': {}, 'arch_xmatch': {}, 'shared_xmatch': {"cp-list": {}}, } self.include_arches = None if self.options.include_arches: self.include_arches = set() self.include_arches.update(*[x.split() for x in self.options.include_arches]) # Disable the "ebuild.notadded" check when not in commit mode and # running `svn status` in every package dir will be too expensive. self.check['ebuild_notadded'] = not \ (self.vcs_settings.vcs == "svn" and self.repolevel < 3 and self.options.mode != "commit") self.effective_scanlist = scanlist if self.options.if_modified == "y": self.effective_scanlist = sorted(vcs_files_to_cps( chain(self.changed.changed, self.changed.new, self.changed.removed), self.repolevel, self.reposplit, self.categories)) self.live_eclasses = portage.const.LIVE_ECLASSES # initialize our checks classes here before the big xpkg loop self.manifester = Manifests(self.options, self.qatracker, self.repo_settings.repoman_settings) self.is_ebuild = IsEbuild(self.repo_settings.repoman_settings, self.repo_settings, self.portdb, self.qatracker) self.filescheck = FileChecks( self.qatracker, self.repo_settings.repoman_settings, self.repo_settings, self.portdb, self.vcs_settings) self.status_check = VCSStatus(self.vcs_settings, self.qatracker) self.fetchcheck = FetchChecks( self.qatracker, self.repo_settings, self.portdb, self.vcs_settings) self.pkgmeta = PkgMetadata(self.options, self.qatracker, self.repo_settings.repoman_settings, metadata_dtd=metadata_dtd) self.thirdparty = ThirdPartyMirrors(self.repo_settings.repoman_settings, self.qatracker) self.use_flag_checks = USEFlagChecks(self.qatracker, uselist) self.keywordcheck = KeywordChecks(self.qatracker, self.options) self.liveeclasscheck = LiveEclassChecks(self.qatracker) self.rubyeclasscheck = RubyEclassChecks(self.qatracker) self.eapicheck = EAPIChecks(self.qatracker, self.repo_settings) self.descriptioncheck = DescriptionChecks(self.qatracker) self.licensecheck = LicenseChecks(self.qatracker, liclist, liclist_deprecated) self.restrictcheck = RestrictChecks(self.qatracker)