将 ppa 软件包降级到之前可用的版本

将 ppa 软件包降级到之前可用的版本

背景是,普通的英特尔 GPU 驱动程序无法执行我的业余编码和一些游戏所需的各种 OpenGL 扩展。所以我必须安装 xorg-edgers,然后它才能正常工作。然而,上周三左右,xorg-edgers 进行了一次更新 - 包含大量软件包 - 并且它严重崩溃;驱动程序锁定并带走整个计算机;需要硬重置。

那么如何降级——选择 PPA 中代表过去某个时间点的软件包版本,而忽略比该时间点更新的版本?

答案1

在日常工作中使用 xorg-edgers ppa 可能是一个非常糟糕的想法。

确实,它可能会为您提供最新的驱动程序,但您也可能会得到无法正常工作的驱动程序。

删除 PPA并降级它所替换的软件包(因此回到官方存储库中可用的软件包),首先安装 ppa-purge:

sudo apt-get install ppa-purge

然后删除 PPA,优雅地降级为官方软件包:

sudo ppa-purge ppaname

这会将您的软件包降级回官方软件包。

其他在 PPA 中但不在官方存储库中的软件包不会被卸载。你应该手动告诉软件包管理器删除它们,例如使用 apt:

sudo apt-get purge packagename

您可以在 Ubuntu 设置中的“软件源”部分找到 ppa 的名称,并在其启动板页面上查看其提供的软件包列表(或者查看 Synaptic 软件包管理器的“来源”部分(如果已安装))。

答案2

我今天遇到了同样的问题,我注意到大约两周前我安装了系统更新,但仍然启用了 ubuntu-x-swat ppa,它有一个新的 nvidia 驱动程序。旧版本没问题,新版本破坏了我的系统(只是轻微的,我花了一段时间才注意到)。

因此,我查看了 /var/log/apt/history.log,以查找我安装的 nvidia 驱动程序包的先前版本号,然后尝试在 /var/cache/apt/archives 中查找该包,通常您会在该位置找到 apt 下载的所有包,但找不到该包。而且,一旦包被新版本取代,ppa 就不会保留其先前版本的包,因此我也无法从那里获取它。

但是,从以前的软件包版本到新版本的差异都保存在所有版本的 ppa 中,并且与原始 tarball 及其 debian 补丁一起,可以撤消新版本的所有更改并获取以前版本的源代码。

我将简要描述必要的步骤:

  • 转到 ppa,找到最新的软件包版本并下载原始 tarball 和(可选)debian 补丁,就我而言,这些是在该页面上找到的:

    https://launchpad.net/~ubuntu-x-swat/+archive/x-updates/+sourcepub/2087970/+listing-archive-extra
    

    原始 tarball 名为:

    nvidia-graphics-drivers_290.10.orig.tar.gz
    

    从 tarball 中生成可构建软件包的 Debian 补丁包括:

    nvidia-graphics-drivers_290.10-0ubuntu1~lucid~xup1.diff.gz
    
  • 最好将它们提取到一个新的空目录中,然后将补丁应用到源树

    ~/nvidia> tar xvzf nvidia-graphics-drivers_290.10.orig.tar.gz
    [...]
    ~/nvidia> gzip -d nvidia-graphics-drivers_290.10-0ubuntu1\~lucid\~xup1.diff.gz
    ~/nvidia> patch -p0 < nvidia-graphics-drivers_290.10-0ubuntu1\~lucid\~xup1.diff
    [...]
    

    修补时你不应该得到任何被拒绝的块。

  • 在同一个 ppa 页面上,您会在“可用差异”部分下找到上一个软件包版本与您正在查看的版本之间的差异。

    对我来说那就是:

    diff from 285.05.09-0ubuntu1~lucid~xup1 to 290.10-0ubuntu1~lucid~xup1
    
  • 下载、提取并反向应用到修补后的原始源:

    ~/nvidia> gzip -d nvidia-graphics-drivers_285.05.09-0ubuntu1\~lucid\~xup1_290.10-0ubuntu1\~lucid\~xup1.diff.gz
    ~/nvidia> patch -R -p0 < nvidia-settings_285.05.09-0ubuntu1\~lucid\~xup1_290.10-0ubuntu1\~lucid\~xup1.diff
    [...]
    
  • 瞧!现在您应该已经准备好了先前版本的源代码树,可以构建软件包了:

    ~/nvidia> mv nvidia-settings-290.10/ nvidia-settings-285.05.09
    ~/nvidia> cd nvidia-settings-285.05.09/
    ~/n/nvidia-settings-285.05.09> dpkg-buildpackage
    
  • 这将为您提供可以使用 dpkg 安装的先前版本的包:

     ~/n/nvidia-settings-285.05.09> cd ..
     ~/nvidia> sudo dpkg -i nvidia-current_285.05.09-0ubuntu1\~lucid\~xup1_amd64.deb
     [...]
    

答案3

将来,如果您使用 synaptic(假设您可以启动到 X),您可以通过突出显示要更改的软件包,然后从菜单中选择“强制版本”,从可用版本中进行选择。从那里您应该能够降级。

答案4

[原始海报]

没什么乐趣,我写了一个脚本来计算差异并执行恢复命令;涉及大约 100 个软件包。遗憾的是我的降级失败了,因为许多软件包不再可用 :(

#!/usr/bin/env python

import sys, getopt, os
from datetime import datetime
datefmt = "%Y-%m-%d %H:%M:%S"

dry_run = True
try:
    opts,args = getopt.getopt(sys.argv[1:],"y")
    if not args:
        raise Exception("no date specified")
    elif len(args) == 1:
        args.append("00:00:00") # default time
    elif len(args) != 2:
        raise Exception("unexpected arguments")
    snapshot = datetime.strptime(" ".join(args),datefmt)
    for opt,_ in opts:
        if opt == "-y":
            dry_run = False
        else:
            raise Exception("unsupported option %s"%opt)
except Exception as e:
    print "error:",e
    print "usage:",sys.argv[0],"[flags] YYYY-MM-DD [HH:MM:SS]"
    print "flags: -y = for real; don\'t just show it, restore it"
    sys.exit(1)

# work out what to do
history = {}
restore = set()
remove = set()
with open("/var/log/dpkg.log","r") as log:
    for line in log:
        date,time,action,line = line.split(None,3)       
        when = datetime.strptime("%s %s"%(date,time),datefmt)
        package,ver = line.strip().split(None,1)
        if when <= snapshot:
            if action in ("upgrade","install"):
                prev_ver,new_ver = ver.split()
                history[package] = new_ver
            elif action == "remove":
                if package in history:
                    del history[package]
                else:
                    print "(cannot remove %s)"%line
        else:
            if action == "install":
                remove.add(package)
            elif action == "upgrade":
                if package in history:
                    restore.add(package)
                elif package not in remove:
                    print "(cannot revert %s)"%line
            elif action == "remove":
                if package in history:
                    restore.add(package)
                elif package in remove:
                    remove.remove(package)
                else:
                    print "(cannot revert %s)"%line

# show what to do
for package in restore:
    print "restore",package,history[package]
for package in remove:
    print "remove",package

# do it
if not dry_run:
    print "======"
    def execute(cmd):
        print cmd
        os.system(cmd)
    #execute("apt-get remove "+" ".join(remove))
    execute("apt-get install "+" ".join("%s=%s"%(package,history[package]) for package in restore))

相关内容