def digest_regen(self, updates, removed, manifests, scanner, broken_changelog_manifests): '''Regenerate manifests @param updates: updated files @param removed: removed files @param manifests: Manifest files @param scanner: The repoman.scanner.Scanner instance @param broken_changelog_manifests: broken changelog manifests ''' if 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)
def digest_regen(self, updates, removed, manifests, scanner, broken_changelog_manifests): '''Regenerate manifests @param updates: updated files @param removed: removed files @param manifests: Manifest files @param scanner: The repoman.scanner.Scanner instance @param broken_changelog_manifests: broken changelog manifests ''' if 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)
def digest_regen(self, updates, removed, manifests, scanner, broken_changelog_manifests): '''Regenerate manifests @param updates: updated files @param removed: removed files @param manifests: Manifest files @param scanner: The repoman.scanner.Scanner instance @param broken_changelog_manifests: broken changelog manifests ''' if updates or removed: for x in sorted(vcs_files_to_cps( chain(updates, removed, manifests), scanner.repolevel, scanner.reposplit, scanner.categories)): self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x) digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb)
def digest_regen(self, updates, removed, manifests, scanner, broken_changelog_manifests): '''Regenerate manifests @param updates: updated files @param removed: removed files @param manifests: Manifest files @param scanner: The repoman.scanner.Scanner instance @param broken_changelog_manifests: broken changelog manifests ''' if updates or removed: for x in sorted(vcs_files_to_cps( chain(updates, removed, manifests), scanner.repo_settings.repodir, scanner.repolevel, scanner.reposplit, scanner.categories)): self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x) digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb)
def _fetchonly_exit(self, fetcher): self._final_exit(fetcher) if self.returncode != os.EX_OK: portdb = self.pkg.root_config.trees[self._tree].dbapi spawn_nofetch(portdb, self._ebuild_path, settings=self.settings) elif 'digest' in self.settings.features: if not digestgen(mysettings=self.settings, myportdb=self.pkg.root_config.trees[self._tree].dbapi): self.returncode = 1 self.wait()
def _fetchonly_exit(self, fetcher): self._final_exit(fetcher) if self.returncode != os.EX_OK: portdb = self.pkg.root_config.trees[self._tree].dbapi spawn_nofetch(portdb, self._ebuild_path, settings=self.settings) elif 'digest' in self.settings.features: if not digestgen(mysettings=self.settings, myportdb=self.pkg.root_config.trees[self._tree].dbapi): self.returncode = 1 self.wait()
def update_manifest(self, checkdir): """Perform a manifest generation for the pkg @param checkdir: the current package directory @rtype: bool @return: True if successful, False otherwise """ self.generated_manifest = False failed = False self.auto_assumed = set() fetchlist_dict = portage.FetchlistDict(checkdir, self.repoman_settings, self.portdb) if self.options.mode == "manifest" and self.options.force: self._discard_dist_digests(checkdir, fetchlist_dict) self.repoman_settings["O"] = checkdir try: self.generated_manifest = digestgen( mysettings=self.repoman_settings, myportdb=self.portdb) except portage.exception.PermissionDenied as e: self.generated_manifest = False writemsg_level( "!!! Permission denied: '%s'\n" % (e, ), level=logging.ERROR, noiselevel=-1, ) if not self.generated_manifest: writemsg_level( "!!! Unable to generate manifest for '%s'.\n" % (checkdir, ), level=logging.ERROR, noiselevel=-1, ) failed = True if self.options.mode == "manifest": if (not failed and self.options.force and self.auto_assumed and "assume-digests" in self.repoman_settings.features): # Show which digests were assumed despite the --force option # being given. This output will already have been shown by # digestgen() if assume-digests is not enabled, so only show # it here if assume-digests is enabled. pkgs = list(fetchlist_dict) pkgs.sort() portage.writemsg_stdout( " digest.assumed %s" % portage.output.colorize( "WARN", str(len(self.auto_assumed)).rjust(18)) + "\n") for cpv in pkgs: fetchmap = fetchlist_dict[cpv] pf = portage.catsplit(cpv)[1] for distfile in sorted(fetchmap): if distfile in self.auto_assumed: portage.writemsg_stdout(" %s::%s\n" % (pf, distfile)) return not failed
def run(self, checkdir, portdb): self.generated_manifest = False self.digest_only = self.options.mode != 'manifest-check' \ and self.options.digest == 'y' if self.options.pretend: return False if self.options.mode in ("manifest", 'commit', 'fix') or self.digest_only: failed = False self.auto_assumed = set() fetchlist_dict = portage.FetchlistDict( checkdir, self.repoman_settings, portdb) if self.options.mode == 'manifest' and self.options.force: portage._doebuild_manifest_exempt_depend += 1 self.create_manifest(checkdir, fetchlist_dict) self.repoman_settings["O"] = checkdir try: self.generated_manifest = digestgen( mysettings=self.repoman_settings, myportdb=portdb) except portage.exception.PermissionDenied as e: self.generated_manifest = False writemsg_level( "!!! Permission denied: '%s'\n" % (e,), level=logging.ERROR, noiselevel=-1) if not self.generated_manifest: writemsg_level( "Unable to generate manifest.", level=logging.ERROR, noiselevel=-1) failed = True if self.options.mode == "manifest": if not failed and self.options.force and self.auto_assumed and \ 'assume-digests' in self.repoman_settings.features: # Show which digests were assumed despite the --force option # being given. This output will already have been shown by # digestgen() if assume-digests is not enabled, so only show # it here if assume-digests is enabled. pkgs = list(fetchlist_dict) pkgs.sort() portage.writemsg_stdout( " digest.assumed %s" % portage.output.colorize( "WARN", str(len(self.auto_assumed)).rjust(18)) + "\n") for cpv in pkgs: fetchmap = fetchlist_dict[cpv] pf = portage.catsplit(cpv)[1] for distfile in sorted(fetchmap): if distfile in self.auto_assumed: portage.writemsg_stdout( " %s::%s\n" % (pf, distfile)) # continue, skip remaining main loop code return True elif failed: sys.exit(1) return False
def update_manifest(self, checkdir): '''Perform a manifest generation for the pkg @param checkdir: the current package directory @returns: dictionary ''' self.generated_manifest = False failed = False self.auto_assumed = set() fetchlist_dict = portage.FetchlistDict( checkdir, self.repoman_settings, self.portdb) if self.options.mode == 'manifest' and self.options.force: self._discard_dist_digests(checkdir, fetchlist_dict) self.repoman_settings["O"] = checkdir try: self.generated_manifest = digestgen( mysettings=self.repoman_settings, myportdb=self.portdb) except portage.exception.PermissionDenied as e: self.generated_manifest = False writemsg_level( "!!! Permission denied: '%s'\n" % (e,), level=logging.ERROR, noiselevel=-1) if not self.generated_manifest: writemsg_level( "Unable to generate manifest.", level=logging.ERROR, noiselevel=-1) failed = True if self.options.mode == "manifest": if not failed and self.options.force and self.auto_assumed and \ 'assume-digests' in self.repoman_settings.features: # Show which digests were assumed despite the --force option # being given. This output will already have been shown by # digestgen() if assume-digests is not enabled, so only show # it here if assume-digests is enabled. pkgs = list(fetchlist_dict) pkgs.sort() portage.writemsg_stdout( " digest.assumed %s" % portage.output.colorize( "WARN", str(len(self.auto_assumed)).rjust(18)) + "\n") for cpv in pkgs: fetchmap = fetchlist_dict[cpv] pf = portage.catsplit(cpv)[1] for distfile in sorted(fetchmap): if distfile in self.auto_assumed: portage.writemsg_stdout( " %s::%s\n" % (pf, distfile)) # continue, skip remaining main loop code return True elif failed: sys.exit(1) return False
def _manifest_gen(self, cp): """ Generate manifest for a cp. @param cp: category/pn string @type str @rtype: bool @return: True if successful, False otherwise """ self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, cp) return bool(digestgen( mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb))
def _create_ebuild_manifests(self, ebuilds): tmpsettings = config(clone=self.settings) tmpsettings['PORTAGE_QUIET'] = '1' for cpv in ebuilds: a = Atom("=" + cpv, allow_repo=True) repo = a.repo if repo is None: repo = "test_repo" repo_dir = self._get_repo_dir(repo) ebuild_dir = os.path.join(repo_dir, a.cp) ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild") portdb = self.trees[self.eroot]["porttree"].dbapi tmpsettings['O'] = ebuild_dir if not digestgen(mysettings=tmpsettings, myportdb=portdb): raise AssertionError('digest creation failed for %s' % ebuild_path)
def _create_ebuild_manifests(self, ebuilds): tmpsettings = config(clone=self.settings) tmpsettings['PORTAGE_QUIET'] = '1' for cpv in ebuilds: a = Atom("=" + cpv, allow_repo=True) repo = a.repo if repo is None: repo = "test_repo" repo_dir = self._get_repo_dir(repo) ebuild_dir = os.path.join(repo_dir, a.cp) ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild") portdb = self.trees[self.eroot]["porttree"].dbapi tmpsettings['O'] = ebuild_dir if not digestgen(mysettings=tmpsettings, myportdb=portdb): raise AssertionError('digest creation failed for %s' % ebuild_path)
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.repo_settings.repodir, 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)...") self.vcs_settings.changes.add_items(myautoadd) myupdates += myautoadd return myupdates, broken_changelog_manifests
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 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 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.repo_settings.repodir, 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)...") self.vcs_settings.changes.add_items(myautoadd) myupdates += myautoadd return myupdates, broken_changelog_manifests