如何清理gentoo系统上的.keywords文件?

如何清理gentoo系统上的.keywords文件?

可以gentoo stable通过向关键字列表添加具有以下语法的行来选择系统上的测试包:

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

该文件会随着时间的推移而增长,迟早人们会记不起哪些行已过时。

如何时不时用脚本整理列表?

应删除一行,

  • 如果测试版本已经稳定
  • >= 用于同一个包
  • = 用于具有较小版本号的同一软件包

答案1

现在有一个用于此任务的官方包,名为应用程序 portage/portpeek

它可以

  • 找到过时的 USE 标志并
  • 过时的关键字和
  • -f如果添加 (fix) 作为参数,则清理文件。

答案2

我写了一个小的 python 脚本来解决这个问题。该逻辑查看文件中的每一行package.accept_keywords,并且仅作用于以=或开头的行<=。这些行有最大绑定版本,因此我们可以检查它们是否不再需要。没有限定符或 a 的行>=保持原样,因为我们无法知道它们是否已过时。

然后解析我们关心的行并检查包的安装版本。如果安装的版本比关键字版本新,或者根本不再安装,则该关键字被视为已过时。如果已安装的软件包与带关键字的版本是同一版本,则检查已安装的软件包是否仍带关键字。如果已经稳定,则该线路被废弃,否则保留。

#!/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)

这会将新的关键字文件打印到标准输出。 笔记:不要将输出重定向回/etc/portage/package.accept_keywords,否则您将破坏文件并丢失所有内容。

这对于清理关键字文件大有帮助,对于您的其他问题,对文件进行排序,然后检查同一包的多行将有助于解决剩下的大部分问题。

答案3

您知道可以转换目录中的 package.* 文件,对吧?

然后你可以将你的原子组织在几个文件中,例如,在我的系统中我得到了以下内容(好吧,不是真的,我现在不在我的笔记本电脑旁。但你知道这个想法):

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

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

ETC。

我发现这对于帮助我更新文件非常有用。

答案4

这是一个小脚本,用于过滤 /etc/portage/package.* 文件中不再安装的条目。此外,它还会删除已删除条目正上方的所有注释行。 (例如由 autounmask 生成)。如果注释由空行分隔,则只会删除较低的注释。该脚本不会删除重复的条目。

请注意portage 实用程序需要安装 postsync 钩子/etc/portage/postsync.d/q-重新初始化必须激活为了让这个脚本工作。

#!/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 = []

相关内容