User:Tillschaefer/cleanup package

From Gentoo Wiki
Jump to: navigation, search

Cleaning /etc/portage/package.* from unused entries

After some time it happens, that files under /etc/portage/package.* (e.g. /etc/portage/package.accept_keywords contain entries of packages that are no longer installed or are installed in another version than specified. This useless entries are removed by the following script. The script also remove any comment lined directly above the removed entries. Comment lines separated by blank lines are not removed.

Example

FILE /etc/portage/package.accept_keywordsbefore cleaning
#############
# custom keywords
#############

kde-apps/*

#############
# autounmask
#############

# required by kde-frameworks/baloo-5.18.0::gentoo
# required by kde-apps/dolphin-15.12.1::kde[semantic-desktop]
# required by kde-apps/kdecore-meta-15.12.1-r1::kde
# required by kde-apps/kdebase-meta-15.12.1-r2::kde
# required by @selected
# required by @world (argument)
=dev-db/lmdb-0.9.17 ~amd64
# required by kde-apps/libkexiv2-15.12.1::gentoo
# required by kde-apps/thumbnailers-15.12.1::gentoo
# required by kde-apps/dolphin-15.12.1::kde[thumbnail]
# required by kde-apps/kdecore-meta-15.12.1-r1::kde
# required by kde-apps/kdebase-meta-15.12.1-r2::kde
# required by @selected
# required by @world (argument)
=media-gfx/exiv2-0.25-r2 ~amd64

if dev-db/lmdb-0.9.17 is no longer installed (e.g. because it is updated to version 0.9.18) and we run

root #eclean-package --inplace

we get a filtered file, that does not contain the outdated package atom. The related autounmask comments are also removed, but not the custom commend above.

FILE /etc/portage/package.accept_keywordsafter cleaning
#############
# custom keywords
#############

kde-apps/*

#############
# autounmask
#############

# required by kde-apps/libkexiv2-15.12.1::gentoo
# required by kde-apps/thumbnailers-15.12.1::gentoo
# required by kde-apps/dolphin-15.12.1::kde[thumbnail]
# required by kde-apps/kdecore-meta-15.12.1-r1::kde
# required by kde-apps/kdebase-meta-15.12.1-r2::kde
# required by @selected
# required by @world (argument)
=media-gfx/exiv2-0.25-r2 ~amd64

Script

Note
You must have installed app-portage/portage-utils and activate the q-reinitialize as postsync hook /etc/portage/postsync.d/q-reinitialize
FILE /usr/local/sbin/eclean-package
#!/usr/bin/env python3

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

if __name__ != '__main__':
    raise Exception("must 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 = []