9

One can select testing packages on a gentoo stable system by adding a line with the following syntax to keywords list:

cat /etc/portage/package.keywords

=dev-python/ipython-0.13.2 ~amd64
# and many lines later
=dev-python/ipython-0.14.1 ~amd64
# and many lines later
>=dev-python/ipython-0.13.4 ~amd64

This file will grow within the time and sooner or later one can not remember which lines are obsolete.

How can I tidy up the list with a script from time to time?

A line should be deleted,

  • if the testing version is already stabilized
  • >= was used for the same package
  • = was used for the same package with smaller version number
  • If you're still watching this see my Answer. – eyoung100 Dec 5 '14 at 22:14
5

There is an official package now for this task called app-portage/portpeek.

It can

  • find obsolete USE flags and
  • obsolete KEYWORDS and
  • clean the files, if -f (fix) is added as parameter.
3

I wrote a small python script that takes care of this problem. The logic looks at each line in the file package.accept_keywords and only acts on lines that start with = or <=. These lines have a maximum bound version so we can check if they are needed anymore. Lines without a qualifier or a >= are left as-is as we cannot know if they are obsolete.

The lines that we care about are then parsed and the installed version of the package is checked. If the installed version is newer than the keyworded version, or is not longer installed at all, the keyword is considered obsolete. If the installed package is the same version as the keyworded version then the installed package is checked to see if it is still keyworded. If it has been stabilized, the line is obsoleted, otherwise it is retained.

#!/bin/env python

import re
import portage

vartree = portage.db[portage.root]['vartree']

with open('/etc/portage/package.accept_keywords') as f:
    for x in f:
        # eat newline
        x = x.rstrip()
        # we only want lines with a bounded max version
        if re.match('^(=|<=)',x):
            # get the package cpv atom -- strip the =|<= and the trailing keyword(s)
            cpv_masked = re.sub('[<=]','',x.split(' ',1)[0])
            cat, pkg, ver, rev = portage.catpkgsplit(cpv_masked)
            # get cpv for all installed versions of the package
            cpv_installed = vartree.dep_match(cat+'/'+pkg)
            for cpv in cpv_installed:
                cmp = portage.pkgcmp(portage.pkgsplit(cpv), portage.pkgsplit(cpv_masked))
                # if the installed version is not newer than the masked version
                if (cmp <= 0):
                    # check if this version is still keyworded
                    cpv_keywords = vartree.dbapi.aux_get(cpv, ['KEYWORDS'])
                    # keep keyword if the package has no keywords (**)
                    if not cpv_keywords[0]:
                        print(x)
                        break
                    # check if the installed package is still keyworded
                    for cpv_keyword in cpv_keywords[0].split(' '):
                        if cpv_masked_keyword == cpv_keyword:
                            # it is, keep the atom and move on to the next one
                            print(x)
                            break                    
        else:
            # keep atoms that have an unbounded max version
            print(x)

This will print the new keywords file to standard out. Note: do not redirect the output back into /etc/portage/package.accept_keywords or you will clobber the file and lose everything.

This will go a long way toward cleaning up your keywords file and for your other concerns, sorting the file and then examining it for multiple lines for the same package will help resolve most of what is left.

1

You know you can convert the package.* files in directories, right?

Then you can organize your atoms in several files, eg, in my system I got the following (well, not really, i am not at my laptop now. But you het the idea):

/etc/portage/package.keywords:
  package.keywords
  qt5.keywords
  xfce.keywords

/etc/portage/package.use:
  package.use
  qt5.use
  xfce.use

etc.

I found this really useful to help me have the files updated.

0

Adding to Ikraav's answer:

After using eix -tT, remove the comparison operators and the package version number. Your File can also be written as:

dev-python/ipython ~amd64
# and many lines later
package-cat/package ~arch

This will guarantee that you will always get the testing versions of dev-python/ipython and package-cat/package

  • the ~amd64 in my question might be misleading. The version numbers should stay untouched. I do not want to get always the latest version, but find redundant lines. – Jonas Stein Dec 10 '14 at 16:54
  • Using the package without the version removes the duplicate entries. Consider Package A requires >= Package C Version 1.0.0, and Package B requires C Version 1.0.1. In practice, Package A and B are both Satisfied by any version Greater than 1, and if all versions > 1.0.0 are in ~arch then the version numbers are irrelevant. The only other way to fix this is to mask all versions of Package C then unmask the greatest Version after the portage world update. – eyoung100 Dec 10 '14 at 17:48
  • I'm old school, and I manually edit all my Portage config files, mainly because I learned how to do it before portage did it automatically. The reason you have duplicates is because portage won't remove the line when a newer version supersedes an older one. – eyoung100 Dec 10 '14 at 17:56
0

Here is a small script that filters entries from /etc/portage/package.* files that are not installed anymore. Additionally it removes all comment lines directly above the removed entry. (e.g. as generated by autounmask). If comments are separated by a blank line it will only remove the lower comments. The script does not remove duplicate entries.

Please note that portage-utils need to be installed and the postsync hook /etc/portage/postsync.d/q-reinitialize must be activated in order to get this script working.

#!/usr/bin/env python3

import argparse
import sys
import os
from subprocess import call
import contextlib

if __name__ != '__main__':
    raise Exception("ust be used as a main module with a parameter as the input file")

parser = argparse.ArgumentParser(description="cleanup /etc/portage/package.* files")
parser.add_argument("infile", help="an input file to clean")
parser.add_argument("--out", dest="outfile", help="the output is written to this file. if not specified, the output is written to stdout.")
parser.add_argument("--inplace", action='store_true', help="overwrite the in file. if specified, --out is ignored.")

args = parser.parse_args()

def checkInstalled(package):
    with open(os.devnull, 'w') as devnull:
        status = call('qlist -IC "' + str(package.split()[0].strip()) + '"', shell=True, stdout=devnull)
        return status == 0

@contextlib.contextmanager
def getOutFile(args):
    if args.inplace:
        fh = open(args.infile, 'w')
    elif args.outfile != None:
        fh = open(args.outfile, 'w')
    else:
        fh = sys.stdout
    try:
        yield fh
    finally:
        if fh is not sys.stdout:
            fh.close()

commentBuffer = []
lines = []

with open(args.infile, 'r') as f:
    lines = f.readlines()

with getOutFile(args) as out:
    for line in lines: 
        if line.lstrip().startswith("#"):
            commentBuffer.append(line)
        else:
            if line.strip() == "" or checkInstalled(line):
                if  commentBuffer:
                    out.write("".join(commentBuffer))
                out.write(line)
            commentBuffer = []
0

As of now, the app-portage/eix package offers a handy tool named eix-test-obsolete. A brief description from eix-test-obsolete -h:

Usage: eix-test-obsolete [options] detail|brief|quick
  This is a wrapper script for eix (eix 0.33.5).

It calls eix -tTc several times with various variable settings in order to
display missing packages or packages with obsolete entries in
/etc/portage/package.* in a more organized manner than eix -tTc would do alone.

It gives a pretty good overview of all the redundant entries in /etc/portage/package.* files. The only thing I'm personally missing is an info about the exact file and line defining the redundant unmask/use/accept/whatever. However, grep -nr helps in that case.

$ eix-test-obsolete -c
No non-matching entries in /etc/portage/package.keywords
No non-matching entries in /etc/portage/package.accept_keywords
No non-matching entries in /etc/portage/package.mask
No non-matching entries in /etc/portage/package.unmask
No non-matching or empty entries in /etc/portage/package.use
No non-matching or empty entries in /etc/portage/package.env
No non-matching or empty entries in /etc/portage/package.license
No non-matching or empty entries in /etc/portage/package.accept_restrict
No non-matching or empty entries in /etc/portage/package.cflags
The names of all installed packages are in the database.

Redundant in /etc/portage/package.{,accept_}keywords:

... considered as REDUNDANT_IF_NO_CHANGE
[I] app-accessibility/at-spi2-core (2.26.2(2)@11/30/2018): D-Bus accessibility specifications and registration daemon
[I] app-emulation/runc (1.0.0_rc5_p20180509@11/29/2018): runc container cli tools
[N] app-emulation/wine-staging ((~)3.21(3.21)): Free implementation of Windows(tm) on Unix, with Wine-Staging patchset
[I] sys-process/tini (0.18.0@11/29/2018): A tiny but valid init for containers
[1] "go-overlay" /var/db/repos/go-overlay

Found 4 matches


Not installed but in /etc/portage/package.{,accept_}keywords:
[N] app-emulation/wine-staging ((~)3.21(3.21)): Free implementation of Windows(tm) on Unix, with Wine-Staging patchset

No  redundant  entries in /etc/portage/package.mask
No uninstalled entries in /etc/portage/package.mask
No  redundant  entries in /etc/portage/package.unmask
No uninstalled entries in /etc/portage/package.unmask
Skipping check:  redundant  entries in /etc/portage/package.use
Skipping check: uninstalled entries in /etc/portage/package.use
Skipping check:  redundant  entries in /etc/portage/package.env
Skipping check: uninstalled entries in /etc/portage/package.env
No  redundant  entries in /etc/portage/package.license
No uninstalled entries in /etc/portage/package.license
No  redundant  entries in /etc/portage/package.accept_restrict
No uninstalled entries in /etc/portage/package.accept_restrict
Skipping check:  redundant  entries in /etc/portage/package.cflags
Skipping check: uninstalled entries in /etc/portage/package.cflags

Installed packages with a version not in the database (or masked):
[U] www-client/firefox (60.3.0-r1@12/01/2018 -> 60.4.0^d): Firefox Web Browser
-1

Start with eix -tT. Install app-portage/eix to get that.

  • I do not understand how eix -tT solves this. Can you explain it a bit more please? – Jonas Stein Jul 13 '14 at 20:35
  • I think you'd have to pastebin some output and point to line numbers of parts you don't understand. – lkraav Jul 13 '14 at 20:49
  • I wish there was more info. This leads to "tips and tricks" and the link to the original blog post is dead. This helps a bit. The package has been active recently. The homepage link points to eix.berlios.de but this doesn't exist. Where are the manpages for that online(with all the options)? – user44370 Jul 22 '14 at 20:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.