deshacerse de los paquetes instalados accidentalmente

deshacerse de los paquetes instalados accidentalmente

Parece que agregué accidentalmente el ppa system76 para Pop! _OS a mi instalación de Ubuntu 20.04. (lo que es realmente extraño es que no me he dado cuenta de esto...)

Mientras tanto, eliminé el ppa y las entradas en la lista de repositorios que pude encontrar. El sistema está cerca de volver a la normalidad. Sin embargo, creo que me quedan algunos restos, al menos así es como interpreto el siguiente resultado:

$ apt list --installed  | grep pop[0-9]

accountsservice/now 0.6.55-0ubuntu13.2pop0~1605745773~20.04~d9482b1 amd64 [installed,local]
gnome-settings-daemon-common/now 3.36.1-0ubuntu1pop0~1596026424~20.04~8296153 all [installed,local]
gnome-terminal-data/now 3.36.2-1ubuntu1~20.04pop0~1594780610~20.04~8048ed7 all [installed,local]
gnome-terminal/now 3.36.2-1ubuntu1~20.04pop0~1594780610~20.04~8048ed7 amd64 [installed,local]
...

¿Cómo puedo saber ahora a qué repositorio pertenecen y cómo puedo degradar estos paquetes a la versión contenida en los repositorios actualmente activos?

Por ejemplo, veo:

$ apt policy gnome-settings-daemon-common
gnome-settings-daemon-common:
  Installed: 3.36.1-0ubuntu1pop0~1596026424~20.04~8296153
  Candidate: 3.36.1-0ubuntu1pop0~1596026424~20.04~8296153
  Version table:
 *** 3.36.1-0ubuntu1pop0~1596026424~20.04~8296153 100
        100 /var/lib/dpkg/status
     3.36.1-0ubuntu1 500
        500 http://xx.archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages
        500 http://xx.archive.ubuntu.com/ubuntu focal-updates/main i386 Packages
     3.36.0-1ubuntu2 500
        500 http://xx.archive.ubuntu.com/ubuntu focal/main amd64 Packages
        500 http://xx.archive.ubuntu.com/ubuntu focal/main i386 Packages

Y:

$ apt-cache madison  gnome-settings-daemon-common
gnome-settings-daemon-common | 3.36.1-0ubuntu1 | http://xx.archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages
gnome-settings-daemon-common | 3.36.1-0ubuntu1 | http://xx.archive.ubuntu.com/ubuntu focal-updates/main i386 Packages
gnome-settings-daemon-common | 3.36.0-1ubuntu2 | http://xx.archive.ubuntu.com/ubuntu focal/main amd64 Packages
gnome-settings-daemon-common | 3.36.0-1ubuntu2 | http://xx.archive.ubuntu.com/ubuntu focal/main i386 Packages
gnome-settings-daemon | 3.36.0-1ubuntu2 | http://xx.archive.ubuntu.com/ubuntu focal/main Sources
gnome-settings-daemon | 3.36.1-0ubuntu1 | http://xx.archive.ubuntu.com/ubuntu focal-updates/main Sources

Interpreto que esto indica que la versión actualmente instalada no está contenida en los repositorios.

Pero, ¿cómo revierto la versión en el repositorio? Idealmente, me gustaría hacer esto paratodopaquetes...

ACTUALIZARAhora reemplacé manualmente todos los paquetes con los que quería, usando apt-get install package=version. Esto fue una gran molestia porque tuve que buscar la versión que necesitaba apt policypara cada uno de estos y, a veces, reemplazar un montón de paquetes a la vez para satisfacer las dependencias. Aunque mi problema está resuelto, todavía estoy muy interesado en saber cómo se podría realizar dicha limpieza de manera más eficiente.

Respuesta1

Con todo ese tedioso trabajo de limpieza manual, al final también escribí un script de Python que identifica todos los paquetes que no están en los repositorios activos o para qué versiones están instaladas más nuevas que las de los repositorios.

El siguiente código es una solución rápida y no ganará un concurso de belleza, pero para mí funcionó.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Identify all packages that are not in active repositories or for
which newer versions are installed.
"""

import re
import subprocess
from pprint import pprint


def get_packages():
    vers = subprocess.run("apt-show-versions", shell=True, capture_output=True)
    vers = vers.stdout.decode("utf-8").splitlines()
    vers = [y for y in (x.strip() for x in vers) if y]
    not_in_archive = {}
    newer_than_archive = {}
    others = {}
    for pkg in vers:
        p = [x.strip() for x in pkg.split(' ', 2)]
        name = p[0]
        vers = p[1]
        status = p[2] if len(p) == 3 else ''
        if vers == 'not' and status == 'installed':
            continue
        if status == 'uptodate':
            continue

        tmp = {name: {'vers': vers}}
        if status == 'installed: No available version in archive':
            not_in_archive.update(tmp)
        elif status == 'newer than version in archive':
            newer_than_archive.update(tmp)
        else:
            others.update(tmp)
            others[name][status] = status

    return not_in_archive, newer_than_archive, others


def get_version(pkg):
    vers = subprocess.run("apt policy {}".format(pkg),
                          shell=True, capture_output=True)
    vers = vers.stdout.decode("utf-8").splitlines()

    vt = re.compile(r'^ +version table:', re.IGNORECASE)
    stars = re.compile(r'^ \*\*\* *')

    res = []

    while True:
        line = vers.pop(0)
        if vt.match(line):
            break

    for i, line in enumerate(vers):
        if line[:8].strip():
            s = line[:5]
            v = line[5:].split(' ', 1)[0]
            installed = bool(stars.match(s))
        else:
            p, a = line[8:].split(' ', 1)
            res.append({'installed': installed,
                        'version': v,
                        'prio': p,
                        'archive': a})
    return res


if __name__ == '__main__':

    missing, newer, rest = get_packages()

    url = re.compile(r'^https?://', re.IGNORECASE)

    res = {}

    for p in newer:
        v = get_version(p)
        for x in v:
            if url.match(x['archive']):
                res[p] = x['version']
                break

    if missing:
        print("===== packages not in repositories =====")
        print(' '.join(p for p in missing))
        print()

    if rest:
        print("===== packages with other status =====")
        pprint(rest)
        print()

    if res:
        print("===== command to downgrade =====")
        print('sudo apt-get install {}'.format(
            ' '.join('{}={}'.format(p, v) for p, v in res.items())))

Por ejemplo, después de deshabilitar mis PPA darktable y kicad, obtengo

===== packages not in repositories =====
darktable-dbg:amd64 libpng12-0:amd64 zoom:amd64

===== command to downgrade =====
sudo apt-get install darktable:amd64=3.0.1-0ubuntu1 kicad:amd64=5.1.5+dfsg1-2build2 kicad-demos:all=5.1.5+dfsg1-2build2 kicad-doc-en:all=5.1.5+dfsg1-2build2 kicad-footprints:all=5.1.5-1 kicad-libraries:all=5.1.5+dfsg1-2build2 kicad-packages3d:all=5.1.5-1 kicad-symbols:all=5.1.5-1 kicad-templates:all=5.1.5-1

El último comando degradaría los paquetes instalados y los anteriores tendrían que eliminarse con apt-get remove ....

(Entiendo que ppa-purge es el camino a seguir si solo se trata de eliminar un ppa y todo lo demás en el sistema está "limpio", pero puede que no siempre sea así)

información relacionada