Import Debian changes 2.0.5.15-ok1

kylin-system-updater (2.0.5.15-ok1) yangtze; urgency=medium

  * BUG: #140507 : 【2203自适应升级2209】2107升级到2203,再由2203自适应升级至2209-RC6失败
         #145229 : 【2203自适应升级2209】升级过程中出现弹窗认证

  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.14) v101; urgency=medium

  * BUG: #144937 : 【2203自适应升级2209】自动更新下载报错
         #144756 : 【在线更新】开启自动更新,kylin-unattended-upgrades服务状态异常
         #140277 : 【在线更新】更新失败后查看更新历史,显示包名
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.13) v101; urgency=medium

  * BUG: #141330 【在线更新】0521系统在线升级到2203-update1时提示依赖冲突
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.12) v101; urgency=medium

  * BUG: #141197 【在线更新】更新升级安装软件包过程中点击电源后还可以正常关机重启、
         #141309 【在线更新】自动更新失败
         #142560 【2203自适应升级2209】用命令升级完成后,控制面板-关于界面的版本号和系统补丁版本号均为2203
         #143275 【2203自适应升级2209】使用自动更新下载安装命令升级成功后,控制面板-更新界面依然能检测出“系统更新”和“系统基础组件”
         #143274 【2203自适应升级2209】使用自动更新下载安装命令升级成功后,开始菜单缺少部分软件
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.11) v101; urgency=medium

  * BUG: #140451 【2203自适应升级2209】自动更新下载报错
         #139133 【需求12242】【软件商店客户端】软件卸载后未自动清除卸载后的残留
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.10) v101; urgency=medium

  * BUG: #138243 修复优先升级,安装的部分检查出计算依赖错误
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.9) v101; urgency=medium

  * BUG: #138243 修复优先升级,安装的部分检查出计算依赖错误
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.8) v101; urgency=medium

  * BUG: #135190【2203自适应升级2209】系统更新自动下载和安装,内核未更新
   	 #136765 【离线更新】使用U盘源时,控制面板-更新中,“有更新应用时通知”打开无效果
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.7) v101; urgency=medium

  * BUG: #126438 【reopen】【安装器】中文环境下,安装失败或者未授权的错误日志信息显示为英文
        #134470 【设计】安装失败日志语言显示异常
        #127975 【reopen】【云桌面】【在线更新】累计更新成功后,系统版本号以及补丁包版本号未发生变化
        #135020 【在线更新】【PTOF】更新成功后,系统版本号以及补丁包版本号不会变化
        #136748 【在线更新】从安装器安装和更新软件后,本地日志未记录数据,未进行上传。
  * 需求号: # 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.6) v101; urgency=medium

  * BUG: #135270【解决方案|更新升级V1.6】【系统更新客户端】客户端进行自动更新,更新失败后,查看更新历史,历史内容显示为空
         #135227 【解决方案|更新升级V1.6】【更新升级】未连接网络时,更新界面显示“检查更新异常!”,悬浮提示为“无法访问源管理服务器,请稍后再试”
     	 #136093  【解决方案|更新升级V1.6】【更新升级】使用安装器安装deb包,旧的服务没有收集到数据          
         #135372 【解决方案|更新升级V1.6】【系统更新客户端】客户端进行自动更新,更新后,查看更新历史分组名称显示了包名,应该显示软件名称          
         #120948  【在线更新】断网时检测更新失败的文案何设计图不符
  * 需求号: # 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.5) v101; urgency=medium

  * BUG: #120948  【在线更新】断网时检测更新失败的文案何设计图不符
         # 134470 【设计】安装失败日志语言显示异常
  * 需求号: # 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.4) v101; urgency=medium

  * BUG: #134497 【在线更新】打开设置-更新,自动更新按钮默认是“打开”状态
         #134493 【在线更新】【PTOF】更新完成后重启系统,打开设置-更新界面,提示“后台程序未启动”
         #131509 【更新升级】环境破损修复之后,没有自动安装更新包
         #125723 【x100】【系统更新】英文安装操作系统,修改系统语言为中文后,检测更新的提示语仍是英文的
         #120948 【在线更新】断网时检测更新失败的文案何设计图不符
         #134470 【设计】安装失败日志语言显示异常
         #126438 【安装器】中文环境下,安装失败或者未授权的错误日志信息显示为英文
         #122425 【在线更新】设置每隔1min38s弹出通知,在弹出的通知弹窗中点击推迟,1min38s后再次弹出更新通知
  * 需求号: # 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.3) v101; urgency=medium

  * BUG: # 125182 【安装器】在安全中心将应用程序来源检查设置为阻止,双击安装未签名deb包,安装失败但是日志为空
         # 122183 【在线更新】上午8-12点外仍会弹出更新通知 
  * 需求号: 无 
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.2) v101; urgency=medium

  * BUG: #118026 【在线更新】英文环境下,安装和卸载应用时弹出授权界面,提示内容表述方式不一致
         #125182 【安装器】在安全中心将应用程序来源检查设置为阻止,双击安装未签名deb包,安装失败但是日志为空
         #126365 【安装器】英文状态下授权窗口未中文
         #126787 【离线更新】光盘源/U盘源插入被测机器,控制面板-更新界面提示软件源更新失败
         #124430 【在线更新】控制面板-更新中“自动下载和安装更新”按钮未与配置文件进行联动
         #120948 【在线更新】断网时检测更新失败的文案何设计图不符
  * 需求号: 无 
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.5.1) v101; urgency=medium

  * BUG: # 121890 【更新升级】部分应用更新完成后,在“查看历史更新”中查不到数据
         # 123985 【在线更新】系统存在可选更新且在设置中开启了自动下载和安装更新,系统到达定时下载的时间未进行自动下载
         # 110370 【更新升级】 【自动更新】出现一次,自动更新安装服务,将本地安装包地址检测成源地址导致安装报错
  * 需求号: # 12722 【更新升级】系统更新全流程监控
           # 12720 【更新升级】升级环境检测
           # 12721 【更新升级】系统版本号体系
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.4.3) v101; urgency=medium

  * BUG: # 118021 【在线更新】中文环境下,安装和卸载应用时弹出授权界面,提示内容未汉化 
         # 118026 【在线更新】英文环境下,安装和卸载应用时弹出授权界面,提示内容表述方式不一致
         # 122799 【在线更新】配置项中的源地址错误时,客户端重启后打开设置更新,提示后台程序未启动
         # 119435 【更新升级】配置组包json格式错误时,system-updater、自动更新服务均不能启动,更新功能失效,需要增加异常处理机制
         # 121781 【在线更新】中文环境下,静默更新完成后,右上角及侧边栏通知未汉化
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.4.2kord) v101; urgency=medium

  * BUG: # 118021 【在线更新】中文环境下,安装和卸载应用时弹出授权界面,提示内容未汉化 
         # 118026 【在线更新】英文环境下,安装和卸载应用时弹出授权界面,提示内容表述方式不一致
         # 122799 【在线更新】配置项中的源地址错误时,客户端重启后打开设置更新,提示后台程序未启动
         # 119435 【更新升级】配置组包json格式错误时,system-updater、自动更新服务均不能启动,更新功能失效,需要增加异常处理机制
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.3.2kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: 增加系统版本号
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.2kord) v101; urgency=medium

  * BUG:  113951 【电源管理】偶现机器无法通过关机选项或终端命令睡眠、关机或重启(7/10)
  * 需求号: 无
  * 其他改动说明: 增加系统版本号
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.1kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: 增加开机定时下载、关机安装功能,仅合入代码未启用功能
  * 其他改动影响域:系统更新

kylin-system-updater (2.0.0kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: sp3前后端分离: 更新后端+自动更新
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.20kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: 修复计算删除包异常
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.19kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明:
    调整自动更新的开关接口,新增检查更新时候的当前状态显示;优化更新下载阶段增加超时退出功能;
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.18kord) v101; urgency=medium

  * BUG: # 109487 【更新升级】【重启提示】【PTOF】全部更新-备份更新方式,备份完成不继续更新流程
         # 109871 【自适应升级】【系统更新】单个更新回连后提示您的系统已是最新,实际存在未更新的包
         # 108555 【自适应升级】【更新升级】升级系统更新进度在85%卡住,重启控制面板显示英文提示,不显示检测的更新内容,重启后恢复
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.17kord) v101; urgency=medium

  * BUG: #109623 【自适应升级】 【系统更新】光盘源拔出后,还在尝试获取光盘源内容,未自动检测仓库源,可手动恢复
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.16kord) v101; urgency=medium

  * BUG: #108277 【自适应升级】更新升级过程中提示“ukui-kwin-common”缺少依赖
         #109095 【自适应升级】【更新升级】 0326arm版本安装system-updater 1.4.14升级后,系统自适应升级过程超时,控制面板中未结束更新一直停留在安装中的状态
         #108665 【自适应升级】【更新升级】0326arm进行版本升级后提示升级成功,实际有部分包未安装成功
         #109032 【自适应升级】【更新升级】公网不可访问时不能获取更新列表进行更新
         #109036 【自适应升级】【更新升级】 自适应升级后,全部更新中包含缺依赖的包,更新完成后在历史记录中缺依赖的包也显示更新成
         # 105722 【安装器】【龙芯3A5000】安装器安装用户手册deb时提示依赖错误,但是用dpkg命令可以安装
         # 103939 【安装器】安装高版本用户手册后,安装低版本,提示安装失败,dpkg可以安装成功 
         # 100272 【安装器】双击deb包无法安装,日志中提示存在依赖,但通过dpkg可以安装 
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.15kord) v101; urgency=medium

  * BUG: #108555:【自适应升级】【更新升级】升级系统更新进度在85%卡住,重启控制面板显示英文提示,不显示检测的更新内容,重启后恢复 
         #102591:【控制面板|更新】笔记本在20%低电量时更新未有任何特殊提示,建议增加
         #105111:【更新升级】【重启提示】更新完成后出现弹窗提示重启,此时安装另一包(手动安装或者静默更新后台安装包过程中)后点击弹窗中的立即重启,系统不重启也无提示
         #102172:【自适应更新】【系统更新】从sp1 0722自适应升级到sp2 1223版本后,更新设置会恢复默认
         #102104:【自适应更新】【系统更新】从sp1 0722自适应升级到sp2 1223版本后,上次更新时间与更新历史被清空
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.14.1kord) v101; urgency=medium

  * BUG: #108555:【自适应升级】【更新升级】升级系统更新进度在85%卡住,重启控制面板显示英文提示,不显示检测的更新内容,重启后恢复 
         #102591:【控制面板|更新】笔记本在20%低电量时更新未有任何特殊提示,建议增加
         #105111:【更新升级】【重启提示】更新完成后出现弹窗提示重启,此时安装另一包(手动安装或者静默更新后台安装包过程中)后点击弹窗中的立即重启,系统不重启也无提示
         #102172:【自适应更新】【系统更新】从sp1 0722自适应升级到sp2 1223版本后,更新设置会恢复默认
         #102104:【自适应更新】【系统更新】从sp1 0722自适应升级到sp2 1223版本后,上次更新时间与更新历史被清空
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.13.1kord) v101; urgency=medium

  * BUG: #108277:  【自适应升级】更新升级过程中提示“ukui-kwin-common”缺少依赖
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.13kord) v101; urgency=medium

  * BUG: 无 
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.12kord) v101; urgency=medium

  * BUG: #102172: 【自适应更新】【系统更新】从sp1 0722自适应升级到sp2 1223版本后,更新设置会恢复默认
         #102104: 【自适应更新】【系统更新】从sp1 0722自适应升级到sp2 1223版本后,上次更新时间与更新历史被清空
  	     #101852: 【用户手册】【更新升级】用户手册中设置下的更新升级内容与文档不一致
         #104435: 【用例240562】设置-更新界面点击菜单栏-帮助,未直接定位到更新部分
         #105336: 【更新升级】【重启提示】自动更新安装开始和结束的弹窗内容显示不明确  
         #105330 【更新升级】【重启提示】存在源中无所需依赖的包时,弹窗是否进行全盘更新,点击确认后控制面板闪退
         # 105104 【更新升级】【重启提示】带按钮的强弹窗不应该出现在侧边栏,需修改弹窗类型
         # 102465 【系统更新】缺依赖的包,单个更新提示缺依赖后点击全部更新提示更新成功
         # 102175 【自适应更新】【系统更新】升级后,更新一个安装时间较长的包,重启控制面板,此时会一直等待收到安装完成的信号后,才能继续检测更新,影响用户体验
         # 102015 【97888】【系统更新】使用光盘源更新缺依赖的包提示"没有找到需要升级和安装的包",未提示缺依赖
         # 101864 【自适应更新】【自动更新】自动更新下载阶段或者备份前阶段打开控制面板,自动更新服务均不能自动退出 
         # 101852 【用户手册】【更新升级】用户手册中设置下的更新升级内容与文档不一致
         # 101669 【自适应更新】【自动更新】自动更新过滤掉了非正式源,只能获取archive正式源的包,其余源的更新内容不能获取到 
         # 93555 【系统更新】【SP2 UI走查】更新-页面未按最新设计稿实现
         # 90446 【更新升级-需求-9002】【系统更新】点击单个更新后,取消更新按钮未上下对齐 
         # 89824 【更新升级-需求-9002】【系统更新】单个待更新包选择全部更新,拒绝安装后不应该提示"部分更新失败"
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.11.2kord) v101; urgency=medium

  * BUG: #102172: 【自适应更新】【系统更新】从sp1 0722自适应升级到sp2 1223版本后,更新设置会恢复默认
         #102104: 【自适应更新】【系统更新】从sp1 0722自适应升级到sp2 1223版本后,上次更新时间与更新历史被清空
  	     #101852: 【用户手册】【更新升级】用户手册中设置下的更新升级内容与文档不一致
         #104435: 【用例240562】设置-更新界面点击菜单栏-帮助,未直接定位到更新部分
         #105336: 【更新升级】【重启提示】自动更新安装开始和结束的弹窗内容显示不明确  
         #105330 【更新升级】【重启提示】存在源中无所需依赖的包时,弹窗是否进行全盘更新,点击确认后控制面板闪退
         # 105104 【更新升级】【重启提示】带按钮的强弹窗不应该出现在侧边栏,需修改弹窗类型
         # 102465 【系统更新】缺依赖的包,单个更新提示缺依赖后点击全部更新提示更新成功
         # 102175 【自适应更新】【系统更新】升级后,更新一个安装时间较长的包,重启控制面板,此时会一直等待收到安装完成的信号后,才能继续检测更新,影响用户体验
         # 102015 【97888】【系统更新】使用光盘源更新缺依赖的包提示"没有找到需要升级和安装的包",未提示缺依赖
         # 101864 【自适应更新】【自动更新】自动更新下载阶段或者备份前阶段打开控制面板,自动更新服务均不能自动退出 
         # 101852 【用户手册】【更新升级】用户手册中设置下的更新升级内容与文档不一致
         # 101669 【自适应更新】【自动更新】自动更新过滤掉了非正式源,只能获取archive正式源的包,其余源的更新内容不能获取到 
         # 93555 【系统更新】【SP2 UI走查】更新-页面未按最新设计稿实现
         # 90446 【更新升级-需求-9002】【系统更新】点击单个更新后,取消更新按钮未上下对齐 
         # 89824 【更新升级-需求-9002】【系统更新】单个待更新包选择全部更新,拒绝安装后不应该提示"部分更新失败"
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.11kord) v101; urgency=medium

  * BUG: #102172: 【自适应更新】【系统更新】从sp1 0722自适应升级到sp2 1223版本后,更新设置会恢复默认
         #102104: 【自适应更新】【系统更新】从sp1 0722自适应升级到sp2 1223版本后,上次更新时间与更新历史被清空
  	 #101852: 【用户手册】【更新升级】用户手册中设置下的更新升级内容与文档不一致
         #104435: 【用例240562】设置-更新界面点击菜单栏-帮助,未直接定位到更新部分
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.10kord) v101; urgency=medium

  * BUG: #101864: 【自适应更新】【自动更新】自动更新下载阶段或者备份前阶段打开控制面板,自动更新服务均不能自动退出
         #104699:  【自适应更新】【自动更新】自动更新过滤掉了非正式源,只能获取archive正式源的包,其余源的更新内容不能获取到  
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.9kord) v101; urgency=medium

  * BUG: #105336: 【更新升级】【重启提示】自动更新安装开始和结束的弹窗内容显示不明确
         #104275: 【系统更新】自动更新和下载无法使用
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.8kord) v101; urgency=medium

  * BUG: #100272: 【安装器】双击deb包无法安装,日志中提示存在依赖,但通过dpkg可以安装
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.7kord) v101; urgency=medium

  * BUG: #89964: 【更新升级-需求-9002】【系统更新】当前源锁定方案对于私有化部署用户,获取更新包时,不易自由从私有源、公网源之间切换
         #89921:  【更新升级-需求-9002】【系统更新】sources.list中sp1源与私有源共存,私有源中包版本高,实际更新获取的是私有源的包,锁定源未生效
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.6.1kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: 增加重启弹窗
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.6kord) v101; urgency=medium

  * BUG: #102463: 【自动更新】自动更新时源优先级策略未生效,实际获取所有源中最高版本而非按照设置的优先级顺序获取包,导致包版本下载错误
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.5kord) v101; urgency=medium

  * BUG: #102442 【系统更新】【PTOF】系统更新过程重启控制面板,页面展示内容为上次更新时间并持续停留在此页面,此时不能获取更新列表进行更新操作
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.4kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: 增加自适应更新的安装重启提示
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.3kord) v101; urgency=medium

  * BUG: #94805 【更新升级-需求-9002】【系统更新】更新页面上方文字与图标未对齐
         #101985【更新】系统字号为15,点击查看历史设备,左上角“历史更新”字样未随系统字号改变而改变
         #101669【自适应更新】【自动更新】自动更新过滤掉了非正式源,只能获取archive正式源的包,其余源的更新内容不能获取到
         #102069【安装器】无法安装360助手等三方软件且报错不满足依赖,使用dpkg命令可以成功安装且不需要安装其他依赖
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.1.5kord) v101; urgency=medium

  * BUG: #94805 【更新升级-需求-9002】【系统更新】更新页面上方文字与图标未对齐
         #101985【更新】系统字号为15,点击查看历史设备,左上角“历史更新”字样未随系统字号改变而改变
         #101333【控制面板】【更新】系统语言为英文,系统字号为15,系统主题为默认,升级页面自动下载与安装更新悬浮框背景为黑色
         #101669【自适应更新】【自动更新】自动更新过滤掉了非正式源,只能获取archive正式源的包,其余源的更新内容不能获取到
         #102069【安装器】无法安装360助手等三方软件且报错不满足依赖,使用dpkg命令可以成功安装且不需要安装其他依赖
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.4.1.1kord) v101; urgency=medium

  * BUG: #101309【控制面板】【更新】更新页面图标和检查更新时的动画丢失
         #89824【更新升级-需求-9002】【系统更新】单个待更新包选择全部更新,拒绝安装后不应该提示"部分更新失败";且更新失败后应该出现检测更新的按钮
         #100839【控制面板|更新】最大字号,一个账户系统语言为英文,一个为中文,英文账户的控制面板-更新界面显示不全
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新插件

kylin-system-updater (1.4.0kord) v101; urgency=medium

  * BUG: #99496【系统更新】【英文】【UI布局】更新界面提示信息较长时,页面格式变成左右拖动框与其他界面格式不符
         #98774【用例104332】【升级】更新历史窗口,左侧名称显示不全
         #97888【离线更新】【PTOF】控制面板识别不到光盘源中的包
         #97116【控制面板|更新】更新界面检测按钮显示不全
         #95290【系统更新】系统语言为英文时,打开控制面板-更新升级页面,再切换到字体页面,将字号切换到15号,返回升级页面,details显示不全
         #94804【更新升级-需求-9002】【系统更新】应用后的更新按钮内“更新”字样未居中
         #93555【系统更新】【SP2 UI走查】更新-页面未按最新设计稿实现
         #85618【内测】【摸底测试】【更新升级】上次更新提示词错误
         #85312【内测】【摸底测试】【更新升级】更新失败提示字不合理
         #85269【内测】【控制面板|更新】英文模式下检查更新文字显示不全
  * 需求号: 无
  * 其他改动说明: 修改frame边际,保证在显示器不同缩放情况下仍然能够正常显示
  * 其他改动影响域:系统更新插件

kylin-system-updater (1.3.5kord) v101; urgency=medium

  * BUG: #100356【试用模式】点击设置的更新,控制面板闪退(安装完系统后打开不会闪退)
         #93390 【控制面板|更新】打开控制面板切换深色主题,不关闭控制面板的前提下更新部分文字未反白
         #91169 【更新升级-需求-9002】【系统更新】开启通知可更新应用后不弹窗通知可更新
         #99894 【安装器】安装失败-不满足依赖的提示未汉化
         #97120 【控制面板|更新】软件源更新失败提示语未汉化
         #99500 【系统更新】【英文】【UI布局】更新界面,update settings与下方标题未对齐
         #99498 【系统更新】【英文】【UI布局】更新界面,自动更新的第二行介绍显示不全
  * 需求号: 无
  * 其他改动说明: 修改部分英文表述和中文翻译
  * 其他改动影响域:系统更新插件

kylin-system-updater (1.3.4kord) v101; urgency=medium

  * BUG: #100356【试用模式】点击设置的更新,控制面板闪退(安装完系统后打开不会闪退)
         #93390 【控制面板|更新】打开控制面板切换深色主题,不关闭控制面板的前提下更新部分文字未反白
         #91169 【更新升级-需求-9002】【系统更新】开启通知可更新应用后不弹窗通知可更新
         #99894 【安装器】安装失败-不满足依赖的提示未汉化
         #97120 【控制面板|更新】软件源更新失败提示语未汉化
         #99500 【系统更新】【英文】【UI布局】更新界面,update settings与下方标题未对齐
         #99498 【系统更新】【英文】【UI布局】更新界面,自动更新的第二行介绍显示不全
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新插件

kylin-system-updater (1.3.2.1kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: 增加运行依赖python3-distro-info
  * 其他改动影响域:系统更新插件

kylin-system-updater (1.3.2kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: 修改与旧版本控制面板的冲突
  * 其他改动影响域:系统更新插件

kylin-system-updater (1.3.1kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: 修复点击全部升级后执行更新检测的问题
  * 其他改动影响域:系统更新全部升级

kylin-system-updater (1.3.0kord) v101; urgency=medium

  * BUG:  #97525:  【安装器】安装器无法安装降级的deb包,终端dpkg可以安装
          #85685:  【更新升级】中断自动备份更新过程后,无法再进行自动备份更新
          #97859:  【安装器】安装软件包失败的输出日志不够详细
  * 需求号: 无
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.18.5kord) v101; urgency=medium

  * BUG:  #97525:  【安装器】安装器无法安装降级的deb包,终端dpkg可以安装
  * 需求号: 无
  * 其他改动说明: 更改logrotate.d/unattended-upgrades
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.18.4kord) v101; urgency=medium

  * BUG:  #97525:  【安装器】安装器无法安装降级的deb包,终端dpkg可以安装
  * 需求号: 无
  * 其他改动说明:
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.18.3kord) v101; urgency=medium

  * BUG:  #97525:  【安装器】安装器无法安装降级的deb包,终端dpkg可以安装
  * 需求号: 无
  * 其他改动说明: 合并plugin_dev改动,测试
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.18.2kord) v101; urgency=medium

  * BUG:
  * 需求号: 无
  * 其他改动说明: 合并plugin_dev改动,测试
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.18.1kord) v101; urgency=medium

  * BUG:  
  * 需求号: 无
  * 其他改动说明: 
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.18kord) v101; urgency=medium

  * BUG:  #95760:  【更新升级-需求-9002】【系统更新】控制面板更新提示更新失败-软件包错误,实际已经安装成功
  * 需求号: 无
  * 其他改动说明: 修改大数据采集后端dbus接口
  * 其他改动影响域:系统更新多维数据采集

kylin-system-updater (1.2.17.3kord) v101; urgency=medium

  * BUG:  #95760:  【更新升级-需求-9002】【系统更新】控制面板更新提示更新失败-软件包错误,实际已经安装成功
  * 需求号: 无
  * 其他改动说明: 修改大数据采集后端dbus接口
  * 其他改动影响域:系统更新多维数据采集

kylin-system-updater (1.2.17.2kord) v101; urgency=medium

  * BUG:  无
  * 需求号: 无
  * 其他改动说明: 更改过滤属性获取不正确;新增大数据采集后端dbus接口
  * 其他改动影响域:系统更新过滤与多维数据采集

kylin-system-updater (1.2.17.1kord) v101; urgency=medium

  * BUG:  无
  * 需求号: 无
  * 其他改动说明:无
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.17kord) v101; urgency=medium

  * BUG:  #89964: 【系统更新】当前源锁定方案对于私有化部署用户,获取更新包时,不易自由从私有源、公网源之间切换
          #89921: 【系统更新】sources.list中sp1源与私有源共存,私有源中包版本高,实际更新获取的是私有源的包,锁定源未生效
  * 需求号: 无
  * 其他改动说明:无
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.16.3kord) v101; urgency=medium

  * BUG:  #89964: 【系统更新】当前源锁定方案对于私有化部署用户,获取更新包时,不易自由从私有源、公网源之间切换
          #89921: 【系统更新】sources.list中sp1源与私有源共存,私有源中包版本高,实际更新获取的是私有源的包,锁定源未生效
  * 需求号: 无
  * 其他改动说明:无
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.16.1kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明:无
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.15.3kord) v101; urgency=medium

  * BUG:  #93483: 【在线更新】控制面板识别不出ftp源中的包
          #93484: 【用例104578】单个更新提示不能关机,全部更新能关机
          #93312: 【系统升级】详情中的下载大小与实际不符
          #89819: 【系统更新】全部更新和单个更新开始过程几秒钟,网速固定是100B/S未显示实际网速;下载完成包后更新,显示0B/0B,建议改为下载完成
          #89544: 【系统更新】大包(4g)更新包,在控制面板显示下载大小为0KB,单个更新后不显示下载中而是安装中
  * 需求号: 无
  * 其他改动说明:无
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.15.1kord) v101; urgency=medium

  * BUG:  #90667: 【系统更新】系统更新-单个更新,下载过程中取消按钮不应该被屏蔽
          #90446: 【系统更新】点击单个更新后,取消更新按钮未上下对齐
          #89817: 【系统更新】控制面板-更新界面未进行英化
          #89530: 【系统更新】取消单个更新后还会弹出是否安装的窗口
          #85487: 【更新升级】系统语言为英文时,Check Update和back显示不全
          #85180: 【更新升级】提示网络异常后仍显示正在下载并安装更新,且全部更新按钮可点击
          #69831: 【系统升级】点击全部更新后,软件包更新失败,控制面板中仍显示正在下载和更新
          #85315: 【更新升级】更新成功后仍显示正在更新
          #90077: 【系统更新】全部更新过程中,更新软件源进度是11% 91% 92%,不是线性增长
  * 需求号: 无
  * 其他改动说明:无
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.15kord) v101; urgency=medium

  * BUG:  #90667: 【系统更新】系统更新-单个更新,下载过程中取消按钮不应该被屏蔽
          #90446: 【系统更新】点击单个更新后,取消更新按钮未上下对齐
          #89817: 【系统更新】控制面板-更新界面未进行英化
          #89530: 【系统更新】取消单个更新后还会弹出是否安装的窗口
          #85487: 【更新升级】系统语言为英文时,Check Update和back显示不全
          #85180: 【更新升级】提示网络异常后仍显示正在下载并安装更新,且全部更新按钮可点击
          #69831: 【系统升级】点击全部更新后,软件包更新失败,控制面板中仍显示正在下载和更新
          #85315: 【更新升级】更新成功后仍显示正在更新
          #90077: 【系统更新】全部更新过程中,更新软件源进度是11% 91% 92%,不是线性增长
  * 需求号: 无
  * 其他改动说明:无
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.14.1kord) v101; urgency=medium

  * BUG:  #90667: 【系统更新】系统更新-单个更新,下载过程中取消按钮不应该被屏蔽
          #90446: 【系统更新】点击单个更新后,取消更新按钮未上下对齐
          #89817: 【系统更新】控制面板-更新界面未进行英化
          #89530: 【系统更新】取消单个更新后还会弹出是否安装的窗口
          #85487: 【更新升级】系统语言为英文时,Check Update和back显示不全
          #85180: 【更新升级】提示网络异常后仍显示正在下载并安装更新,且全部更新按钮可点击
          #69831: 【系统升级】点击全部更新后,软件包更新失败,控制面板中仍显示正在下载和更新
          #85315: 【更新升级】更新成功后仍显示正在更新
          #90077: 【系统更新】全部更新过程中,更新软件源进度是11% 91% 92%,不是线性增长
  * 需求号: 无
  * 其他改动说明:无
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.13.3kord) v101; urgency=medium

  * BUG:  #93675: 【系统更新】点击单个更新,准备更新过程中点击取消,仍然可以更新应用
          #93668: 【系统更新】点击单个更新,下载过程中点击取消,出现安装中字样再提示本次更新已取消
          #93320: 【系统升级】更新过程中退出控制面板,再打开进入升级无法看到正在更新的应用
          #93309: 【系统升级】更新过程中,取消按钮置灰无法点击
          #90660: 【系统更新】第一次装机,打开控制面板进行系统更新,备份完成后提示备份完成不继续更新流程
          #90455: 【系统更新】更新前的备份过程中退出控制面板,再次打开控制面板选择备份更新界面卡在开始备份,正在获取进度,等待上次备份完成才能恢复
          #89819: 【系统更新】全部更新和单个更新开始过程几秒钟,网速固定是100B/S未显示实际网速;下载完成包后更新,显示0B/0B,建议改为下载完成
          #89527: 【系统更新】单个更新失败后,点击全部更新后取消,失败的单个更新后方出现取消更新的按键
          #89517: 【系统更新】备份还原工具运行过程中,进行"备份及更新"提示备份还原工具正在进行其他操作,此时点击单个更新实际开始全部更新
          #89449: 【系统更新】全部更新过程中,关闭控制面板后再次打开,一直卡在更新源界面不能检测出待更新的包
          #93680: 【系统更新】点击全部更新,有安装弹窗的应用点击拒绝后,操作记录显示应用都安装失败,实际无安装弹窗的应用安装成功
          #93671: 【系统更新】系统字号为15时,安装详情应用名称显示不全
          #92987: 【控制面板】英文状态下,控制面板中更新未英化
          #91435: 【用例87055】设置系统语言为英文,部分显示仍为中文
          #91305: 【控制面板|更新】英文模式更新界面英化未完全
          #94029: 【控制面板】通知界面缺少"电源管理器、系统更新"设置项
  * 需求号: 无
  * 其他改动说明:无
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.13.2kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明:更新源过滤机制,取消服务器下发允许的源列表
  * 其他改动影响域:系统更新源过滤

kylin-system-updater (1.2.13.1kord) v101; urgency=medium

  * BUG: #89461:【系统更新】全部更新过程中,点击详情无更新进度;安装过程中点击详情不会显示安装进度
  *      #93309:【系统升级】更新过程中,取消按钮置灰无法点击
  *      #89535:【更新升级-需求-9002】【系统更新】全部更新-备份及更新过程中需屏蔽单个更新按键
  * 需求号: 无
  * 其他改动说明:增加获取破损包的依赖错误描述,状态保留增加取消功能
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.13kord) v101; urgency=medium

  * BUG: #89461:【系统更新】全部更新过程中,点击详情无更新进度;安装过程中点击详情不会显示安装进度
  *      #93309:【系统升级】更新过程中,取消按钮置灰无法点击
  *      #89535:【更新升级-需求-9002】【系统更新】全部更新-备份及更新过程中需屏蔽单个更新按键
  * 需求号: 无
  * 其他改动说明:增加获取破损包的依赖错误描述,状态保留增加取消功能
  * 其他改动影响域:系统更新

kylin-system-updater (1.2.12.2kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明:增加获取破损包的依赖错误描述,状态保留增加取消功能,优化静态变量
  * 其他改动影响域: 

kylin-system-updater (1.2.12.1kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明:增加获取破损包的依赖错误描述,状态保留增加取消功能,优化静态变量
  * 其他改动影响域: 

kylin-system-updater (1.2.12kord) v101; urgency=medium

  * BUG: #89818:【系统更新】将系统字体调整为最大,控制面板-更新界面"您的系统已是最新未跟随改变";且界面显示不全
  *      #89554:【系统更新】控制面板-更新界面没有兼容ukui3.1
  *      #89817:【系统更新】控制面板-更新界面未进行汉化
  * 需求号: 无
  * 其他改动说明:增加自主升级功能
  * 其他改动影响域: 影响更新检测功能,在更新检测时将更新系统升级包本身

unknown (unknown1) unknown; urgency=unknown

  *      #89810:【系统更新】全部更新缺少错误原因提示,且取消全部下载建议提示下载取消。将依赖冲突的包以虚包形式进行全部更新,提示部分更新失败;空间少于备份空间或者安装包的空间,全部更新后提示部分更新失败。都未展示实际原因
  * 需求号: 无
  * 其他改动说明:增加自主升级功能,优化进度显示保持功能
  * 其他改动影响域: 影响更新检测功能,在更新检测时将更新系统升级包本身

kylin-system-updater (1.2.9kord) v101; urgency=medium

  * BUG: bug#91191,bug#90533,bug#91103,bug#90454,bug#89871
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:system-updater.conf文件配置;fix升级版本号记录不正确;修复高优先级低版本包被过滤的问题;安装异常时开机进行修复;
  * 影响域: 系统升级

kylin-system-updater (1.2.8.1kord) v101; urgency=medium

  * BUG: bug#91191,bug#90533,bug#91103,bug#90454
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:system-updater.conf文件配置;fix升级版本号记录不正确;修复高优先级低版本包被过滤的问题;安装异常时开机进行修复;
  * 影响域: 系统升级

kylin-system-updater (1.2.7.4kord) v101; urgency=medium

  * BUG: bug#91191,bug#90533
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:system-updater.conf文件配置;fix升级版本号记录不正确;修复高优先级低版本包被过滤的问题;下载包时可以点击取消按钮;
  * 影响域: 系统升级

kylin-system-updater (1.2.7.3kord) v101; urgency=medium

  * BUG: bug#91191
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:system-updater.conf文件配置;fix升级版本号记录不正确;
  * 影响域: 系统升级

kylin-system-updater (1.2.7.2kord) v101; urgency=medium

  * BUG:
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:升级插件UI修复;添加修复功能;修复安装时preinst报错的问题
  * 影响域: 系统升级

kylin-system-updater (1.2.7.1kord) v101; urgency=medium

  * BUG:
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:升级插件UI修复;
  * 影响域: 系统升级

kylin-system-updater (1.2.7kord) v101; urgency=medium

  * BUG: 
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:解决so包含导致的升级问题;增加源优先级的判断,优化优先级问题;规范文件安装路径;
  * 影响域: 系统升级

kylin-system-updater (1.2.6.3kord) v101; urgency=medium

  * BUG: 
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:解决so包含导致的升级问题;增加源优先级的判断;规范文件安装路径;
  * 影响域: 系统升级

kylin-system-updater (1.2.6.1kord) v101; urgency=medium

  * BUG: 
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:解决so包含导致的升级问题
  * 影响域: 系统升级

kylin-system-updater (1.2.6kord) v101; urgency=medium

  * BUG: bug#90102,bug#89338,bug#89792,bug#85318,bug#85325,bug#89813
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:增加调整候选版本的选项,限速功能调整,分组包记录失败修复,修复全盘修复逻辑错误问题,优化逻辑
  * 影响域: 系统升级

kylin-system-updater (1.2.5.2kord) v101; urgency=medium

  * BUG: bug#90102,bug#89338,bug#89792,bug#85318,bug#85325,bug#89813
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:增加调整候选版本的选项,限速功能调整,分组包记录失败修复,修复全盘修复逻辑错误问题,
  * 影响域: 系统升级

kylin-system-updater (1.2.5.1kord) v101; urgency=medium

  * BUG: bug#90102,bug#89338,bug#89792,bug#85318,bug#85325
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:增加调整候选版本的选项,限速功能调整,分组包记录失败修复.
  * 影响域: 系统升级

kylin-system-updater (1.2.5kord) v101; urgency=medium

  * BUG: bug#89045,bug#89464,bug#89530,bug#89471,bug#89575
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:修复升级记录不全;取消启动自动update;修改接口文档;解决出现升级准备失败的问题;为自动更新提供白名单,插件bug修复
  * 影响域: 系统升级

kylin-system-updater (1.2.4.1kord) v101; urgency=medium

  * BUG: bug#89045,bug#89464
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明:修复升级记录不全;取消启动自动update;修改接口文档;解决出现升级准备失败的问题;为自动更新提供白名单.
  * 影响域: 系统升级

kylin-system-updater (1.2.4kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明: 修复安装更新包kylin-update-desktop-config时报错的问题,优化修复冲突更新时未收起部分更新列表,源过滤速度优化
  * 影响域: 系统升级

kylin-system-updater (1.2.3.5kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明: 修复安装更新包kylin-update-desktop-config时报错的问题
  * 影响域: 系统升级

kylin-system-updater (1.2.2kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 9002
  * 需求:1.升级依赖修复机制,减小第三方软件对系统更新的影响;2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
  * 其他改动说明: 完善升级功能,调整超时时间为20min
  * 影响域: 系统升级

kylin-system-updater (1.2.0.8.1kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: 完善升级功能,源过滤优化,合并系统升级控制面板插件
  * 影响域: 系统升级

kylin-system-updater (1.1.9kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: 修改词条、国际化、修改编译生成的文件的追踪、增加log日志并修改颜色、取消安装刷新数据库
  * 影响域: 系统升级

kylin-system-updater (1.1.7kord) v101; urgency=medium

  * BUG: 无
  * 需求号: 无
  * 其他改动说明: 更改数据库插入格式,判断升级方式,增加刷新更新时间的信号,+ ws的修改
  * 影响域: 重构系统更新器中数据库部分

kylin-system-updater (1.1.6kord) v101; urgency=medium

  * 升级禁止关机

kylin-system-updater (1.1.4kord) v101; urgency=medium

  * 代码优化,新增接口.
  * 修改数据库结构.

kylin-system-updater (1.1.2kord) v101; urgency=medium

  * 增加数据库接口 .

kylin-system-updater (1.1.1kord) v101; urgency=medium

  * add database .

kylin-system-updater (1.0.4kord) v101; urgency=medium

  * 重新编包,修复依赖,去除无用文件, 修改版本号

kylin-system-updater (2.0.5.4.1) v101; urgency=medium

  * BUG: # 无
  * 需求号: #15034  【更新升级】更新历史中新增自动更新结果显示
            #15107】【更新升级】自动更新数据上报
            #15089】【更新升级】【P2P】更新策略下发支持P2P配置内容下发(IP)
            #15109】【更新升级】更新历史中增加历史更新内容日志显示
            #15027】【更新升级】更新通知弹窗界面优化
            #14380】【更新】搜索只能搜索包的全名,不能模糊搜索,也不能搜索别的字段 
  * 其他改动说明: 无
  * 其他改动影响域:系统更新

kylin-system-updater (1:20.04.9) v101; urgency=medium

  * for v10sp1

kylin-system-updater (1:20.04.9) focal; urgency=medium

  * Remove ubuntu-support-status as the term support can be confusing and the
    Supported field has been removed from Launchpad packages. (LP: #1873362)
  * Add ubuntu-security-status - a tool for displaying information about
    packages installed and the kind of updates which they may or may not
    receive. (LP: #1873362)

update-manager (1:20.04.9) focal; urgency=medium

  * Remove ubuntu-support-status as the term support can be confusing and the
    Supported field has been removed from Launchpad packages. (LP: #1873362)
  * Add ubuntu-security-status - a tool for displaying information about
    packages installed and the kind of updates which they may or may not
    receive. (LP: #1873362)

update-manager (1:20.04.7) focal; urgency=medium

  [ Marcus Tomlinson ]
  * Show progress of snap updates (LP: #1871099).
  * Display an error message when snap updates fail (LP: #1871100).

  [ Łukasz 'sil2100' Zemczak ]
  * Adjust dates in hwe-support-status for focal.

update-manager (1:20.04.6) focal; urgency=medium

  * deb2snap: Don't replace debs that were manually installed via
    another package (LP: #1872958).

update-manager (1:20.04.5) focal; urgency=medium

  * Fix TypeError crash in update() (LP: #1871490).

update-manager (1:20.04.4) focal; urgency=medium

  * Fix pycodestyle and pyflakes autopkgtests.

update-manager (1:20.04.3) focal; urgency=medium

  [ Gunnar Hjalmarsson ]
  * po/POTFILES.in:
    Add UpdateManager/backend/__init__.py, so the new translatable
    strings get included in the translation template (LP: #1868409).

  [ Brian Murray ]
  * UpdateManager/UpdateManager.py: Do not offer to upgrade systems running on
    an i386 host architecture to another release. (LP: #1845690)

update-manager (1:20.04.2) focal; urgency=medium

  * UpdateManager/backend/__init__.py: once apt upgrade completes, use the
    deb2snap.json file from ubuntu-release-upgrader to perform snap updates.
    (LP: #1868409)

update-manager (1:20.04.1) focal; urgency=medium

  * UpdateManager/Core/UpdateList.py: remove unused import of subprocess.
  * janitor/plugincore/manager.py: replace basestring abstract type.

update-manager (1:19.04.10) focal; urgency=medium

  * UpdateManager/Core/UpdateList.py: Use utils.get_dist() instead of
    platform.dist() to find codename, the latter was removed in Python 3.8

update-manager (1:19.04.9) focal; urgency=medium

  * tests: Handle the rename of the pep8 tool to pycodestyle.

update-manager (1:19.04.8) eoan; urgency=medium

  * data/gtkbuilder/UpdateManager.ui: enforce icon size for download size icon
    so it's consistent with the other status icons. (LP: #1790134)

update-manager (1:19.04.7) eoan; urgency=medium

  * Fix E117 over idented code

update-manager (1:19.04.5) disco; urgency=medium

  * UpdateManager/Core/utils.py: when testing to see if a url is downloadable
    support https in addition to http and ftp. (LP: #1823410)
  * debian/tests/control: really use pyflakes3 instead of pyflakes,
    additionally resolve pyflakes3 errors.

update-manager (1:19.04.4) disco; urgency=medium

  [ Colin Watson ]
  * Use the source version to generate changelog URIs, not the binary
    version (LP: #655917).

update-manager (1:19.04.3) disco; urgency=medium

  * Add gnome-shell as the first alternate for the polkit-1-auth-agent
    dependency to allow policykit-1-gnome to be demoted to universe

update-manager (1:19.04.2) disco; urgency=medium

  * UpdateManager/Core/MetaRelease.py: set prompt in MetaReleaseCore so that
    do-release-upgrade can provide more informative error messages.
    (LP: #1798618, LP: #1795024)

update-manager (1:19.04.1) disco; urgency=medium

  * Do not show the livepatch reminder if update-manager is running
    on a distribution without software-properties-gtk. (LP: #1805118)  

update-manager (1:18.10.10) cosmic; urgency=medium

  * Stop lazy import of InstallBackends.
    Lazy imports made update-manager crash when an update-manager
    update changed the backend API and an updated incompatible backend
    was loaded to the not updated running update-manager process. (LP: #1795898)
  * Cancel transaction on exit only when Cancel button is active.
    Also ignore exception when cancellation fails. (LP: #1790670)

update-manager (1:18.10.9) cosmic; urgency=medium

  * Allow unselecting updates and performing only removals (LP: #1792320)
  * Stop trying apt_pkg.pkgsystem_(un)lock(), as a normal user it always fails
    (LP: #1795387)
  * Keep or delete packages after looping over all of them.
    This prevents the resolver from changing the packages in the loop resulting
    in not keeping some phased packages back from being upgraded. (LP: #1072136)
  * Fix PEP 8 warnings (LP: #1795384)
    Also ignore "W503 line break before binary operator" because it will
    become the best practice

update-manager (1:18.10.8) cosmic; urgency=medium

  * Print transaction error and let the user try again applying updates
    (LP: #1317164)
  * Don't ask backend to do package operations aready done.
    Aptdaemon cancels the transaction when asked to remove packages already
    removed which results the failure being shown to the user. This
    is unnecessary as update-manager can just filter the package operations to
    be done using a fresh cache and decrease the likelyhood of hitting
    a race condition where packages to be removed are already removed.
    (LP: #1791931)

update-manager (1:18.10.7) cosmic; urgency=medium

  * Fix PEP8 regression from 18.10.4 to allow autopkgtest to pass
  * Fix unused import of subprocess in Dialogs.py

update-manager (1:18.10.6) cosmic; urgency=medium

  * debian/control:
    - Build-Depends on python3-distro-info

update-manager (1:18.10.5) cosmic; urgency=medium

  * Add a reminder to enable Livepatch (LP: #1787553).

update-manager (1:18.10.4) cosmic; urgency=medium

  [ Łukasz 'sil2100' Zemczak ]
  * Ignore Prompt=lts for non-LTS series. This way if a user is on a non-LTS
    and has Prompt=lts, he/she will be upgraded to the next supported series
    until finally reaching an LTS. (LP: #1783328)

update-manager (1:18.10.3) cosmic; urgency=medium

  * Add support for HTTPS proxies; this breaks UpdateManager.Core.utils.init_proxy()
    API - the return value is now a dict, rather than a string (LP: #1771914).

update-manager (1:18.10.2) cosmic; urgency=medium

  * Fix my spelling mistake in the previous upload. Oops.

update-manager (1:18.10.1) cosmic; urgency=medium

  * Block style context changed signal while enforcing the main window's
    constant size. Thanks to Thomas Waldmann and Sebastien Bacher for the
    initial analysis of this bug. (LP: #1637180)

update-manager (1:18.04.11) bionic; urgency=medium

  * Add Appstream metadata with compulsory_for_desktop fields to prevent
    the accidental uninstallation of ubuntu-desktop in GNOME Software.
    ubuntu-desktop depends on update-manager.
  * Build-Depend on dh-python
  * Update translation template

update-manager (1:18.04.10) bionic; urgency=medium

  * Support package removals in install backends and really remove packages
    (LP: #1624644, #1675079)

update-manager (1:18.04.9) bionic; urgency=medium

  * Keep PEP 8 checks happy

update-manager (1:18.04.8) bionic; urgency=medium

  * Offer removal of unused autoremovable kernel packages
    (LP: #1624644, #1675079)

update-manager (1:18.04.7) bionic; urgency=medium

  * Comment out the KDE frontend in debian/control so we can remove pykde4
    from the archive (LP: #1745741).

update-manager (1:18.04.6) bionic; urgency=medium

  * Use HTTPS for changelogs.ubuntu.com (LP: #1744318)

update-manager (1:18.04.5) bionic; urgency=medium

  * Drop the update-manager-text package and code as it has been broken for a
    long time and it wasn't used by many people. (LP: #1385524)

update-manager (1:18.04.4) bionic; urgency=medium

  [ Balint Reczey ]
  * Place .keep files in empty directories to keep them when converting the
    repo to git
  * Call do-release-upgrade without pkexec and depend on a version which
    raises privileges itself (LP: #1748509)

  [ Jeremy Bicha ]
  * update-manager: Depend on libgtk3-perl for debconf's GNOME backend.
    Drop previous Recommends on libgtk2-perl. (LP: #1607929)

update-manager (1:18.04.3) bionic; urgency=medium

  * ubuntu-support-status: use component to differentiate packages
    supported by the community and packages supported by Canonical.
    (LP: #1574670)

update-manager (1:18.04.2) bionic; urgency=medium

  * Build from bazaar repository to keep empty dirs in the source package
  * Break long comment to keep PEP 8 test happy

update-manager (1:18.04.1) bionic; urgency=medium

  [ Jean-Baptiste Lallement ]
  * UpdateManager/Dialogs.py: Workaround restricted access to GUI applications
    by user root under wayland to start do-release-upgrade in graphical mode
    (LP: #1732185)

update-manager (1:17.10.11) artful; urgency=medium

  * UpdateManager/UpdatesAvailable.py: Also mention using COMPRESS=xz in
    intramfs.conf to free more space in /boot.

update-manager (1:17.10.10) artful; urgency=medium

  * UpdateManager/UpdatesAvailable.py: Provide instructions when mount points
    have insufficient free space for the upgrade to complete. (LP: #1477455)

update-manager (1:17.10.9) artful; urgency=medium

  [ Łukasz 'sil2100' Zemczak ]
  * test_update_origin.py: fix the extended origin matcher test as it was
    making wrong assumptions, not checking if packages actually had ANY package
    in -security. This should fix the current autopkgtest failures.

  [ Brian Murray ]
  * test_update_origin.py: fix some typos.

update-manager (1:17.10.8) artful; urgency=medium

  * UpdateManager/Dialogs.py: use a variable instead of hard coding 1 to
    allow the translation of the message, thanks to Andrea Azzarone.
    (LP: #1714489)

update-manager (1:17.10.7) artful; urgency=medium

  * Show status of Canonical's Livepatch service in update-manager dialog
    window, thanks to Andrea Azzarone. (LP: #1712591)

update-manager (1:17.10.6) artful; urgency=medium

  *  UpdateManager.py: Workaround a crash when calling software-properties-gtk
     by not using --toplevel under wayland (LP: #1703365)

update-manager (1:17.10.5) artful; urgency=medium

  * test_update_origin.py: This does not need to be architecture specific so
    just set the arch to amd64 like test_update_list.py.
  * test_utils.py: mock /proc/net/tcp and processes in proc so that we are
    testing the code and not the system under test.

update-manager (1:17.10.4) artful; urgency=medium

  * UpdateManager/Core/UpdateList.py: Instead of trying to print an error
    when trying to find the desktop file log it. (LP: #1428297)

update-manager (1:17.10.3) artful; urgency=medium

  * Resolve a multitude of test failures, pep8 and pyflakes issues.

update-manager (1:17.10.2) artful; urgency=medium

  * Recommend libgtk2-perl be installed so we have a working debconf frontend.
    (LP: #1607929)

update-manager (1:17.10.1) artful; urgency=medium

  [ Steve Langasek ]
  * ubuntu-support-status: instead of checking the Release timestamp in
    the releases file for every single package on the system, get the
    release date from distro-info-data because it will always be the same.
    This speeds up the script by > 50% in testing.

  [ Brian Murray ]
  * update-manager: Clarify that the "-d" switch is only for upgrading from
    the latest supported release to the development release, not any release.
    (LP: #1700829)
  * Remove --sandbox (aufs support) as it has been broken for some time and
    was rather unused. (LP: #1605259)

update-manager (1:17.04.3) zesty; urgency=medium

  * Use a 64 bit integer for launch-time instead of a 32 bit one which won't
    work someday. (LP: #1654008)

update-manager (1:17.04.2) zesty; urgency=medium

  [ Jeremy Bicha ]
  * Update alternate dependencies for policykit-1-gnome:
    - Add virtual polkit-1-auth-agent
    - Replace non-existant policykit-1-kde with polkit-kde-agent-1
    - Replace razorqt-policykit-agent with lxqt-policykit
      (since lxqt is the replacement for razorqt)

  [ Manzur Mukhitdinov ]
  * UpdateManager/Core/MetaRelease.py:
    - Add a clearer error message when a network failure occurs

  [ Brian Murray ]
  * UpdateManager/Dialogs.py:
    - Remove misleading ellipsis in “Restart Now” action button. Thanks to
      Adolfo Jayme for the change.  (LP: #1568368)

  [ Steve Langasek ]
  * Drop estimate_kernel_size_in_boot() from UpdateManager/Core/utils.py; this
    was only used in ubuntu-release-upgrader so the code has now moved there
    (with code fixes).  Ensure upgrade ordering with Breaks: on older
    python3-distupgrade.  LP: #1646222.

update-manager (1:17.04.1) zesty; urgency=medium

  * tests/test_hwe_support_status.py: Resolve issues with the test.
  * data/gtkbuilder/UpdateManager.ui: Set a minimum content height of 80px for
    the technical description scrolled window. This was the default height
    gtk3widgets used in GTK versions prior to 3.20. Thanks to Martin Wimpress
    for the fix. (LP: #1623856)

update-manager (1:16.10.7) yakkety; urgency=medium

  * UpdateManager/Core/MyCache.py: Gracefully handle absence of Launchpadlib
    module.
  * Lower python3-launchpadlib Depends: to a Suggests:, to avoid pulling it
    into "standard" priority. Retrieving PPA changelogs is more of a niche
    feature which is relevant for desktops, but shoud not drag the entire
    python3-launchpadlib stack into small installations. Add it as Recommends
    to the GUI frontends instead, to retain current behaviour on desktops.

update-manager (1:16.10.6) yakkety; urgency=medium

  * UpdateManager/UnitySupport.py: Handle ValueError traceback when checking
    for Unity and Dbusmenu support.  Thanks to Launchpad user flocculant for
    the patch.  (LP: #1629900)

update-manager (1:16.10.5) yakkety; urgency=medium

  [ Brian Murray ]
  * UpdateManager/UpdateManager.py: when marking HWE packages for install pass
    on a SystemError and let the problem resolver sort it out.
  * HweSupportStatus/consts.py: Improve wording of the messages.
  * hwe-support-status:
    - decode output when checking for foreign architectures so that the result
      is unicode not bytes.
    - add libwayland-egl1-mesa to the list of metapackages.
    - utilize a virtualbox metapackage set.
    - Do not show replacements that are already installed on
      the system.  (LP: #1607983)
  * source_update-manager.py: collect information about the state of HWE
    support on the system. (LP: #1617080)
  * source_update-manager.py: only collect HWE information if it exists.

  [ Jeremy Bicha ]
  * Add gi.require_version in a few more places to reduce the annoying
    warnings. (LP: #1573177)

update-manager (1:16.10.4) yakkety; urgency=medium

  * ChangelogViewer: Fix an API call to work with GTK < and ≥ 3.20. Upstream
    gave gtk_text_view_get_iter_at_location a gboolean return type, which
    makes gobject-introspection return (return value, out parameter). (LP:
    #1548425)
  * ChangelogViewer: Set vexpand so that the changelog TextView takes up all
    the remaining vertical space.

update-manager (1:16.10.3) yakkety; urgency=medium

  [Nicolas Delvaux]
  * Attempt to retrieve Changelogs from PPA sources (LP: #253119)
  * Correctly detect the usage of a username in changelog URIs

update-manager (1:16.10.2) yakkety; urgency=medium

  * Include HWE support tools and information. (LP: #1498059)

update-manager (1:16.10.1) yakkety; urgency=medium

  * Correctly calculate the end of support, and return correctly when support
    has ended. Patch from Andrew Gaul, with thanks.

update-manager (1:16.04.3) xenial; urgency=medium

  * Quote URL parameters for the Release Announcement. (LP: #1561215)

update-manager (1:16.04.2) xenial; urgency=medium

  [ Tim Lunn ]
  * UpdateManage/Core/utils.py: Update to use logind inhibitors (LP: #1566141)

update-manager (1:16.04.1) xenial; urgency=medium

  * Update Build-Depends to resolve ftbfs in xenial.

update-manager (1:15.10.3) wily; urgency=medium

  * Pass a '#auto' suffix to aptdaemon for packages that are autoinstalled,
    so that we have enough information to autoremove them later.  Thanks to
    Michael Vogt <mvo@ubuntu.com> for the patch.  LP: #1439769.
  * Add versioned dependency on aptdaemon (>= 1.1.1+bzr982-0ubuntu13) for the
    above.

update-manager (1:15.10.2) wily; urgency=medium

  * UpdateManager/Core/UpdateList.py: update the binary packages made by the
    linux-meta source package. (LP: #1215114)

update-manager (1:15.10.1) wily; urgency=medium

  * UpdateManager/Core/MetaRelease.py: When not running in development mode,
    if the next release is unsupported do not offer to upgrade to that, but
    the release after it. When running in development mode continue to offer
    upgrading to unsupported release. (LP: #1497024)

update-manager (1:15.04.7) vivid; urgency=medium

  * debian/tests/control: pyflakes3 is provided by pyflakes

update-manager (1:15.04.6) vivid; urgency=medium

  * debian/tests/control: switch to using pyflakes3 instead of pyflakes.

update-manager (1:15.04.5) vivid; urgency=medium

  * tests/test_pyflakes.py: switch to using pyflakes3 instead of pyflakes.

update-manager (1:15.04.4) vivid; urgency=medium

  * Properly check for FileNotFoundError when looking for /etc/machine-id.
    (LP: #1443929)

update-manager (1:15.04.3) vivid; urgency=medium

  * Allow being a child of 'systemd' as well as 'init' .If we're booted with
    e.g. init=/lib/systemd/systemd then the parent will be systemd.
  * Use the systemd /etc/machine-id file if available for our unique ID.

update-manager (1:15.04.2) vivid; urgency=medium

  * UpdateManager/Core/utils.py: use rpartition in case the process name
    contains the right parenthesis character. Thanks to Roman Odaisky for the
    patch. (LP: #1399916)
  * UpdateManager/Dialogs.py: set the focus to "Restart Later" instead of
    "Restart Now", so people don't accidentally reboot. (LP: #1421044)

update-manager (1:15.04.1) vivid; urgency=medium

  * debian/control: Don't depend on gir1.2-vte-2.90, we don't use it
    (directly) any more.

update-manager (1:14.10.6) utopic; urgency=medium

  * UpdateManager/ChangelogViewer.py: update URL for CVEs (LP: #1374715)

update-manager (1:14.10.5) utopic; urgency=medium

  [ Yu-Cheng Chou ]
  * UpdateManager/UpdateManager.py: _on_close() should return the value to make
    close button work properly (LP: #1363580)

update-manager (1:14.10.4) utopic; urgency=medium

  * Fix test_url_downloadable() with proxis: ensure that $no_proxy doesn't
    prevent us from accessing localhost through proxy.

update-manager (1:14.10.3) utopic; urgency=low

  [ Mitsuya Shibata ]
  * lp:~cosmos-door/ubuntu/trusty/update-manager/fix1358229:
    - ensure all scripts are treated as python by gettext
      LP: #1358229

update-manager (1:14.10.2) utopic; urgency=low

  * pep8 fixes to fix autopkgtest failure with the latest pep8

update-manager (1:14.10.1) utopic; urgency=low

  * fix ADT failure

update-manager (1:14.10.0) utopic; urgency=low

  * make meta-release parser stricter to avoid storing the data 
    that e.g. intercepting proxies send (LP: #1310891)

update-manager (1:0.196.12) trusty-proposed; urgency=low

  * use Gtk.init() to ensure update-manager fails with a
    runtime error message instead of crashing if the display
    can not be opened (LP: #1269397)

update-manager (1:0.196.11) trusty; urgency=low

  * lp:~mvo/update-manager/lp1202754:
    - do nt crash if the user clicks "cancel" in the polkit dialog
      (LP: #1202754)

update-manager (1:0.196.10) trusty; urgency=low

  * debian/control:
    - add dependencies to the various policykit agents to ensure
      that update-manager is not run without policykit agent support
      in the session (LP: #1164558)
  * tests/test_update_list.py:
    - test improvements from Barry Warsaw (many thanks!)

update-manager (1:0.196.9) trusty; urgency=medium

  [ Sebastien Bacher ]
  * UpdateManager/UpdatesAvailable.py: 
    - use the correct icon theme (lp: #1283554)

  [ Marc Deslauriers ]
  * UpdateManager/Dialogs.py: close window after requesting reboot.
    (LP: #1297361)
  
  [ Michael Vogt ]
  * tests/aptroot-update-list-test:
    - fix test failure caused by not-installable depends (lp: #1295392)

update-manager (1:0.196.8) trusty; urgency=medium

  * source_update_manager.py: set response to None if the problem type is not
    a bug
  * UpdateManager/Core/utils.py: do not perform DNS lookups with iptables,
    thanks to John Edwards for the patch.  (LP: #1290825)

update-manager (1:0.196.7) trusty; urgency=medium

  * Fix PEP-8 style error to fix tests.

update-manager (1:0.196.6) trusty; urgency=low

  * Allow user to close the restart required dialog (LP: #1033226)
    - Add a settings button
    - Add a "Restart Later" button
    - Rename existing button to "Restart Now..."
    - Add secondary text to updates dialog when a restart is still pending
      from last updates

update-manager (1:0.196.5) trusty; urgency=medium

  * Stop using deprecated GObject constructors with positional arguments
    (see https://wiki.gnome.org/PyGObject/InitializerDeprecations).

update-manager (1:0.196.4) trusty; urgency=low

  * lp:~mterry/update-manager/requires-restart:
    - warn if a update requires a reboot (LP: #255443)

    This requires that the packages that need a reboot set
    "XB-Restart-Required: system" in the package record

update-manager (1:0.196.3) trusty; urgency=low

  [ Sebastien Bacher ]
  * lp:~seb128/update-manager/check-none-controller
    - Check for controller being None before using it (this was
      accidentally dropped in a previous refactoring).
    - LP: #1203919

update-manager (1:0.196.2) trusty; urgency=low

  [ Brian Murray ]
  * UpdateManager/Core/MetaRelease.py: speed up the check for a new release of
    Ubuntu.  Thanks to Anders Kaseorg for the patch.

  [ Sebastien Bacher ]
  * lp:~seb128/update-manager/box-use-vertical-space:
    - Use the vertical space, GTK 3.10 displays the box shrinked otherwise

update-manager (1:0.196.1) trusty; urgency=low

  * debian/source_update_manager.py: Fix too long line (pep8 error).

update-manager (1:0.196) trusty; urgency=low

  * In the apport hook ask if the bug is about upgrading from one release to
    another and send bug to ubuntu-release-upgrader. (LP: #1071057)

update-manager (1:0.195) trusty; urgency=low

  * Add support for logind to the restart dialog.  Thanks to Thaddaus
    Tintenfisch for the patch.  (LP: #1232363)

update-manager (1:0.194) saucy; urgency=low

  * Fix a bug introduced in the dialog refactor from version 1:0.189 that
    causes update-manager to crash instead of showing a dialog when there are
    no updates to apply but the system needs rebooted.  LP: #1219414.

update-manager (1:0.193) saucy; urgency=low

  * Fix PEP-8 errors.

update-manager (1:0.192) saucy; urgency=low

  * Core/UpdateList.py: if a package is an ignored phased update mark it for
    keeping (LP: #1211511)

update-manager (1:0.191) saucy; urgency=low

  * Fix update-manager crashing when trying to raise
    window. on_button_install_clicked takes only one positional argument,
    not two. (LP: #1202959)

update-manager (1:0.190) saucy; urgency=low

  * Update for python-distutils-extra 2.38 (yelp-tools style help)

update-manager (1:0.189) saucy; urgency=low

  [ Jeremy Bicha ]
  * Drop unused system-software-update icons since it is a
    standard theme icon
  
  [ Robert Roth ]
  * Remove dist-upgrade option description from manpage (LP: #1079136)

  [ Dylan McCall ]
  * Refactor dialogs to have a common base.
  * tests/test_update_error.py: Fix test regression from the above.

  [ Martin Pitt ]
  * Drop obsolete GObject.threads_init() calls to avoid warnings at startup.
    Bump python-gi dependency accordingly.
  * Drop unused imports and assignments to fix pyflakes errors.
  * Fix PEP-8 errors.
  * tests/test_update_error.py: Adjust test_error_no_updates() to current
    string.

update-manager (1:0.188) saucy; urgency=low

  * Core/UpdateList.py: Drop unused "src_name" variable (pyflakes error).
  * tests/test_update_list.py: Fix too long line (pep8 error).

update-manager (1:0.187) saucy; urgency=low

  [ Sami Jaktholm ]
  * Greatly speed up update calculation (LP: #1167277)

  [ Martin Pitt ]
  * Drop unnecessary ubuntu-drivers-common build dependency, to ease
    backporting.

  [ Brian Murray ]
  * Modify phased update percentage to use source packages and not binary
    packages, additionally add a test for this.
  * Remove check for update-notifier auto-launch gsettings key

update-manager (1:0.186) raring; urgency=low

  [ Sebastien Bacher ]
  * Use correct variable in error message, fixing a crash (LP: #1142151)

update-manager (1:0.185) raring; urgency=low

  [ Sebastien Bacher ]
  * Specify a background color for the unity launcher icon (lp: #1081691)

  [ Michael Terry ]
  * Look for to-be-updated application icons in app-install-data
    (LP: #1145157)

update-manager (1:0.184) raring; urgency=low

  [ Michael Terry ]
  * Don't temporarily freeze when calculating which updates are available.
    LP: #1137996

  [ Colin Watson ]
  * Allow removals with only Conflicts+Replaces; while policy 7.6.2 quotes
    Provides in an example, it's clear that Conflicts+Replaces alone should
    be sufficient to indicate that the target package may be removed.

update-manager (1:0.183) raring; urgency=low

  [ Mike Terry ]
  * Fix toggling items after doing a deselect-all. (LP: #1129191)

  [ Colin Watson ]
  * Fix PEP-8 failures.
  * Fix pyflakes failures.
  * Depend on pep8 and pyflakes for the autopkgtest suite.
  * Use logging.warning rather than deprecated logging.warn.
  * Fix test_meta_release_core.SillyProxyRequestHandler to write bytes
    rather than text to its output file object.
  * Make test_meta_release_core pick a new proxy port for each test.
  * Use EnvironmentVarGuard in test_meta_release_core to reduce the risk of
    test isolation bugs.
  * MetaReleaseCore: Plug some open file object leaks.
  * Make test_meta_release_core call install_opener(None) every time it
    changes proxy settings, to avoid stale ones being left around from
    previous tests.
  * Reopen cache in GroupingTestCase.setUp, TestCache.setUp, and
    TestChangelogs.setUp to avoid test isolation bugs.
  * Remove unnecessary cache update in PhasedTestCase.setUp; reopening the
    cache is sufficient.
  * Allow saveDistUpgrade to remove packages provided that upgrade
    candidates declare Conflicts+Replaces+Provides on them (LP: #1038113).

  [ Steve Langasek ]
  * Build-depend on python3-all (>= 3.3.0-2) for pybuild support and drop
    the now-extraneous overrides from debian/rules; this incidentally works
    around an issue I don't understand where the package was now failing to
    build locally from trying to invoke python setup.py instead of python3.

update-manager (1:0.182) raring; urgency=low

  * MetaReleaseCore: Create ~/.cache if it does not exist.

update-manager (1:0.181) raring; urgency=low

  * Use the gnome debconf frontend, accidentally dropped in update-manager
    1:0.165 (LP: #1110585).

update-manager (1:0.180) raring; urgency=low

  [ Dylan McCall ]
  * Make sure text in Install column properly uses ellipses. (LP: #1105363)
  * Refactor CellAreaPackage class for ease of future changes.

update-manager (1:0.179) raring; urgency=low

  * Properly xml-escape application names too, not just package labels
  * Make sure dialog buttons are actually at the bottom of the dialog

update-manager (1:0.178) raring; urgency=low

  * Implement the "available updates" details pane from the SoftwareUpdates
    spec.  Specifically, this adds grouping of related updates, adds an
    "Ubuntu base" group for core packages, and shows only the description
    summary in the main view.
  * Show a restart icon next to packages that declare they will need a
    system restart via XB-Restart-Required: system

update-manager (1:0.177) raring; urgency=low

  * Fix missing import in tests/test_upgrade.py.
  * Make tests/test_update_list.py more robust against other tests being run
    before it.
  * Depend on aptdaemon for DEP-8 tests.
  * Fix typo in test dpkg status file for test_update_list.
  * Add Update-Manager::Never-Include-Phased-Updates, the converse of
    Update-Manager::Always-Include-Phased-Updates; this opts out of
    upgrading to any package with a Phased-Update-Percentage set.

update-manager (1:0.176) raring; urgency=low

  * Use GLib.timeout_add_seconds instead of deprecated GObject.timeout_add
  * Keep dialogs 33em wide
  * Pass update-manager arguments on to do-release-upgrade (LP: #1097907)

update-manager (1:0.175) raring; urgency=low

  [ Eric Williams ]
  * German translation fix (LP: #1070289)

  [ Stephen Kraemer ] 
  * UpdateManager/Dialogs.py: made Settings... button open software-properties
    non-modally.  (LP: #1058070)

  [ Robert Roth ]
  * Remove package count badge from the unity launcher (LP: #1036891)
  * Added 6px border to the button box to align the buttons with the contents
    above (LP: #1081099)

  [ Michael Vogt ]
  * debian/rules:
    - do not call dh_auto_build as as it call py2 even when its not
      supposed to (LP: #1089808), thanks to Jean-Baptiste Lallement 
  * fix missing "Architecture" when writing out the fake dpkg-status
    file in the tests (LP: #1089793)

update-manager (1:0.174.3) quantal; urgency=low

  * UpdateManager/UpdatesAvailable.py:
    - never pass "None" to xml.sax.saxutils.escape (LP: #1044080)

update-manager (1:0.174.2) quantal; urgency=low

  [ Michael Vogt ]
  * fix crash in UpdateManager.Core.utils.error(), thanks to
    Christian Parrino (LP: #964674)

  [ Michael Terry ]
  * Stop showing Install All Available Updates quicklist item when it isn't
    appropriate (LP: #1031307).

update-manager (1:0.174.1) quantal; urgency=low

  * po/POTFILES.in:
    - add missing InstallBackendAptdaemon.py, thanks to Igor Zubarev
      (LP: #1055594)

update-manager (1:0.174) quantal; urgency=low

  * UpdateManager/ChangelogViewer.py: improve url parsing of changelog files
    so that more links are created.  Thanks to sampo555 for the patch 
    (LP: #1011093).
  * Add a dependency to update-manager on update-notifier (LP: #1043725) 

update-manager (1:0.173) quantal; urgency=low

  * Make update-manager-core depend on ubuntu-release-upgrader-core and
    update-manager-kde depend on ubuntu-release-upgrader-qt, so that
    functionality isn't lost on upgrade (LP: #1049062).

update-manager (1:0.172) quantal; urgency=low

  * Remove dependency on update-notifier as it added many dependencies to
    cloud-images.

update-manager (1:0.171) quantal; urgency=low

  [ Michael Terry ]
  * Fix test suite to pass when run on non-amd64 machine

  [ Brian Murray ]
  * Add a dependency on update-notifier (LP: #1043725) 

update-manager (1:0.170) quantal; urgency=low

  * When user cancels/stops the apt cache update, still let them
    view available updates from a previous cache update.  LP: #1024909

update-manager (1:0.169) quantal; urgency=low

  [ Michael Terry ]
  * Drop Unity-support gir Recommends down to Suggests. LP: #1029764
  
  [ sampo555 ]
  * lp:~sampo555/update-manager/fix-for-1031280:
    - Convert SystemError into string in order to avoid TypeError in
      UpdateManager.refresh_cache SystemError handles. Fixes LP: #1031280

  [ Robert Park ]
  * Allow test suite to not need to be run as root
  
  [ Michael Vogt ]
  * lp:~mvo/update-manager/phased-updates:
    - Implement the client part of the "foundations-q-phased-updates".
      This allows to deploy updates in phases where only a subset of
      the users will get a update, controlled via the 
      Phased-Updates-Percentage tag in the Packages file.

update-manager (1:0.168) quantal; urgency=low

  * Run tests under xvfb and don't try to use non-existant python3-coverage
  * Don't throw exception on socket timeout when downloading metarelease
    file.  LP: #818760

update-manager (1:0.167) quantal; urgency=low

  * Rebuild to get python3 wrapper script (LP: #1023474)

update-manager (1:0.166) quantal; urgency=low

  [ Colin Watson ]
  * Write metarelease file as UTF-8 (LP: #1020526)

  [ Michael Terry ]
  * Use a wrapper script of /bin/sh when calling pkexec, to workaround its
    requirement that the ppid not be 1.  (LP: #1020115)
  * Update Unity badge count before showing "please restart" dialog
  * Don't allow closing the "please restart" dialog via window manager
  * Show "please restart" dialog on startup if needed, instead of only
    after installing some updates

update-manager (1:0.165) quantal-proposed; urgency=low

  * Implementation of "update on start" feature from spec
    https://wiki.ubuntu.com/SoftwareUpdates
  * Use a single main window that changes instead of having modal dialogs
  * Implement several special-purpose dialogs like "No updates" or
    "Dist upgrade needed" accordingn to the above spec
  * Split out release upgrader code and DistUpgrade module into a separate
    source package
  * Drop python-update-manager, as it is unused
  * debian/tests:
    - Add dep8 tests

update-manager (1:0.164) quantal; urgency=low

  [ Brian Murray ]
  * DistUpgrade/DistUpgradeApport.py: ensure package install failures are
    tagged dist-upgrade

  [ Robert Roth ]
  * UpdateManager/UpdateManager.py: check for None type from
    get_last_update_minutes (LP: #1013325)

  [ Colin Watson ]
  * DistUpgrade/NvidiaDetector, debian/control: Update symlink to Python 3
    version, available as of ubuntu-drivers-common 1:0.2.55.
  * debian/rules: Make sure to run setup.py with the default python3 last,
    so that scripts get correct #! lines.

  [ Barry Warsaw ]
  * pre-build.sh:
    - Add python-gi as an explicit dependency.
    - python3-mock is required.
  * setup.py:
    - Fix the installation of the janitor.plugincore package for Python 3.
      (LP: #1013490)
    - Calculate the setup() version number from debian/changelog.
    - Remove package_dir since it's not actually needed.
    - Whitespace normalization.
  * tests/Makefile
    - Add sleep between Python 2 and Python 3 invocation of tests under
      xvfb-run, otherwise I get crashes where xvfb doesn't come up.

update-manager (1:0.163) quantal; urgency=low

  [ Colin Watson ]
  * Isolate tests from local configuration in
    /etc/update-manager/release-upgrades.d/.
  * Use Python attributes rather than GObject.get_data and GObject.set_data,
    which have been removed upstream (LP: #1009859).
  * Switch default view class to Gtk3 and replace python-gobject dependency
    with python-gi.
  * Port away from old-style apt.Package candidateFoo and installedFoo
    properties, preferring candidate.foo and installed.foo.  In a number of
    cases we have to check whether candidate/installed is non-None first.
  * Use apt_pkg.version_compare rather than apt_pkg.VersionCompare.
  * Use apt_pkg.uri_to_filename rather than apt_pkg.URItoFileName.
  * Use apt_pkg.TagFile (and related new-style API) rather than
    apt_pkg.ParseTagFile.
  * Use apt_pkg.PackageManager rather than apt_pkg.GetPackageManager.
  * Use apt_pkg.Acquire rather than apt_pkg.GetAcquire.
  * Use mark_foo/marked_foo rather than markFoo/markedFoo.
  * Use apt_pkg.ActionGroup rather than apt_pkg.GetPkgActionGroup.
  * Use apt_pkg.ProblemResolver rather than apt_pkg.GetPkgProblemResolver.
  * Use apt_pkg.read_config_file rather than apt_pkg.ReadConfigFile.
  * Use new spelling of apt_pkg.DepCache methods.
  * Rename several local cache methods to PEP-8 style to avoid showing up in
    the output of /usr/share/python-apt/migrate-0.8.py.
  * Use apt_pkg.size_to_str rather than apt_pkg.SizeToStr.
  * Use apt_pkg.PackageManager.get_archives rather than
    apt_pkg.PackageManager.GetArchives.
  * Use apt_pkg.Acquire.fetch_needed rather than
    apt_pkg.Acquire.FetchNeeded.
  * Use new spelling of apt_pkg.Package/Version/Dependency methods.
  * Use apt_pkg.pkgsystem_lock rather than apt_pkg.PkgSystemLock.
  * Use new spelling of apt_pkg dependency parsing methods.
  * Use new spelling of apt_pkg.SourceList methods.
  * Bump python-apt (build-)dependency to >= 0.8.0.
  * Add a scheme for excluding false positives from the pyflakes test, and
    enable it by default.
  * Rearrange the OptionParser workaround from 1:0.154.5 to work with Python
    3, using gettext or ugettext as appropriate.
  * Always pass bytes to hashlib.md5.update.
  * Fix DistUpgradeAptCdrom to account for gzip files being opened in binary
    mode.
  * Convert the last use of os.popen to subprocess.check_output, which makes
    it easier to read str rather than bytes.  (This requires Python 2.7.)
  * Decode bytes read from urlopened file objects.
  * UpdateManager/backend/InstallBackendSynaptic.py
    - Keep a reference to the data tuple passed to GObject.child_watch_add
      to avoid attempts to destroy it without a thread context
      (LP: #724687).
    - Open temporary synaptic selections file in text mode.
  * Define __bool__ rather than __nonzero__ method in Python 3.
  * sort(cmp=) and sorted(cmp=) no longer work in Python 3.  Use appropriate
    key= arguments instead.
  * Fix ResourceWarning while reading /proc/mounts.
  * Make update-manager-kde depend on psmisc, for killall.
  * DistUpgrade/DistUpgradeView.py:
    - Use floor division in FuzzyTimeToStr.
  * DistUpgrade/DistUpgradeViewText.py:
    - Flush stdout after printing confirmation message, since it doesn't
      have a trailing newline.
  * Use the appropriate Unicode gettext methods in both Python 2 and 3, and
    drop lots of Python-3-unfriendly Unicode mangling as a result.
  * DistUpgrade/DistUpgradeViewKDE.py:
    - Open the terminal log in binary mode.
  * data/do-release-upgrade.8:
    - Provide a more useful NAME section.
  * DistUpgrade/DistUpgradeCache.py:
    - Tolerate SyntaxError from attempting to import NvidiaDetector, until
      such time as a complete ubuntu-drivers-common Python 3 port is in the
      archive.
  * Switch #! lines over to python3, apart from dist-upgrader which needs to
    stay as Python 2 for a while longer (and have some special arrangement
    for running with Python 3 for upgrades from >= quantal).
  * Run tests under both Python 2 and 3.

  [ Adam Conrad ]
  * Merge branch from Michael Terry to drop auto-upgrade-tester
    from update-manager and move it into its own source package

  [ Barry Warsaw ]
  * Begin refactoring of Computer Janitor code by renaming and
    re-situating all of it to janitor/plugincore.  This will eventually be
    removed from here into its own separate branch.
  * Merge the temporary Python 3 sprint branch back into trunk, and close
    the py3 sprint branch.
  * Moved UpdateManager/backend and UpdateManager/UnitySupport.py to the
    python*-update-manager packages for apturl.

  [ Michael Vogt ]
  * UpdateManager/GtkProgress.py:
    - fix python-apt 0.8 API crash

  [ Stéphane Graber ]
  * Drop fdsend as it's not used and doesn't build with python3.
  * Make update-manager-core a binary all packages (everything is python).
  * Split update-manager-core into python-update-manager,
    python3-update-manager and update-manager-core.
  * Build-depend and depend on python-apt >= 0.8.5~ as we need proper
    python3 support.

  [ Steve Langasek ]
  * tests/test_country_mirror.py: the test suite shouldn't fail if $LANG
    isn't set in the environment.
  * update-manager is now using python3 as an interpreter, so fix these up
    to actually be python3 packages.

update-manager (1:0.162) quantal; urgency=low

  * DistUpgrade/build-tarball.sh:
    - include "DistUpgrade" symlink in tarball to ensure relative
      imports keep working

update-manager (1:0.161) quantal; urgency=low

  * /usr/share/nvidia-common/obsolete was renamed to
    /usr/share/ubuntu-drivers-common/obsolete and moved packages.  Cope with
    this.

update-manager (1:0.160) quantal; urgency=low

  [ Colin Watson ]
  * Use Python 3-style print functions.
  * Use "except Exception as e" syntax rather than the old-style "except
    Exception, e".
  * Fix a few assorted pyflakes warnings.
  * Use string methods rather than functions from the string module.
  * Replace most uses of filter and map with list comprehensions or for
    loops.
  * Use open() rather than file().
  * Use Python 3 renaming of ConfigParser if available.
  * Use "raise Exception(value)" syntax rather than the old-style "raise
    Exception, value".
  * Remove duplicate imports of os.path; 'import os' is enough.
  * Use Python 3 renamings of urllib, urllib2, and urlparse if available.
  * Remove all hard tabs from Python code.  Python 3 no longer tolerates
    mixing tabs and spaces for indentation.
  * Use Python 3 renaming of httplib if available.
  * Use email.utils.parsedate (with a DST handling correction) rather than
    the long-deprecated rfc822.parsedate.
  * Use the threading module instead of thread (renamed to _thread in Python
    3).
  * Tell Python to use absolute imports by default, and annotate cases where
    we need relative imports.
  * Update test_proxy to use gsettings and the python-apt 0.8 API.
  * Use new-style octal literals.
  * Drop use of deprecated statvfs module.
  * Use Python 3 renamings of BaseHTTPServer and SocketServer if available.
  * Modernise use of unittest methods.
  * Use python-apt 0.8 API spellings of apt_pkg.config methods.
  * Fix several ResourceWarnings with Python 3.
  * Port to python-apt 0.8 progress classes.
  * Since python-gnupginterface is not likely to be ported to Python 3, and
    since it's almost just as easy to call gpg directly via subprocess, do
    so.
  * Use gettext if ugettext does not exist (as in Python 3).
  * Ignore __pycache__ directories, and exclude them from dist-upgrader
    tarballs.
  * Fix up module path when running AutoUpgradeTester/auto-install-tester.py
    from the build tree.
  * Add a DistUpgrade -> . symlink in DistUpgrade/, to make it possible to
    have compatible imports both in update-manager proper and in
    dist-upgrader tarballs.
  * Use only absolute imports in AutoUpgradeTester/auto-install-tester.py
    and DistUpgrade/dist-upgrade.py; these have no __package__ and so cannot
    use relative imports.
  * Open subprocesses with universal_newlines=True when expecting to read
    text from them.  On Python 2, this only enables \r\n conversion and the
    like, but on Python 3 this also causes subprocess-related file objects
    to read str rather than bytes.
  * Use "key in dict" rather than "dict.has_key(key)".
  * Pass globals() to __import__ so that relative imports work.

  [ Michael Vogt ]
  * DistUpgrade/*.py:
    - update for the 12.04 -> 12.10 upgrade
  * AutoUpgradeTester/profile/defaults.cfg.d/defaults.cfg:
    - update for precise->quantal
  * fix some remaining python-apt 0.8+ API issues

  [ Brian Murray ]
  * DistUpgrade/DistUpgradeApport.py
    - check errormsg for the English version of the dependency problems error
      first (LP: #999890)

  [ Michael Terry ]
  * Rename to Software Updater and fix some other strings to match mpt's
    spec.
  * lp:~mterry/update-manager/move-changelogs:
    - implement new app layout

update-manager (1:0.156.14.5) UNRELEASED; urgency=low

  * lp:~ember/update-manager/ubuntu.bug1002956:
    - fix missing ReleaseNotesViewerWebkit.py support, thanks to
      Pedro Fragoso (LP: #1002956)

update-manager (1:0.156.14.4) precise-security; urgency=low

  * SECURITY UPDATE: Incorrect permissions on system_state archive may
    expose repo passwords (LP: #954483)
    - DistUpgrade/DistUpgradeMain.py: create file with proper permissions.
    - debian/update-manager-core.postinst: clean up permissions on existing
      files.
    - CVE-2012-0948
  * SECURITY UPDATE: Apport hook may upload system_state archive containing
    repo passwords (LP: #954483)
    - debian/source_update-manager.py: don't upload system_state archives.
    - CVE-2012-0949
  * This package does _not_ contain the changes from (1:0.156.14.2) in
    precise-proposed.

update-manager (1:0.156.14.2) precise-proposed; urgency=low

  * fix automatic expand of the terminal if no activity happend
    for >300s (LP: #979661)

update-manager (1:0.156.14.1) precise-proposed; urgency=low

  * DistUpgrade/ReleaseAnnouncement:
    - add "LTS" to the version

update-manager (1:0.156.14) precise; urgency=low

  * debian/control:
    - fix description for update-manager-kde (LP: #984906),
      thanks to Scott Kitterman
  * DistUpgrade/DistUpgradeController.py:
    - do not set PYCENTRAL_NO_DPKG_QUERY (LP: #986233)

update-manager (1:0.156.13) precise; urgency=low

  * Improve the error message used when a package cannot be located after
    updating, probably caused by an overloaded mirror. (LP: #873468)

update-manager (1:0.156.12) precise; urgency=low

  [ Colin Watson ]
  * data/gtkbuilder/UpgradePromptDialog.ui:
    - Remove has_separator property from dialog_really_do_not_upgrade
      (deprecated in GTK+ 2.22, removed in 3.0).
  * debian/control:
    - Restore gksu dependency, needed by e.g. check-new-release-gtk
      (LP: #980637).
  
  [ Michael Vogt ]
  * UpdateManager/UpdateManager.py:
    - disconnect model and clear store before rebuilding the cache,
      thanks to Colin Watson
  * po/*.po:
    - updated to the latest launchpad (LP: #628157)
  * DistUpgrade/DistUpgradeController.py:
    - remove backports sources.list.d file again after its no
      longer needed (LP: #973717)
  * DistUpgrade/DistUpgradeController.py:
    - when checking for the backports, its enough to check is the
      set of the needed ones is a subset of the found ones (LP: #969182)
  * DistUpgrade/DistUpgrade.cfg.lucid:
    - release-upgrader-libapt-pkg-dev is not needed for the upgrade
      itself
  * remove skype from the removal blacklist

update-manager (1:0.156.11) precise; urgency=low

  * DistUpgrade/DistUpgrade.cfg.lucid:
    - add in a missing backported package (LP: #969182)
  * DistUpgrade/Distupgrade.py:
    - workaround issue regarding removing selections, thanks to sampo555 for
      the patch (LP: #945536)
  * Automatic update of mirrors, demoted packages and of included source
    packages: base-installer

update-manager (1:0.156.10) precise; urgency=low

  [ Michael Vogt ]
  * UpdateManager/Core/MyCache.py:
    - do not attempt to download changelogs from https locations if
      the uri requires credentials, thanks to Pat McGowan

  [ Colin Watson ]
  * UpdateManager/Core/MyCache.py:
    - Check that pkg.candidate.uri is not None when looking for changelogs
      (LP: #839986).

update-manager (1:0.156.9) precise; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeController.py:
    - support cdrom-only upgrades properly by using the backported
      libapt-{pkg,inst} and release-upgrader-python-apt from the CD
  * DistUpgrade/DistUpgrade.cfg:
    - update KernelRemoval/Version to match oneirics kernel
  * DistUpgrade/DistUpgrade.cfg.lucid:
    - update KernelRemoval/Version to match lucids kernel
  * data/release-upgrades:
    - set releae upgrades default to "lts"
  * DistUpgrade/DistUpgradeCache.py:
    - when selecting a new default kernel from base-installer, ensure
      to install the matching kernel headers too if previously kernel
      headers were installed (LP: #959307)
  
  [ Brian Murray ]
  * debian/source_update-manager.py: pass if attach_gsettings fails like on a
    server

  [ Gabor Kelemen ]
  * lp:~kelemeng/update-manager/bug957552:
    - Mark two accessible descriptions for translation. LP: #957552

update-manager (1:0.156.8) precise; urgency=low

  [ Robert Roth ]
  * Update icon name to use FD.o standard (LP: #921310)
  
  [ Julien Lavergne ]
  * DistUpgrade/DistUpgrade.cfg, DistUpgrade/removal_blacklist.cfg,
    UpdateManager/Core/utils.py,
    AutoUpgradeTester/profile/lubuntu/DistUpgrade.cfg:
   - Add Lubuntu support, and don't upgrade gnome-components which have been
     removed from Lubuntu installation (LP: #945215)

  [ Barry Warsaw ]
  * Improve the warning issued when i8xx graphics hardware is
    detected. (LP: #941172)

  [ Brian Murray ]
  * DistUpgrade/removal_blacklist.cfg: 
    - blacklist gnome-session so that users can always login after a failed
      partial upgrade (LP: #946539)

  [ James Hunt ]
  * Only attempt to stop screensaver if DISPLAY set, and throw away
    xdg-screensaver output. (LP: #883618)

  [ Colin Watson ]
  * Use 'from dbus.mainloop.glib import DBusGMainLoop;
    DBusGMainLoop(set_as_default=True)' to set up the main loop, rather than
    importing the deprecated dbus.glib.
  
  [ Gabor Kelemen ]
  * Fix misplaced parentheses. LP: #952959

update-manager (1:0.156.7) precise; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeCache.py:
    - fix nvidia detection, thanks to Brian Murray
  * DistUpgrade/xorg_fix_proprietary.py:
    - fix crash when apt_pkg is not initialized (LP: #942106)
  * DistUpgrade/DistUpgradeController.py, DistUpgrade/mirrors.cfg:
    - support upgrades with commercial-ppas in the sources.list
      (LP: #939461) and add tests
  * UpdateManager/UpdateManager.py:
    - fix inaccurate string, thanks to JohnNapster (LP: #942590)

  [ Brian Murray ]
  * DistUpgrade/removal_blacklist.cfg: 
    - Only blacklist unity-2d, not all packages whose names start with
      unity-2d.  (LP: #940196)

update-manager (1:0.156.6) precise; urgency=low

  [ Robert Roth ]  
  * lp:~evfool/update-manager/lp930177:
    - Add missing space (LP: #930177) 
  
  [ Michael Vogt ]
  * DistUpgrade/DevelReleaseAnnouncement:
    - change label from alpha to beta release

update-manager (1:0.156.5) precise; urgency=low

  [ Brian Murray ]
  * do-release-upgrade: capitalize U in ubuntu
  * debian/source_update-manager.py: add screenlog.0 from
    /var/log/dist-upgrade to apport bug reports

  [ Marc Deslauriers ]
  * DistUpgrade/DistUpgradeViewKDE.py: fix regression caused by improper
    return value handling. (LP: #933225)

update-manager (1:0.156.4) precise; urgency=low

  * DistUpgrade/DistUpgrade.cfg.lucid:
    - Update libapt-pkg and libapt-inst versions.

update-manager (1:0.156.3) precise; urgency=low

  [ Jean-Baptiste Lallement ]
  * lp:~jibel/update-manager/AutoUpgradeTester-desktoptests:
    New tests for Ubuntu Desktop LTS upgrade:
    * autologin check
    * user settings check: wallpaper, theme, keyboard layout, custom 
      launchers (desktop and panel)
  * lp:~jibel/update-manager/AutoUpgradeTester-portlocking:
    - automatically allocate free ssh/vnc ports

  [ Colin Watson ]
  * Clean up a few pyflakes warnings.
  * DistUpgrade/DistUpgradeMain.py
    - Make sure main.log is actually created.
  * DistUpgrade/removal_blacklist.cfg:
    - Only blacklist unity, not all packages whose names start with unity.
  
  [ Robert Roth ]
  * lp:~evfool/update-manager/lp351665:
    -  Use ngettext to humanize size (LP: #351665)
  * lp:~evfool/update-manager/distupgradefixes:
    - DistUpgrade changes dialog text fixes 
      (LP: #348517, LP: #513908)
    - Fix resize on changes dialog to stretch the details
      (LP: #294293)

  [ Michael Vogt ]
  * add humanize_size() test
  * pyflakes fixes
  * tests/test_pyflakes.py:
    - always pyflakes as part of the pre-build process to ensure
      we are clean
  * disable apply_dselect_upgrades()

update-manager (1:0.156.2) precise; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/removal_blacklist.cfg:
    - add unity, unity-2d

  [ Brian Murray ]
  * debian/source_update-manager.py: use attach_file for dist-upgrade log
    files rather than attach_root_command_outputs resolving the double gzipped
    apt clone attachment issue
  
  [ Matthew Linscott ]
  * UpdateManager/Core/utils.py
    - fixed typos in docstring for ExecutionTime 

  [ Daniel Polehn ]
  * DistUpgrade/DistUpgradeView.py
    - Made usage of 'canceled' v. 'cancelled' consistent. LP: #918302

update-manager (1:0.156.1) precise; urgency=low

  * debian/source_update-manager.py: include AptDaemon messages from syslog to
    help identify failures

update-manager (1:0.156) precise; urgency=low

  [ Michael Vogt ]
  * pyflake fixes, remove some dead code
  * update unity dependency

  [ Brian Murray ]
  * DistUpgrade/DistUpgradeController.py
    - call apport-cli directly for bug reporting of errors
  * check-new-release-gtk
    - ensure to write a integer when calculating the next time that
      the release available window will be presented (LP: #873424)
    - hide redundant release-notes button (LP: #873432)

update-manager (1:0.155.3) precise; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/removal_blacklist.cfg:
    - add screen as the server upgrade runs inside it, thanks to
      Steve Langasek
  * DistUpgrade/DistUpgradeController.py, 
    DistUpgrade/prerequists-sources.list:
    - use the release-upgrader-python-apt from lucid-updates instead
      of lucid-proposed

  [ Brian Murray ]
  * UpdateManager/UpdateManager.py
    - add periods to sentences in refresh_updates_count

update-manager (1:0.155.2) precise; urgency=low

  [ Robert Roth ]
  * DistUpgrade/DistUpgradeController.py:
    - Avoid using systemdir abbreviation (LP: #903939)

  [ Brian Murray ]
  * debian/source_update-manager.py:
    - Use attach_gesttings_package instead of attach_gconf
  
  [ Jean-Baptiste Lallement ]
  * lp:~jibel/update-manager/AutoUpgradeTester-aptclone:
    - support building a profile from a apt-clone file and testing
      that
    - add amd64 test profiles

update-manager (1:0.155.1) precise; urgency=low

  * fix crash in backports fetching code

update-manager (1:0.155) precise; urgency=low

  [ Michael Vogt ]
  * lp:~mvo/update-manager/lucid-precise-upgrades:
    - support upgrades with multiarch-support (for e.g. flash)
      from lucid to precise by using the release-upgrader-python-apt
      from lucid-proposed during the upgrade

  [ Gabor Kelemen ]
  * Mark a few strings for translation, make variables reorderable

update-manager (1:0.154.6) precise; urgency=low

  * DistUpgrade/DistUpgrade.ui:
    - remove <child internal-child="selection"> as this is not
      supported by the gtkbuilder in lucid and makes the release
      upgrader crash (LP: #898482)

update-manager (1:0.154.5) precise; urgency=low

  [ Nicholas Skaggs ]
  * lp:~nskaggs/update-manager/fix-for-702418:
    - Removed gnome-power-manager dbus interface completely and
      only use freedesktop interface.
      Thanks to Nicholas Skaggs (LP: #702418)
  
  [ Gabor Kelemen ]
  * Replace gettext.install() with bindtextdomain() calls.
    Work around crash in OptionParser when displaying
    localized --help text, to not regress on bug LP: #557804
  * Extract strings for translation from u-m-t and u-s-s executables
  
  [ Marc Deslauriers ]
  * SECURITY UPDATE: arbitrary code execution via directory traversal
    (LP: #881548)
    - UpdateManager/Core/DistUpgradeFetcherCore.py: verify signature before
      unpacking the tarball.
    - CVE-2011-3152
  * SECURITY UPDATE: information leak via insecure temp file (LP: #881541)
    - DistUpgrade/DistUpgradeViewKDE.py: use mkstemp instead of mktemp.
    - CVE-2011-3154
  
  [ Michael Vogt ]
  * UpdateManager/UpdateManager.py:
    - ensure that the origin headers state of "select all/dselect all"
      is consistent

update-manager (1:0.154.3) precise; urgency=low

  [ Alexey Feldgendler ]
  * lp:~feldgendler/update-manager/574436:
    Introduced the [ThirdPartyMirrors] configuration section for the
    distribution upgrader. All keys in it must have distinct names, but
    only values matter. Each value is a third-party source URI. Such
    whitelisted sources don't get disabled on upgrade; however, if they
    use "from" release name, it's replaced with the "to" release name.
    (LP: #574436)

update-manager (1:0.154.2) precise; urgency=low

  * UpdateManager/backend/InstallBackendSynaptic.py
    - fix crash when using synaptic (LP: #878719)
  * DistUpgrade/DistUpgradeController.py, DistUpgrade/DistUpgradeMain.py:
    - before doing the upgrade test if all systemdirs are actually 
      writable, thanks to Brian Murray (LP: #889921)

update-manager (1:0.154.1) precise; urgency=low

  [ Robert Roth ]
  *  Change up-to-date text to up to date (LP: #864336)
  
  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeController.py:
    - add precise as a LTS release
  * AutoUpgradeTester/profile/*/DistUpgrade.cfg:
    - updated to test oneiric->precise and lucid->precise
  * AutoUpgradeTester/UpgradeTestBackendQemu.py:
    - add support for different architectures
  * AutoUpgradeTester/profile/server-amd64/DistUpgrade.cfg:
    - add amd64 server upgrade test profile
  * DistUpgrade/DistUpgradeConfigParser.py:
    - add new "defaults_dir" argument to allow simplifying the 
      auto-upgrade-tester config
  * DistUpgrade/DistUpgrade.cfg.lucid:
    - add lucid->precise upgrade config
  * AutoUpgradeTester/UpgradeTestBackendQemu.py:
    - dynamically allocate ssh/vnc ports when multiple testers are run

update-manager (1:0.154) precise; urgency=low

  * lp:~barcc/update-manager/all_changes-wrong-use:
    - Fixed wrong use of self.cache.all_changes[name] in
      UpdateManager.on_treeview_update_cursor_changed
  * data/gtkbuilder/UpdateManager.ui:
    - set default height to 500 (thanks to Sebastien Bacher)
  * DistUpgrade/DistUpgradeController.py:
    - do not crash if apt-btrfs-snapshot fails to run (LP: #873411)
  * UpdateManager/Core/MyCache.py, DistUpgrade/DistUpgradeCache.py:
    - honor dselect request install state when calcuating the upgrade
      thanks to Evan for suggesting this
  * merge fixes from oneiric-proposed
  * DistUpgrade/*
    - update for oneiric->precise upgrades

update-manager (1:0.152.25.4) oneiric-proposed; urgency=low

  * DistUpgrade/removal_blacklist.cfg:
    - ensure that postgresql does not get removed (LP: #871893)

update-manager (1:0.152.25.3) oneiric-proposed; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - fix crash when packages needs downgrading
  * UpdateManager/Core/utils.py:
    - do not crash if iptables does not exist, thanks to Daniel
      Holbach for reporting the issue (LP: #877514)
  * DistUpgrade/DistUpgradeQuirks.py:
    - keep poking the screensaver to ensure that it really won't
      activate during the upgrade (thanks to Jonathan Davies for
      the report)
  * tests/test_sources_list.py:
    - fix test (archive.ubuntu.com no longer listens to ftp)
  * po/*:
    - refresh again to fix regression (LP: #877461)

update-manager (1:0.152.25.2) oneiric-proposed; urgency=low

  * refresh translation for the release-upgrader (LP: #873905)

update-manager (1:0.152.25.1) oneiric-proposed; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - do not crash if apt-btrfs-snapshot fails to run (LP: #873411)

update-manager (1:0.152.25) oneiric; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - add workaround for a python-apt bug that causes the release
      upgrade to import the old version of "DistInfo" intead of the 
      one that is bundled with the release-upgrader (LP: #871007)

update-manager (1:0.152.24) oneiric; urgency=low

  * AutoUpgradeTester/profile/eduubuntu/DistUpgrade.cfg:
    - Fix typo, renaming to edubuntu instead

update-manager (1:0.152.23) oneiric; urgency=low

  * DistUpgrade/DistUpgrade.cfg:
    - ensure that edubuntu-desktop really gets upgraded
  * AutoUpgradeTester/profile/eduubuntu/DistUpgrade.cfg:
    - update profile for edubuntu

update-manager (1:0.152.22) oneiric; urgency=low

  * tests/test_update_origin.py, Janitor/computerjanitor/plugin.py:
    - fix tests
  * .bzr-builddeb/default.conf:
    - re-enable pre-build script to ensure we get a updated 
      base-installer, demotions and html Announcements

update-manager (1:0.152.21) oneiric; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - increase the amd64 cache size to 48mb to workaround bug 
      LP: #854090 during the natty -> oneiric upgrade

update-manager (1:0.152.20) oneiric; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - increase the default cache size on a multiarch system to
      avoid potential crash in natty apt (LP: #854090)
  * DistUpgrade/DistUpgradeController.py, UpdateManager/Core/utils.py:
    - do not leak password from sources.list entries into the logfile
      (LP: #839094)
  * UpdateManager/UpdateManager.py:
    - do not crash if a package can not be put into "install" state,
      instead, just keep the old (unmarked) state (LP: #850482)
  * UpdateManager/DistUpgradeFetcher.py:
    - fix crash for changed gtk2 -> gtk3 API (LP: #859862)
  * UpdateManager/backend/InstallBackendAptdaemon.py:
    - remove debug output (LP: #855495)

update-manager (1:0.152.19) oneiric; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - do not use O_SYNC for the apt.log, its not important enough
      to justify the slowdown (LP: #852128)

update-manager (1:0.152.18) oneiric; urgency=low

  [ Michael Vogt ]
  * debian/pycompat:
    - removed, no longer needed
  * debian/rules:
    - fix incorrect invocation of --with=python2
  
  [ Robert Roth ]
  * lp:~evfool/update-manager/handlewarning:
    - Only disconnect handler if it's still connected (LP: #133139)
  * lp:~evfool/update-manager/glibchangefix:
    - Call glib.markup_escape_text() correctly as per current 
      gir (don't pass in string length; LP: #832745)
  * lp:~evfool/update-manager/fixcopylink:
    - Fix the "Copy web link" context menu item of the ChangeLog viewer.
      It did not work before of some Gtk changes, now it does work. 
      Fixes LP: #831944.
  
  [ Stefano Rivera ]
  * extras is another special case where validTo=False (LP: #775694)

update-manager (1:0.152.17) oneiric; urgency=low

  * debian/source-update_manager.py:  ask the reporter if their issue is
    regarding a distribution upgrade if so include log files (LP: #836846)

update-manager (1:0.152.16) oneiric; urgency=low

  * DistUpgrade/DevelReleaseAnnouncement:
    - prepare text for the beta release

update-manager (1:0.152.15) oneiric; urgency=low

  [ Brian Murray ]
  * DistUpgrade/DistUpgradeApport.py: 
    - properly add the tag 'dist-upgrade' to the bug report
  
  [ Michael Vogt ]
  * UpdateManager/backend/InstallBackendAptdaemon.py:
    - fix incorrect initialization
  * fix GLib.timeout_add_seconds() with the new GIR (LP: #829186)
  * call software-properties-gtk without gksu, that is no longer
    needed

update-manager (1:0.152.14) oneiric; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - enable multiarch on amd64 during the upgrade
    - add new "PreCacheOpen" hook and use it for the multiarch 
      enabling
  * DistUpgrade/DistUpgradeCache.py:
    - when checking for missing "priority: required" packages 
      ignore the foreign architecture ones

update-manager (1:0.152.13) oneiric; urgency=low

  [ Robert Roth ]
  * Fix link context menu in changelog viewer (LP: #824957)
  
  [ Michael Vogt ]
  * debian/control:
    - bump unity dependency to gir1.2-unity-4.0 

update-manager (1:0.152.12) oneiric; urgency=low

  [ Michael Vogt ]
  * AutoUpgradeTester/UpgradeTestBackendQemu.py:
    - add NonInterative/AddRepoUpgradeImmediately option that allows
      installing test package *before* the test upgrade runs (useful
      for e.g. testing a new apt or dpkg)

  [ Robert Roth ]
  * Added default value to be able to start UpdateManager without 
    having gir-unity installed (LP: #823935)
  * Fixed changelog test with the new wording
  * Specify default -1 length for terminal response (LP: #817785)

update-manager (1:0.152.11) oneiric; urgency=low

  * DistUpgrade/DistUpgradeViewGtk3.py:
    - use vte.for_command_full() instead of fork_command() as 
      fork_command is no longer available in the gir-2.90
      (LP: #808738)

update-manager (1:0.152.10) oneiric; urgency=low

  [ Michael Vogt ]
  * merged lp:~evfool/update-manager/pkgsections, many thanks
  * debian/control:
    - fix dependency on python-aptdaemon.gtk3widgets
  * DistUpgrade/DistUpgradeController.py:
    - only ask for a reboot if the upgrade is not running inside a
      chroot

  [ Brian Murray ]
  * DistUpgrade/DistUpgradeController.py:
    - when upgrading do not disable deb-src entries in /etc/apt/sources.list
  * DistUpgrade/DistUpgradeMain.py:
    - string fix thanks to David Stansby for the fix (LP: #510681)
  
  [ Robert Roth ]
  * Give clear instructions when the last update timestamp is 
    not found (LP: #821345)
  * Fix operation between NoneType and int (LP: #820126)

update-manager (1:0.152.9) oneiric; urgency=low

  * remove old UpdateManager.glade file
  * rename data/glade to data/gtkbuilder
  * merged lp:~rodrigo-moya/update-manager/use-new-power-interface, 
    thanks to Rodrigo Moya
  * DistUpgrade/DistUpgradeQuirks.py:
    - when upgrading, ensure that zz-update-grub is early in
      /etc/kernel/postinst.d to ensure we always have a good grub
      config and not depend on the package upgrade ordering for that

update-manager (1:0.152.8) oneiric; urgency=low

  [ Robert Roth ]
  * Ordered the packages alphabetically on the dist-upgrade
    confirmation dialog. (LP: #764831)
  * Update last updated text every 15 minutes in the first hour
    after update (LP: #747336). Thanks to Fredrik Ekelund.

  [ Michael Vogt ]
  * UpdateManager/UpdateManager.py, data/glade/UpdateManager.ui:
    - remove old manual text wrap code that is now superseeded by
      gtk3 (LP: #812949)
  * data/glade/UpdateManager.ui:
    - fix the xalign and expand properties of the various alert
      labels

update-manager (1:0.152.7) oneiric; urgency=low

  [ Michael Vogt ]
  * merged lp:~mterry/update-manager/813778 to fix crash in 
    initCache() LP: #813778. Many thanks to Michael Terry
  * add jenkins slave setup (config, upstart job), similar to the
    server-isotesting  (disabled by default)
  * DistUpgrade/DistUpgrade.ui:
    - add minimal size for the details expander (and let glade 
      reindent/reformat the entire file along the way)
  * merged lp:~evfool/update-manager/stringfixes
  
  [ Robert Roth ]
  * Updated translator comment to follow the Ubuntu Units policy
  * Display sizes according to the Ubuntu Units Policy (LP: #410310)
  * Fix ambiguous text explaining updates to running release (LP: #461780)
  * Added label to distinguish candidate version from installed version 
    (LP: #537942)
  * Rename Check all/Uncheck all to Select/Deselect all

update-manager (1:0.152.6) oneiric; urgency=low

  * Only build dist-upgrader tarball in the binary-indep target,
    fixing both the non-x86 build failures, and Soyuz having a
    hissy fit over multiple identically-named files (LP: #813867)

update-manager (1:0.152.5) oneiric; urgency=low

  * DistUpgrade/DistUpgrade{Cache,Controller}.py:
    - if  btrfs snapshots are used, add the additional required 
      diskspace requierd into the free space calculation
  * debian/{rules,control}:
    - move to debhelper 7

update-manager (1:0.152.4) oneiric; urgency=low

  * merged lp:~evfool/update-manager/fix622489, many thanks
    to "FooBar" and Robert Roth (evfool)
  * when downloading the html release notes, ensure to send a
    query string similar to ubiquity to allow more specific
    release notes

update-manager (1:0.152.3) oneiric; urgency=low

  * remove unneeded GConf imports (we are using gsettings now)
    LP: #807715
  * a good bunch of pyflakes fixes

update-manager (1:0.152.2) oneiric; urgency=low

  * data/update-manager.convert:
    - ship gconf->gsettings convert script

update-manager (1:0.152.1) oneiric; urgency=low

  * fix release upgrade view dialog in gtk3
  * UpdateManager/UpdateManager.py, check-new-release-gtk:
    - use GLib.timeout_add(priority, timeout, func, data) instead
      of the old glib.timeout_add()
      thanks to Michael Terry (lp:~mterry/update-manager/pygi-cleanups)
  * check-new-release-gtk, tests/test_end_of_life.py:
    - fix test failures

update-manager (1:0.152) oneiric; urgency=low

  * ported to gtk3/GI
  * port from gconf to gsettings
  * debian/control:
    - depend on python-gobject with overwrite bugfixes needed
      for update-manager

update-manager (1:0.151.10) oneiric; urgency=low

  [ Brian Murray ]
  * In apport hook, collect non-default gconf values.

update-manager (1:0.151.9) oneiric; urgency=low

  * do not crash if lspci is not installed
  * merged lp:~brian-murray/update-manager/apport-hook-changes,
    thanks!
  * merged lp:~eapache/update-manager/unity-urgency-hint, many
    thanks to Evan Huus (LP: #799173)

update-manager (1:0.151.8) oneiric; urgency=low

  * DistUpgrade/DistUpgradeViewGtk.py:
    - set DPKG_UNTRANSLATED_MESSAGES to force untranslated dpkg
      terminal messages for easier package failure duplication 
      detection
  * DistUpgrade/DistUpgradeCache.py:
    - when calculating the size of the space required in /boot use
      the size of the currently running kernel as the base and add
      a small safety margin (LP: #798462). 
  * import new apt-btrfs-snapshot to fix crash for certain fstab
    entries (LP: #806065)

update-manager (1:0.151.7) oneiric; urgency=low

  * fix apt-btfs-snapshot releated crash

update-manager (1:0.151.6) oneiric; urgency=low

  * pre-build.sh:
    - automatically include apt_btrfs_snapshot.py in the release
      uprader tarball

update-manager (1:0.151.5) oneiric; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - warn intel i8xx user that the upgrade to oneiric may cause
      issues with their particular graphics hardware (LP: #774999)
  * merge patch from "eapache" to fix the unity progress bars
    (LP: #796311)

update-manager (1:0.151.4) oneiric; urgency=low

  [ Robert Roth ]
  * Fix problem of showing only integer MB count and causing 
    size inconsistencies

  [ Brendan Donegan ]
  * Updated NetworkManagerHelper with new NM 0.9 states as well as
    updating the UpdateManager itself to handle codes more robustly

  [ Michael Vogt ]
  * merged lp:~brendan-donegan/update-manager/bug791548_networkmanager0.9,
    many thanks
  * merged lp:~evfool/update-manager/fixmbcount, many thanks
  * show progress inside unity, thanks to Bilal Akhtar for the initial
    version of the patch!

update-manager (1:0.151.3) oneiric; urgency=low

  [ Michael Vogt ]
  * merged 
    lp:~brendan-donegan/update-manager/bug699660-fix-settings-shortcut
    thanks to Brendan Donegan
  * AutoUpgradeTester/profile/*:
    - updated for natty->oneiric
  * DistUpgrade/DistUpgradeViewGtk.py:
    - use VteTerminal "child-exit" signal instead of the Reaper object
  * optionally use webkit for the release notes viewer
 
  [ Brian Murray ]
  * do-release-upgrade: display version of the new release available not the
    code name
  * add an apport hook for update-manager and modify bug reporting
    instructions to recommend using apport (LP: #721382)

update-manager (1:0.151.2) oneiric; urgency=low

  * fix UnitySupport import

update-manager (1:0.151.1) oneiric; urgency=low

  * merged lp:~bilalakhtar/update-manager/unity-quicklist,  many
    thanks to Bilal Akhtar for adding quickly support
  * merged lp:~mvo/update-manager/for-unity to make the support
    optional and to add updates count into the update-manager 
    icon in unity

update-manager (1:0.151) oneiric; urgency=low

  * merged lp:~evfool/update-manager/sectionchecks, many thanks
    to Robert Roth
  * DistUpgrade/*:
    - updated for oneiric
  * fix arguments from "autInst" to "auto_inst" and
    "autoFix" -> "auto_fix"

update-manager (1:0.150.2) natty-proposed; urgency=low

  * debian/control:
    - point to "natty" branch
  * DistUpgrade/DistUpgrade.cfg:
    - remove "kde-plasmoid-cwp" early as it will break upgrades
      later (LP: #773022)
  * DistUpgrade/DistUpgradeCache.py:
    - do not fail if not all meta-package can not be upgraded, packages
      like ubuntu-desktop and xubuntu-desktop have implicit conflicts
      LP: #775411

update-manager (1:0.150.1) natty-proposed; urgency=low

  [ Brian Murray ]
  * DistUpgrade/DistUpgradeApport.py: 
    - do not report zero size attachments (LP: #772052)
  * DistUpgrade/DistUpgrade.cfg:
    - enable apport for distribution upgrades (LP: #772913)
  * DistUpgrade/DistUpgradeController.py:
    - use service to start apport

  [ Michael Vogt ]
  * DistUpgrade/DistUpgrade.cfg:
    - Remove 'dontzap' from kubuntu-desktops rules (LP: #769680).
      This fixes a upgrade issue when a old package is leftover

update-manager (1:0.150) natty; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py, tests/test_quirks.py:
    - don't print a error for already patched files, this removes
      a misleading error from the upgrade logs
    - update tests

update-manager (1:0.147.6) natty; urgency=low

  * AutoUpgradeTester/profile/{euca-cloud,euca-nc,xubuntu}/DistUpgrade.cfg:
    - updated for maverick->natty now that the auto-upgrade-test server
      has more diskspace
  * DistUpgrade/DistUpgradeController.py, DistUpgrade/DistUpgradeMain.py:
    - make running-under-ssh check more robust by looking for sshd parent
  * DistUpgrade/DistUpgradeViewText.py:
    - make user confirm information() messages before continuing
      (important for e.g. the "sshd has started" message)
  * DistUpgrade/DistUpgradeQuirks.py, DistUpgrade/DistUpgradeController.py:
    - ensure that new recommends are installed on a desktop mode upgrade 
      even if that got disabled e.g. via synaptic (LP: #759262)
    - add test for this feature

update-manager (1:0.147.5) natty; urgency=low

  * DistUpgrade/DistUpgradeController.py, DistUpgrade/DistUpgradeMain.py:
    - fix ssh detection (LP: #744995)

update-manager (1:0.147.4) natty; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py
   - Allow to view differences in conf file changes LP: #746431

update-manager (1:0.147.3) natty; urgency=low

  * merged lp:~evfool/update-manager/fix665173 (LP: #665173),
    many thanks to Robert Roth (update the test a bit)
  * merged lp:~evfool/update-manager/fix150677 (LP: #150677),
    many thanks to Robert Roth 
  * merged lp:~evfool/update-manager/fix727069 (LP: #727069),
    many thanks to Robert Roth 

update-manager (1:0.147.2) natty; urgency=low

  * UpdateManager/backend/InstallBackendAptdaemon.py:
    - no not trigger a apport exception on user auth issues and if
      the user does not type the password in time (LP: #626798)

update-manager (1:0.147.1) natty; urgency=low

  * UpdateManager/backend/InstallBackendAptdaemon.py:
    - use pkgsystem_unlock, improve exception handling, add test
  * DistUpgrade/DistUpgradeQuirks.py: 
    - add quirks handler for maverick->natty upgrade for the 
      kdegames-card-data case (LP: #745396)
  * tests/test_quirks.py:
    - add test for LP: #745396
  * UpdateManager/UpdateManager.py, do-release-upgrade:
    - point to http://www.ubuntu.com/releaseendoflife when the release
      is end-of-life message is displayed (LP: #671016)
  * DistUpgrade/EOLReleaseAnnouncement:
    - improve wording, this is displayed if the user is trying to upgrade
      from a unsupported version of Ubuntu to a already unsupported
      version. This now links to  http://www.ubuntu.com/releaseendoflife
      (LP: #671016)

update-manager (1:0.147) natty; urgency=low

  [ Brian Murray]
  * UpdateManager/ReleaseNotesViewer.py: fix the path for gnome-open
    and default to xdg-open (LP: #693131) 
  
  [ Michael Vogt ]
  * DistUpgrade/apt_clone.py:
    - use apt_clone.py from the apt-clone package
  * debian/control:
    - add apt-clone to the build-depends
  * DistUpgrade/DistUpgradePatcher.py:
    - add native ed-style patch implementation as e.g. chroots
      may not have ed installed and its critical to be able to 
      ensure that pycompile is correct before the upgrade starts
  * do-release-upgrade:
    - use apt.progress.text.AcquireProgress to fix deprecation warning
  * DistUpgrade/DistUpgradeViewText.py:
    - fix deprecation warning (LP: #744990)
  * fix deprecation warnings in auxiliary scripts
  * DistUpgrade/DistUpgradeAptCdrom.py:
    - fixes with the python-apt 0.8 API

update-manager (1:0.146.6) natty; urgency=low

  * DistUpgrade/DevelReleaseAnnouncement:
    - fix description to say "BETA"
  * pre-build.sh:
    - cleanup cruft test leftover output

update-manager (1:0.146.5) natty; urgency=low

  * fix FTBFS by including a apt_clone.py copy until apt-clone
    makes it through NEW

update-manager (1:0.146.4) natty; urgency=low

  * DistUpgrade/DistUpgradeMain.py, DistUpgrade/apt_clone.py: 
    Use apt-clone to create system-state instead of custom one
    (apt-clone_system_state.tar.gz)
    This makes reproducing problems a lot easier as apt-clone restore
    <statefile> can be used. It also means that ubiquity can pick up
    failed upgrades from the state file and finish them.

update-manager (1:0.146.3) natty; urgency=low

  * DistUpgrade/DistUpgradeAptCdrom.py, DistUpgrade/DistUpgradeController.py:
    - comment out cdrom source after alternative CD based upgrade
  * DistUpgrade/DistUpgradeController.py:
    - show error message when cdrom fails to add
  * tests/test_cdrom.py:
    - add test for cdrom commenting

update-manager (1:0.146.2) natty; urgency=low

  [ Michael Vogt ]
  *  data/glade/UpdateManager.ui, UpdateManager/UpdateManager.py:
    - improve wording of roaming warning, thanks to Alex Chiang
    - make the roaming warning label wrap
  * UpdateManager/UpdateManager.py:
    - fix crash in  _get_last_apt_get_update_text (LP: #712346)
    - do not try to download changelogs if NM reports we are
      disconnected (LP: #19372)

  [ Julian Taylor ]
  * use dh_installman to install manpages
  * move do-release-upgrade manpage to update-manager-core (LP: #695186)

  [ Martin Pitt ]
  * debian/control: Update Breaks:/Conflicts: for the moved manpage.

update-manager (1:0.146.1) natty; urgency=low

  [ Michael Vogt ]
  * merged lp:~evfool/update-manager/fix689034:
    - Some basic string fixes (lp:#689034), thanks to Robert Roth
  * UpdateManager/Core/roam.py:
    - add backend for roaming detection, thanks to Alex Chiang
    - display warning when on 3g and when roaming (fixes half of 
      LP: 323108)
  * merged lp:~thibault-lemaitre/ubuntu/natty/update-manager/from_pkg.isInstalled_to_pkg.is_installed
    that fixes a bunch of deprecated python-apt issues (many thanks!)

  [ Lionel Le Folgoc ]
  * UpdateManager/UpdateManager.py: try to reboot using consolekit if
    gnome-session isn't present (fixes rebooting on Xfce and LXDE, lp: #530161).

update-manager (1:0.146) natty; urgency=low

  * DistUpgrade/DistUpgradeView*.py:
    - pass apt.Package object to the view instead of strings, this
      allows to show additional info on the packages (like summary
      or size)
  * DistUpgrade/DistUpgradeViewGtk.py:
    - check for libgtk2-perl for debconf support
  * AutoUpgradeTester/install_blacklist.cfg:
    - update blacklist for creating main-all images
  * UpdateManager/ReleaseNotesViewer.py:
    - use monospace font (LP: #153228)
  * DistUpgrade/DistUpgradeController.py:
    - perform btrfs snapshot on upgrade if apt-btrfs-snapshot is 
      available

update-manager (1:0.145.13) natty; urgency=low

  * fix ReleaseAnnoucement.html auto generation

update-manager (1:0.145.12) natty; urgency=low

  * debian/control:
    - drop build-depend on fglrx-modalias
  * DistUpgrade/DistUpgradeQuirks.py:
    - port fglrx-modalias checking code to new modaliases support from
      the pkgrecords
  * tests/test_quirks.py:
    - update tests

update-manager (1:0.145.11) natty; urgency=low

  * debian/91-release-upgrade:
    - test if the script exists before running it (thanks to
      Kees Cook)
  * pre-build.sh:
    - auto generate html files from the *ReleaseAnnoucement
      files
  * merged 
    lp:~brendan-donegan/update-manager/updated-signal-and-no-update-option
    (many thanks)

update-manager (1:0.145.10) natty; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - fixup internal (ed) based patching tool
  * DistUpgrade/patches/
    - add pycompile patch to ensure clean upgrade even when maverick-updates
      is not available (LP: #689615)
  * AutoUpgradeTester/profile/server/DistUpgrade.cfg:
    - updated for maverick
  * DistUpgrade/DistUpgradeCache.py:
    - minor python-apt 0.8 API update
  * tests/patchdir/_patchdir_foo.f41121a903eafadf258962abc57c8644:
    - update test for latest internal patching tool

update-manager (1:0.145.9) natty; urgency=low

  * fix FTBFS
  * improve install-backend error checking

update-manager (1:0.145.8) natty; urgency=low

  * remove update-manager-hildon

update-manager (1:0.145.7) natty; urgency=low

  * UpdateManager/backend/InstallBackendAptdaemon.py:
    - updated for aptdaemon 0.40
  * merged lp:~alexlauni/update-manager/dbus, many thanks

update-manager (1:0.145.6) natty; urgency=low

  * debian/rules:
    - build with --skip-private, otherwise dh_python2 will generate
      a incorrect maintainer script for the auto-upgrade-tester package
      that contains a invalid version range string

update-manager (1:0.145.5) natty; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeViewText.py:
    - start with gnu screen integration
  * DistUpgrade/DistUpgradeController.py:
    - when starting a additional sshd detect if there is a firewall
      running and if so print information that the additional sshd
      may need to be added to the firewall rules
  * UpdateManager/Core/utils.py:
    - add iptables_active() helper
  * merged lp:~brian-murray/update-manager/has-completed, many thanks
    This fixes issues with the English past tense
  * merged lp:~mvo/update-manager/use-screen-in-text-frontend, this
    will use screen in the text version of the release upgrader
  * Janitor/plugins/dpkg_status_plugin.py, DistUpgrade/DistUpgradeViewGtk.py:
    - fix python-apt 0.8 API
  * merged lp:~kelemeng/update-manager/bug633036 (LP: #633036), many
    thanks to Gabor Kelemen
  * debian/rules, debian/control:
    - use dh_python2 instead of python-central and drop it from the
      build-depends

  [ Colin Watson ]
  * DistUpgrade/*ReleaseAnnouncement:
    - Fix "Narwahl" typo (LP: #684050).

update-manager (1:0.145.4) natty; urgency=low

  * DistUpgrade/*.ui:
    - updated window main heading for 11.04
  * merged lp:~brian-murray/update-manager/upgrade-canceled-wording
    with wording and style fixes, many thanks!
  * DistUpgrade/DistUpgradeCache.py, UpdateManager/Core/utils.py:
    - check if running inside a chroot and if so, skip kernel
      selection
  * UpdateManager/Core/MetaRelease.py:
    - improve error checking and only present upgrade button if there
      is a working network
    - cleanup hardy code

update-manager (1:0.145.3) natty; urgency=low

  * do-release-upgrade:
    - output if the current release is no longer supported
      (part of other-ps-n-testing-upgrades-for-preinstall-hw)
  * check-new-release-gtk:
    - show "dist-no-longer-supported" dialog if the current 
      release is no longer supported
    - automatically "unignore" a previously ignored upgrade if
      the current release becomes EOL
  * AutoUpgradeTester/profile/*/DistUpgrade.cfg:
    - update to auto test maverick to natty
  * DistUpgrade/DistUpgrade.cfg:
    - update kernel removal for natty too

update-manager (1:0.145.2) natty; urgency=low

  [ Barry Warsaw ]
  * Add required details to .emit() call.  (LP: #631328)
  
  [ Michael Vogt ]
  * debian/control:
    - add or-dependency for python-aptdaemon-gtk and drop gksu 
      dependency (its either brought in via synaptic or not needed)
  * UpdateManager/Core/utils.py:
    - add get_arch() call
  * DistUpgrade/DistUpgradeController.py, DistUpgrade/DistUpgradeQuirks.py:
    - use new utils.get_arch() call
  * merged fixes from lp:~ubuntu-core-dev/update-manager/maverick
  * debian/rules:
    - push EOLReleaseAnnouncement to the server too

update-manager (1:0.145.1) natty; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/EOLReleaseAnnouncement:
    - add information for the time when the release is EOL
      (part of the fix for #671016)
  * UpdateManager/UpdateManager.py:
    - fix typo in EOL text
  * DistUpgrade/DistUpgradeController.py:
    - properly log excepition in the child to the main.log, thanks
      to Jonathan Davies
  
  [ Barry Warsaw ]
  * In Python 2.7, locale.format() input test has gotten more strict.  It
    does not allow trailing text after the format string.  Change this to
    locale.format_string().  See Python issue 10379.  (LP: #673297)

update-manager (1:0.145) natty; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/*:
    - updated for natty
  * tests/test_prerequists.py:
    - fix jaunty test now that this is moved to old-releases.ubuntu.com
  * pre-build.sh:
    - run testsuite on bzr-buildpackage 
  * tests/test_dist_upgrade_fetcher_core.py:
    - fix test failures and ensure its python-apt 0.8 clean
  * po/update-manager.pot:
    - updated
  * DistUpgrade/DistUpgradeCache.py:
    - do not crash if no acquire progress is given
  * DistUpgrade/DistUpgradeController.py, 
    DistUpgrade/DistUpgradeViewNonInteractive.py,
    UpdateManager/Core/DistUpgradeFetcherCore.py,
    tests/test_update_origin.py,
    tests/test_sources_list.py:
    - fixes in the python-apt 0.8 API
  * tests/*.py:
    - fix natty test failures

  [ Bilal Akhtar ]
  * UpdateManager/UpdateManager.py:
    - add more meaningful text if info is out-of-date (LP: #35009)

update-manager (1:0.142.22) maverick-proposed; urgency=low

  [ Barry Warsaw ]
  * Add required details to .emit() call when running with
    synaptic as the backend (LP: #631328)
  
  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeQuirks.py:
    - fixes in the cmov quirks handler (LP: #587186)
      (thanks to Jean-Baptiste Lallement)

update-manager (1:0.142.21) maverick-proposed; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - abort the upgrade if the user runs on a i586 or a i686
      with no "cmov" support (LP: #587186)

update-manager (1:0.142.20) maverick-proposed; urgency=low

  [ Michael Vogt ]
  * UpdateManager/UpdateManager.py:
    - do not crash if the free space check fails (LP: #656881)
  * DistUpgrade/DistUpgrade.cfg:
    - add blcr-dkms to the "BadVersions" variable. The current blcr-dkms
      source will not build with 2.6.35. Adding it here will cause the
      upgrade to abort with a message if it is installed. 
      It also means that if support for 2.6.35 is added to blcr-dkms via
      a SRU that will automatically unblock the upgrade (LP: #555729)
  * DistUpgrade/DistUpgradeViewGtk.py,
    DistUpgrade/DistUpgradeViewKDE.py,:
    - workaround dpkg not sending the correct filename on conffile
      prompts over the status-fd (LP: #656912)

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeViewKDE.py:
    - disable confDialogue.show_difference_button, workaround for 
      "distupgrade crashed during conf file change review" (LP: #656876)
      requires release note that user needs to view changes manually on command line

update-manager (1:0.142.19) maverick; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - only add extras.ubuntu.com for systems that have the matching
      keyring (LP: #653200). This ensures its not added on a server
      upgrade.

update-manager (1:0.142.18) maverick; urgency=low

  [ Alessandro Ghersi ]
  * DistUpgrade/DistUpgrade.cfg:
    - make sure that kbluetooth gets removed on upgrade (LP: #653838)

  [ Jonathan Riddell ]
  * Add kubuntu-devel-release-upgrade to setup.py

update-manager (1:0.142.17) maverick; urgency=low

  [ Jonathan Riddell]
  * Add kubuntu-devel-release-upgrade script to run the upgrade 
    command for Kubuntu
  
  [ Michael Vogt ]
  * if foomatic-db-gutenprint needs to be removed during the upgrade
    because its not compatible with foomatic-db-compressed-ppds,
    try replacing it with ijsgutenprint-ppds which is the same content,
    just compressed in the same way like foomatic-db-compressed-ppds
    (LP: #647460)

update-manager (1:0.142.16) maverick; urgency=low

  * DistUpgrade/ReleaseAnnouncement:
    - add link to http://www.ubuntu.com/desktop/features to tell
      users about the new features in this release
  * DistUpgrade/DistUpgrade.cfg:
    - help the upgrade by removing printconf, foomatic-db-gutenprint 
      and ebox-printers as they are not compatible with 
      foomatic-db-compressed-ppds (LP: #647460)

update-manager (1:0.142.15) maverick; urgency=low

  * po/*.po:
    - updated from launchpad translations for the RC candidate
  * DistUpgrade/DevelReleaseAnnouncement:
    - updated for RC

update-manager (1:0.142.14) maverick; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/mirrors.cfg:
    - add extras.ubuntu.com to known mirrors
  * DistUpgrade/DistUpgradeQuirks.py:
    - add extras.ubuntu.com on upgrade
  * AutoUpgradeTester/jeos/create-base-image.sh:
    - add workaround for issue with python-vm-builder that generates
      random filenames in maverick
  
  [ Gabor Kelemen ]
  * Fix invocation of gksu, use the correct .desktop file.
    Fixes LP: #640906
  * Correct misplaced parentheses, so that l10n of strings will 
    work. Fixes LP: #640972

update-manager (1:0.142.13) maverick; urgency=low

  * DistUpgrade/DistUpgradeView.py:
    - only show demotions if we have at least one

update-manager (1:0.142.12) maverick; urgency=low

  * DistUpgrade/DevelReleaseAnnouncement:
    - updated for beta

update-manager (1:0.142.11) maverick; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - fix incorrect paramter passed to confirmChanges in doPostUpgrade
      (thanks to Jonathan Riddel, LP: #624599)

update-manager (1:0.142.10) maverick; urgency=low

  * UpdateManager/UpdateManager.py:
    - when NM thinks we have no network, do not disable the
      install button because for dialup users NM is frequently wrong
      and does not get that there is a network-connection (LP: #624894)
      (thanks to Mohamed Amine IL Idrissi)

update-manager (1:0.142.9) maverick; urgency=low

  [ Mohamed Amine IL Idrissi ]
  * UpdateManager/UpdateManager.py: Changed the whitespace place to not
    confuse translators, many thanks Milo Casagrande (LP: #621373)
  * DistUpgrade/DistUpgradeView.py: There won't be two spaces in
    FuzzyTimeToStr when days or hours are > 0 and hours or minutes are
    equal to 0 (LP: #288912)
  
  [ Michael Vogt ]
  * remove the seperate demotions dialog and move it into the 
    "Confirm changes" step
  * use a treeview instead of a list to show the details of the
    changes in the gtk frontend
  * UpdateManager/UpdateManager.py, data/glade/UpdateManager.ui:
    - fix label wraping for label_downsize

update-manager (1:0.142.8) maverick; urgency=low

  * UpdateManager/Core/utils.py:
    - fix typo (LP: #615923)
  * UpdateManager/UpdateManager.py:
    - when NM thinks we have no network, do not disable the buttons
      because for dialup users NM is frequently wrong and does not 
      get that there is a network-connection (thanks to "gambs")

update-manager (1:0.142.7) maverick; urgency=low

  [ Mohamed Amine IL Idrissi ]
  * Cache is no 
  longer initialized when an operation is not authorized.
    LP: #394608
  * List of updates is active when there are only kept packages.
    LP: #601127 (thanks, Nicolò Chieffo)
  
  [ Michael Vogt ]
  * merged  lp:~simono/update-manager/fixes-bug-563640, many thanks
    (LP: #563640)
  * merged lp:~yofel/update-manager/lp601127 (LP: #601127)
  
  [ Jean-Baptiste Lallement ]
  * UpdateManager/Core/MyCache.py:
    - catch network error when fetching 3rd party changelogs 
      (LP: #565896)

  [ Brian Murray ]
  * UpdateManager/UpdateManager.py: grammar fix

update-manager (1:0.142.6) maverick; urgency=low

  [ Mohamed Amine IL Idrissi ]
  * Implemented battery and network alerts directly in the main window.
    LP: #484249, #426708, #426710, #494772

  [ Michael Vogt ]
  * UpdateManager/Core/MyCache.py:
    - support looking for the changelog by source version
      (and add tests)
  * UpdateManager/Core/utils.py:
    - fix crash when reading the synaptic config (LP: #614170)

update-manager (1:0.142.5) maverick; urgency=low

  * more python-apt 0.8 porting
  * less updates to the progressbar
  * DistUpgrade/DistUpgradeViewNonInteractive.py:
    - fix crash in non-interactive upgrader when a conffile prompt
      is detected

update-manager (1:0.142.4) maverick; urgency=low

  * DistUpgrade/DistUpgradeView.py:
    - fix missing initializer (python0.8 api releated)
      LP: #604250

update-manager (1:0.142.3) maverick; urgency=low

  * merged lp:~and471/update-manager/fix-bug-386196, many thanks
  * DistUpgrade/DistUpgradeView*.py:
    - port progress to new python-apt 0.8 API
  * merged lp:~mdz/update-manager/small-fixes-20100707, many thanks
  * DistUpgrade/DistUpgradeViewGtk.py:
    - call progressbar.set_fraction() less often to avoid too much
      CPU consumption on certain graphic drivers
  * UpdateManager/GtkProgress.py:
    - limit the amount of set_fraction() here too (LP: #595845)
  * UpdateManager/UpdateManager.py:
    - disconnect the model before adding lots of new items, this
      speeds up the building of the view massively

update-manager (1:0.142.2) maverick; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - use privileged port 1022 instead of 9004 when (optinally) 
      starting a additional sshd
  * UpdateManager/UpdateManager.py: 
    - fix crash with --no-focus-on-map
  * data/release-upgrades:
    - set release upgrade policy to "normal" for maverick (instead
      of lts)

update-manager (1:0.142.1) maverick; urgency=low

  * UpdateManager/UpdateManager.py:
    - Show reboot required dialog inline instead of doing a popup
      dialog. When morphing windows land into maverick they can 
      be used to make the inline information more pretty. But
      it should be better than the previous popup dialog

update-manager (1:0.142) maverick; urgency=low

  [ Michael Vogt ]
  * check-new-release-gtk: 
    - fix "ask me later" button time
  * DistUpgrade/DistUpgradeController.py,
    DistUpgrade/DistUpgradeCache.py,
    UpdateManager/Core/MetaRelease.py,
    UpdateManager/Core/utils.py,
    UpdateManager/Core/MyCache.py,
    UpdateManager/Core/UpdateList.py,
    UpdateManager/GtkProgress.py,
    UpdateManager/UpdateManager.py:
    - update for python-apt 0.8 API, add tests (LP: #591236)
  * check-new-release-gtk:
    - remove no longer needed warnings filter

  [ Brian Murray ]
  * string fix for 'is aborted now' to 'has aborted'
  * fix in debian/control

update-manager (1:0.141) maverick; urgency=low

  * UpdateManager/backend/__init__.py:
    - switch to aptdaemon as install backend by default (unless
      the user has UPDATE_MANAGER_FORCE_BACKEND_SYNAPTIC in his
      environment)
    - merged lp:~glatzor/update-manager/ubuntu-glatzor (many thanks!)
  * DistUpgrade/DistUpgradeController.py:
   - use pockets from DistUpgrade.cfg instead of hard-coding them
  * tests/test_sources_list.py:
    - update tests
  * UpdateManager/Core/utils.py:
    - fix url_downloadable and add tests, based on the patch from
      Paulo Albuquerque, many thanks (LP: #396187)
  * UpdateManager/UpdateManager.py:
    - fix typo (thanks to seb128)
  * DistUpgrade/mirrors.cfg:
    - support upgrades when sources.list uses the new
      mirror://mirrors.ubuntu.com/mirrors.txt 
      uri
  * UpdateManager/GtkProgress.py:
    - do not open a cache open progress window, instead show the
      progress inline in the window

update-manager (1:0.140) maverick; urgency=low

  * DistUpgrade/removal_blacklist.cfg:
    - remove gobuntu-desktop from the removal blacklist
  * DistUpgrade/DistUpgradeController.py:
    - start apport only, do not modify any conffile (all versions
      of apport we upgrade from support this now)
  * UpdateManager/UpdateManager.py:
    - fix crash when format string has the wrong number of arguments
      (LP: #569469)
    - fix minor UI resize issue (LP: #572228)
  * DistUpgrade/DistUpgrade.cfg:
    - add ubuntu-netbook (LP: #574279)
  * UpdateManager/Core/MetaRelease.py:
    - add looking for a "UpgradeBroken" tag that contains a reason string
      if the user should not be allowed to perform a release upgrade
  * UpdateManager/UpdateManager.py, do-release-upgrade:
    - honor "UpgradeBroken" flag and error in this case
  * updated to support lucid to maverick upgrades

update-manager (1:0.134.6) lucid; urgency=low

  * fix FTBFS caused by /usr/bin/check-new-release being a symlink
    instead of a real file

update-manager (1:0.134.5) lucid; urgency=low

  * DistUpgrade/DistUpgradeAufs.py:
    - fix crash in aufs (--sandbox mode)

update-manager (1:0.134.4) lucid; urgency=low

  * DistUpgrade/DistUpgrade.cfg, DistUpgrade/DistUpgrade.cfg.hardy:
    - do not enable apport anymore
  * DistUpgrade/DistUpgradeViewGtk.py:
    - set empty dialog titles for error/information dialogs (it looks
      like glade removed those for some reason from the .ui file)
  * DistUpgrade/DistUpgradeAufs.py:
    - fix crash if aufs (--sandbox mode) is used (LP: #562394)
  * DistUpgrade/DistUpgradeMain.py:
    - fix generation of system state file for non-existing dirs/files
      (LP: #561872)
  * UpdateManager/UpdateManager.py:
    - provide a LIST_TOGGLE_CHECKED column as a workaround for orca
      that does not work with values updated via 
      column_install.set_cell_data_func (LP: #561563)
  * update-manager:
    - use gettext.install(unicode=True) to avoid breaking with
      optparse and ja.po (LP: #557804)

update-manager (1:0.134.3) lucid; urgency=low

  * do-release-upgrade:
    - print when a new release is available in "-q" so that the motd
      is correct (thanks to Dustin Kirkland)
  * debian/release-upgrade-motd:
    - add newline after release info (thanks to Dustin Kirkland)

update-manager (1:0.134.2) lucid; urgency=low

  * DistUpgrade/DistUpgradeMain.py:
    - ignore lspci errors
  * UpdateManager/Core/MyCache.py:
    - simplify url schema for third party changelogs (LP: #45129)
  * DistUpgrade/DistUpgradeCache.py:
    - check if the kernel returned from base-installer is downloadable
      (needed on hardy cdrom only upgrades)
  * debian/91-release-upgrade:
    - use a small script instead of a symlink to ensure that dpkg
      treats them as conffiles (LP: #559194)

update-manager (1:0.134.1) lucid; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - honor "DEBIAN_FRONTEND=noninteractive" on pkg failure (LP: #538206)
  * DistUpgrade/DistUpgradeQuirks.py:
    - stop apparmor before dpkg starts on hardy -> lucid upgrades to
      avoid potentially confusing error messages during the upgrade
      (LP: #559433)
  * DistUpgrade/DistUpgradeCache.py, DistUpgrade/build-tarball.sh:
    - include obselte nvidia pkgnames to properly transition old
      to new drivers (LP: #553369)
  * DistUpgrade/DistUpgradeViewText.py:
    - show packages that will be removed (because they were auto installed)
      as well (LP: #558438)
    - fix i18n bug in details output
  * UpdateManager/Core/MyCache.py:
    - support third party changelogs by using  ArchiveURI() and
      append a similar structure as changelogs.ubuntu.com uses 
      (LP: #45129)
  * UpdateManager/Core/MetaRelease.py:
    - do not crash if meta-release file can not be parsed, just remove
      the broken file instead (LP: #558396)

update-manager (1:0.134) lucid; urgency=low

  [ Barry Warsaw ]
  * Bump up the amount of /boot space calculated per kernel.  The current
    value appears to undercount by about 260K/kernel. (LP: #132311)
  
  [ Michael Vogt ]
  * refresh translations from launchpad
  * update "10.04" strings to "10.04 LTS" and unfuzzy translations
  * when requesting the release announcement, append ?lang=current_lang
    to the request URI
  * update quirks for updates from hardy
  * DistUpgrade/DistUpgrade.cfg, DistUpgrade/DistUpgrade.cfg.hardy:
    - add extra protection against video driver removal (LP: #556629)
  * DistUpgrade/DistUpgradeMain.py:
    - improve logging and save system state before performing the 
      upgrade. Suggested by Matt Zimmerman (LP: #551646)

update-manager (1:0.133.11) lucid; urgency=low

  * UpdateManager/GtkProgress.py:
    - remove window title on cache progress (LP: #549936)
  * check-new-release-gtk:
    - if no ReleaseNotesHtml key is found, do nothing (it means the
      meta-release file does not support this client)
  * check-new-release-gtk, UpdateManager/Core/MetaRelease.py: 
    - improve debugging
  * UpdateManager/Core/utils.py:
    - add META_RELEASE_FAKE_CODENAME environment that can be used to
      test/force release upgrades
  * check-new-release-gtk:
    - append language parameter to uri
    - support --debug

update-manager (1:0.133.10) lucid; urgency=low

  * help upgrade by hinting usplash gets removed in favor of 
    plymouth

update-manager (1:0.133.9) lucid; urgency=low

  * DistUpgrade/DistUpgradeController.py, DistUpgrade/DistUpgradeCache.py:
    - do not warn about demoted packages that get removed later anyway
  * DistUpgrade/DistUpgrade.cfg, DistUpgrade/DistUpgrade.cfg.hardy:
    - remove deskbar-applet, and nautilus-cd-burner on ubuntu-desktop
      upgrade   (as discussed with the desktop team)
    - remove notification-daemon in favor of notify-osd in 
      xubuntu-desktop (LP: #546857)
  * DistUpgrade/DistUpgrade.cfg.hardy:
    - remove tracker on hardy ubuntu-desktop upgrade

update-manager (1:0.133.8) lucid; urgency=low

  * DistUpgrade/sources.list.py, distro.py, distinfo.py:
    - temporarily stop embedding from the python-apt build host 
      because of the python-apt api changes, use 0.7.13.5 version 
    instead
  * debian/control:
    - point to lp:~ubuntu-core-dev/update-manager/lucid

update-manager (1:0.133.7) lucid; urgency=low

  [ Nathan Stratton Treadway ]
  * data/release-upgrades
    - Provide better explanation of what how the various options in the
      configuration file control which upgrades are presented to the user.
      (LP: #522910)

  [ Barry Warsaw ]
  * README
    - Minor clean up.
  
  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeCache.py:
    - check if the kernel returned from base-installer is upgradable
      (needed on hardy cdrom only upgrades)
  * check-new-release-gtk:
    - fix "ask me later" button time
  * DistUpgrade/DistUpgradeQuirks.py:
    - fix 386 kernel check/transition on upgrades from hardy
    - move kubuntu-kde4-desktop transition into its own function
  * check-new-release-gtk:
    - use GtkProgress when downloading the release upgrader

  [ Dustin Kirkland ]
  * debian/91-release-upgrade: do the release upgrade check with the
    quiet option to avoid putting debug messages in the MOTD, LP: #548376

update-manager (1:0.133.6) lucid; urgency=low

  * DistUpgrade/DistUpgradeView.py:
    - display the right number of packages that are going to be
      removed
  * DistUpgrade/cdromupgrade:
    - fix cddirname detection when called without a directory prefix
  * DistUpgrade/DistUpgradeViewGtk.py:
    - fix crash in webkit progress

update-manager (1:0.133.5) lucid; urgency=low

  [ Markus Korn ]
  * UpdateManager/Core/utils.py:
    - Modified UpdateManager.Core.utils.on_battery() to use UPower per default
      (and DeviceKit.Power as fallback) to check if a system is running 
      on battery (LP: #539211)
  
  [ Michael Vogt ]
  * DistUpgrade/DistUpgrade.cfg:
    - hint that libparted1.8-12 can be removed to help the upgrader
      logic'
  * DistUpgrade/DistUpgradeViewGtk.py:
    - only run JS progress if there is actually a webkit view
  * DistUpgrade/DevelReleaseAnnouncement:
    - fix text to say that its a BETA release (LP: #544544)
  * DistUpgrade/DistUpgradeViewGtk.py:
    - only run JS updateProgress script if we have a valid slideshow

update-manager (1:0.133.4) lucid; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeController.py, DistUpgrade/DistUpgradeView.py:
    - detect pre-depends cycle and cleanly revert (LP: #516727)
      to the old system state
  * DistUpgrade/DistUpgradeCache.py:
    - only ensure translations are kept if they are still downloadable,
      there is a lot of churn in the translations area so its not 
      feasible to keep them all
    - when checking the kernel list from base-installer, also consider
      kernels that are marked install (LP: #540114)
    - check rdepends of all packages (including auto-removal ones) 
      again ensure the removal blacklist is honored in all cases
      (LP: #540823) 
  * DistUpgrade/DistUpgradeController.py:
    - show progress information when searching for obsolete software
      (this can take a bit on a big install)
  * DistUpgrade/DistUpgradeViewNonInteractive.py:
    - fix crash in non-interactive mode (thanks to Andreas Hasenack)

  [ Colin Watson ]
  * Ship /var/lib/update-notifier directory in update-manager-core, so that
    it's always there for 91-release-upgrade (LP: #540159).

update-manager (1:0.133.3) lucid; urgency=low

  * DistUpgrade/DistUpgrade.cfg, DistUpgrade/DistUpgrade.cfg.hardy:
    - do not allow upgrades to openoffice.org-filter-binfilter that
      causes pre-depends loop (LP: #516727)

update-manager (1:0.133.2) lucid; urgency=low

  * DistUpgrade/DistUpgradeViewNonInteractive.py:
    - fix regression in conffile prompt handling (LP: #538206)
    - add default to the "NonInteractive", "DebugBrokenScripts" 
      config option
  * DistUpgrade/DistUpgradeController.py:
    - honor "DEBIAN_FRONTEND=noninteractive" in recovery mode as
      well (LP: #538206)
  * DistUpgrade/DistUpgrade.cfg:
    - ensure that gtk-qt-engine is removed on upgrade (LP: #532968)

update-manager (1:0.133.1) lucid; urgency=low

  [ Barry Warsaw ]
  * Fix obvious NameError by adding a missing import. (LP: #537250)

  [ David Planella ]
  * Made some strings translatable and extractable as a fix for 
    LP: #537277
 
  [ Michael Vogt ]
  * po/*.po:
    - updated from rosetta
  * DistUpgrade/DistUpgradeApport.py:
    - do not try to add directories under /var/log/dist-upgrade
      to a apport report (LP: #369951)

  [ Shlomi Loubaton ]
  * Set text direction for update treeview to be always LTR regardless
    of current language settings (LP: #316171)

update-manager (1:0.133) lucid; urgency=low

  [ Michael Vogt ]
  * UpdateManager/Core/MetaRelease.py:
    - allow upgrade from unsupported version to unsupported version
  * DistUpgrade/removal_blacklist.cfg:
    - allow removal of update-manager-kde
  * check-new-release-gtk:
    - fixes in the gtk release upgrade check
  * DistUpgrade/xorg_fix_proprietary.py:
    - if /etc/X11/XF86Config-4 is found on upgrade, rename it to
      "XF86Config-4.obsolete"
    - write log to "/var/log/dist-upgrade/xorg_fixup.log"
  * do-release-upgrade, check-new-release:
    - implemented "check-releae-upgrade" as symlink to do-release-upgrade
      and automatically run with "--check-dist-upgrade-only" when called
      as c-r-u
    - add --quiet option to do-release-upgrade
  * debian/update-manager-core.links:
    - install /usr/lib/update-manager/check-new-release as symlink to
      do-release-upgrade -c

  [ Wesley Schwengle ]
  * Check for release upgrade is now also possible with do-release-upgrade
    command: do-release-upgrade -c. (LP: #415026)
  * Added --version/-V to do-release-upgrade (similar to update-manager)

  [ Dustin Kirkland ]
  * debian/91-release-upgrade, debian/update-manager-core.install,
    - some users are complaining of long login times due to the release
      check requiring network connectivity; this information clearly doesn't
      change as frequently as the user logging in, so maintain a cache file
      in /var/lib, display it if it's populated, but otherwise, update it in
      the background if its either missing or the file is older than a day
      old, LP: #522452

  [ Jonathan Riddell ]
  * Do not allow for the removal of update-manager-kde, we do want it after all

update-manager (1:0.132.1) lucid; urgency=low

  * rename update-manager-support-status to ubuntu-support-status
  * check-new-release-gtk:
    - add gtk tool for release notification that is designed to be
      run from update-notifier (desktop-lucid-update-upgrade-requirements)
  * DistUpgrade/DistUpgradeCache.py:
    - fix crash in cleanup code
    - fix crash when /home is missing (LP: #463506)
    - fix component inconsitency detection debug output
  * DistUpgrade/DistUpgradeViewGtk.py:
    - remove old code that moved to python-apt
  * DistUpgrade/DistUpgradeController.py:
    - if universe is not enabled, explain that the demoted packages
      will be suggested for removal in the cleanup stage
  * UpdateManager/Core/MetaRelease.py:
    - fix urlopen() crash on hardy->lucid cdrom upgrades

update-manager (1:0.132) lucid; urgency=low

  [ Michael Vogt ]
  * UpdateManager/Core/MetaRelease.py:
    - add timeout to meta-release download
  * UpdateManager/MetaReleaseGObject.py:
    - make sure threading is enabled
  * DistUpgrade/DistUpgrade.cfg:
    - add kubuntu-netbook to known metapackages
    - remove usplash artwork from KeyDependencies
  * DistUpgrade/DistUpgradeController.py:
    - test for server mode again after the sources.list rewrite,
      to capture the case when the initial sources.list is empty
  * DistUpgrade/DistUpgradeCache.py:
    - when showing the demoted packages, skip packages that
      are automatic installed
    - improve performance on the removal checks by making use of
      the auto removable information more agressively
    - increase space required by the kernel (it grew)
  * DistUpgrade/DistUpgradeView.py, DistUpgrade/DistUpgradeView{Gtk,KDE}.py:
    - show only non auto-installed removals bold
  * update-manager-support-status:
    - add --show-supported, --show-unsupported and --show-all for summary
    - add --list option for full details

  [ Colin Watson ]
  * update-manager-support-status:
    - fix typo in get_maintenance_status (LP: #513303)
    - add support statistics to the output

update-manager (1:0.131.4) lucid; urgency=low

  * update-manager-support-status:
    - text mode tool that gives a overview on the support
      status of the packages
  * DistUpgrade/DistUpgrade.ui, DistUpgrade/window_main.ui:
    - fix version number (thanks to davmor2)
  * DistUpgrade/DistUpgrade.cfg.hardy:
    - fix upgrade target to lucid (LP: #512608)

update-manager (1:0.131.3) lucid; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - add missing check for ubuntu-security when testing for
      mirrors (thanks to Stuart Langridge)
  * DistUpgrade/DistUpgrade.cfg:
    - add example SlideshowUrl
  * DistUpgrade/DistUpgradeController.py, DistUpgrade/DistUpgradeView.py,
    DistUpgrade/DistUpgradeViewGtk.py:
    - add slideshow support based on webkit
    - call percent() JS method on the webkit view
  * check-new-release:
    - use exit codes if run with --quiet otherwise only print
      (LP: #494499)
  * DistUpgrade/DistUpgradeConfigParser.py:
    - fix crash in _interpolate (LP: #500705)
  * UpdateManager/Core/MetaRelease.py:
    - do not crash on stat failure (LP: #496144)
  * UpdateManager/Core/MyCache.py:
    - do not crash if the lock can not be released (LP: #410574)
  * UpdateManager/SafeGConfClient.py
    - implement gconfclient that does not crash if gconf is not 
      working (LP: #261471)

update-manager (1:0.131.2) lucid; urgency=low

  * data/release-upgrades:
    - default to lts->lts upgrade prompts for lucid
  * AutoUpgradeTester/UpgradeTestBackendQemu.py:
    - allow virtio for block devices when the virtio option
      is given in the config
  * DistUpgrade/DistUpgrade.cfg, DistUpgrade/DistUpgrade.cfg.hardy:
    - cleanup PostUpgradePurge and add "linux-restricted-modules-common"
    - cleanup ForcedObsoletes rules
    - update kernel removal rules and BaseNames
    - fix belocs-locales-bin upgrade issue (LP: #474543)
  * DistUpgrade/DistUpgradeController.py:
    - check forh reboot-required files in partial upgrade mode, 
      update-notifier is no longer doing that by default
      (foundations-lucid-restart-required-dialog spec)
  * DistUpgrade/DistUpgrade.ui:
    - add a bunch of missing "<property name="orientation">" 
    - improve restart-required dialog

update-manager (1:0.131.1) lucid; urgency=low

  * DistUpgrade/DistUpgradeViewNonInteractive.py:
    - use getWithDefault() for "NonInteractive","ForceOverwrite"
      (thanks to Free Ekanayaka)
  * UpdateManager/Core/MyCache.py:
    - detect dirty dpkg journal and enter recovery mode in this
      case (thanks to Maco for reporting)
  * DistUpgrade/DistUpgrade.cfg:
    - remove kvm-source on upgrade
  * debian/update-manager-core.links:
    - use "91-release-upgrade" instead of "91-release_upgrade" to
      make run-parts happy
  * fix FTBFS

update-manager (1:0.131) lucid; urgency=low

  * UpdateManager/UpdateManager.py:
    - do not crash if setlocale() fails (LP: #471378)
  * UpdateManager/Core/DistUpgradeFetcherCore.py: 
    - add missing "logging" import (LP: #475941)
  * DistUpgrade/DistUpgradeController.py:
    - better message for upgrades over ssh (LP: #463257)
  * UpdateManager/Core/utils.py:
    - improve proxy check and show error if proxy settings
      look invalid (LP: #472168)
  * AutoUpgradeTester/profile/*/DistUpgrade.cfg:
    - updated to test karimic -> lucid and hardy -> lucid
  * Janitor/plugins/deb_plugin.py:
    - use apt.progress.InstallProgress() to keep the computer-janitor
      UI responsive
  * AutoUpgradeTester/install_blacklist.cfg:
    - add ec2 to the blacklist for the kvm based testing
  * UpdateManager/UpdateManager.py:
    - show selected and download size in two rows (LP: #434062)
  * data/do-release-upgrade.8:
    - man page added, thanks to Willem Bogaerts
  * DistUpgrade/DistUpgrade.cfg:
    - add laptop-mode-tools to the forced obsoletes on upgrade (thanks to
      Steve Langasek)
  * UpdateManager/UpdateManager.py:
    - show restart required dialog in u-m when the upgrade is finished
      with proper parent
  * AutoUpgradeTester/post_upgrade_tests:
    - add python import, xorg and kernel tests
  * UpdateManager/dialog_release_notes.ui:
    - merged lp:~freinhard/update-manager/ui-fix (many thanks)
  * UpdateManager/Core/MetaRelease.py:
    - merge lp:~cristiklein/update-manager/use-xdg (many thanks)

update-manager (1:0.130) lucid; urgency=low

  * UpdateManager/UpdateManager.py:
    - set heading for the release-upgrader download window
  * DistUpgrade/DistUpgradeController.py:
    - force lts for lucid cdrom upgrades
  * AutoUpgradeTester/profile/:
    - fix missing BaseMetaPackages
  * AutoUpgradeTester/UpgradeTestBackendQemu.py:
    - fix AddRepo code
  * DistUpgrade/DistUpgradeConfigParser.py:
    - fix getWithDefault() to use the correct get{int,float,boolean}
      function based on the type of the default (LP: #465619)
      Thanks to Brian Murray for spotting this bug
  * DistUpgrade/DistUpgradeController.py:
    - fix typo (LP: #470011)
  * updated for karmic->lucid upgrades and hardy->lucid upgrades
  * UpdateManager/Core/utils.py::
    - fix url_downloadable() when a proxy needs to be used
      (LP: #446552)

update-manager (1:0.126.9) karmic-proposed; urgency=low

  * DistUpgrade/DistUpgrade.cfg:
    - really stop enabling apport during the upgrade (LP: #465619)

update-manager (1:0.126.8) karmic-proposed; urgency=low

  * when the server is overloaded and no Release file information
    can be obtained, show a better error message instead of the
    bogus "ubuntu-minimal" is missing (LP: #446956)

update-manager (1:0.126.7) karmic-proposed; urgency=low

  * po/*.po:
    - update translations from LP (LP: #460547)
  * UpdateManager/Core/DistUpgradeFetcherCore.py:
    - check if running on a system with noexec /tmp and give a propper
      error message (LP: #461744)
  * DistUpgrade/DistUpgradeViewGtk.py:
    - add missing locale.bindtextdomain() (LP: #460547)

update-manager (1:0.126.6) karmic; urgency=low

  * debian/control:
    - updated to point the karmic branch
  * UpdateManager/GtkProgress.py:
    - fix small cosmetic problem with the release-upgrader
      download window size
  * DistUpgrade/xorg_fix_proprietary.py:
    - if xorg.conf is zero size, remove it (LP: # 439551)
  * change unicode "&#x25E6;" to "*" to make translations
    work (LP: #344693) and unfuzzy translations

update-manager (1:0.126.5) karmic; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - generate note if language-support is incomplete
  * DistUpgrade/DistUpgrade.cfg:
    - stop enabled apport during the upgrade
  * DistUpgrade/DistUpgradeView.py
    - add waitChild implementation from python-apt to ensure
      its working for buggy hardy python-apt
  * DistUpgrade/DistUpgradeQuirks.py:
    - mark mysql-{client,server}-5.0 manual installed in the 
      cluster check (LP: #453513)
    - check if running under a vserver setup and error if this
      is the case. upstart does not support this kind of setup
      (LP: #452011)
  * UpdateManager/Core/utils.py:
    - do not show error if DeviceKit.Power is not available
      (LP: #452004)

update-manager (1:0.126.4) karmic; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - fix running under ssh detection
  * DistUpgrade/DistUpgradeQuirks.py:
    - add check if NBD clustering is in use in mysql server
      and do not upgrade to 5.1 is it is (LP: #450837)
  * DistUpgrade/DistUpgrade.cfg:
    - remove mysql-server rule, this is now done in the above 
      quirks handler
  * DistUpgrade/DistUpgradeController.py:
    - do not do list cleanup so that cancel restores all of the
      previous state. the cleanup will be done later by the apt
      cron job

update-manager (1:0.126.3) karmic; urgency=low

  * UpdateManager/UpdateManager.py:
    - refresh "last updated" text periodically to ensure its
      not stale (LP: #450286)
  * DistUpgrade/DistUpgradeViewGtk.py:
    - deal with io errors when writing the log (LP: #447693)
  * debian/control:
    - add or-dependency to qemu-kvm
  * DistUpgrade/DistUpgrade.cfg:
    - add policykit-gnome and gnome-mount to the forced obsoleted
      packages (thanks to seb128) 
  * merge translations from rosetta
  * DistUpgrade/DistUpgradeQuirks.py:
    - stop docvert-converter when the upgrade starts, otherwise
      OOo will not upgrade at all (LP: #450569)
  * pre-build.sh:
    - fix bug in the demoted.cfg generation
    - fixes in cleanup handling
  * UpdateManager/backend/__init__.py:
    - honor UPDATE_MANAGER_FORCE_BACKEND_APTDAEMON environment
  * DistUpgrade/DistUpgrade.cfg.hardy:
    - updated to include demoted.cfg.hardy

update-manager (1:0.126.2) karmic; urgency=low

  * setup.py:
    - fix FTBFS - the python from two days ago became
      stricter than it used to be (thanks to james_w)

update-manager (1:0.126.1) karmic; urgency=low

  * DistUpgrade/DistUpgradeView.py:
    - log exceptions from pm.DoInstall() into main.log.
      this helps identifiying Dpkg::Pre-Invoke problems
  * DistUpgrade/DistUpgradeCache.py:
    - fix sandbox upgrade mode
  * DistUpgrade/DistUpgrade.cfg:
    - hint for mysql-server upgrade (LP: #413789)
  * UpdateManager/backend/__init__.py:
    - change order of backends to: synaptic, aptdaemon

update-manager (1:0.126) karmic; urgency=low

  * DistUpgrade/DistUpgrade.cfg:
    - add gnome-app-install to the ForcedObsoletes
  * DistUpgrade/DistUpgrade.cfg.hardy:
    - add ability to upgrade from hardy to karmic (as asked for
      by Jonathan Riddell)
  * DistUpgrade/DistUpgradeQuirks.py:
    - add quirk handler to mark the dependencies of
      language-support-translations-* as manual on upgrade
  
      The language-support-translations- packages are removed in 
      karmic and would otherwise be marked as auto-removable.
      (LP: #439296)
    - convert PASS value from 1 to 0 for ntfs entries in
      /etc/fstab (LP: #441242) and add tests for it
    - put 386 to generic transition code here and decouple from
      the kernel selection
    - inhibit gnome-screensaver once the upgrade started 
      to avoid X crash (LP: #439594)
  * DistUpgrade/DistUpgradeCache.py:
    - workaround issues with kdesu when it drop the permission bits
      in a tmpdir (thanks to Jonathan Riddell)
    - fix base-installer kernel selection (LP: #441629)
    - fix log dir does not exist, create it (LP: #441959)
  * UpdateManager/backend/InstallBackendAptdaemon.py:
    - give up lock before running aptdaemon (LP: #445920)
  * po/ 
    - updated from launchpad (required as during a release upgrade
      we can't use langpacks)

update-manager (1:0.125.6) karmic; urgency=low

  * AutoUpgradeTester/UpgradeTestBackendSSH.py:
    - use ssh batch mode
  * AutoUpgradeTester/auto-upgrade-tester:
    - show log files
  * DistUpgrade/DevelReleaseAnnouncement:
    - update for BETA
  * DistUpgrade/DistUpgradeCache.py:
    - add new rule to ensure that base meta packages are always
      kept installed. this helps the server upgrade with the syslogd
      to rsyslog transition

update-manager (1:0.125.5) karmic; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py 
    - fix kbluetooth name to kbluetooth4

update-manager (1:0.125.4) karmic; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - fix brown paperbag bug in quirks hanlding  (LP: #436302)
  * DistUpgrade/DistUpgradeViewGtk.py:
    - fix crash in gettext initialization (LP: #436438)

update-manager (1:0.125.3) karmic; urgency=low

  * DistUpgrade/DistUpgrade.cfg.hardy:
    - fix upgrades from hardy by allowing the removal of sysvutils
  * data/glade/UpdateManager.ui:
    - remove dialog title for cache open progress (LP: #435653)
  * DistUpgrade/DistUpgradeQuirks.py:
    - add translators hints for some strings (LP: #433116)
  * UpdateManager/Core/DistUpgradeFetcherCore.py:
    - fixed typo (thanks to Henrique P. Machado)
  * UpdateManager/UpdateManager.py:
    - fix i18n issues with gtkbuilder
  * DistUpgrade/DistUpgradeQuirks.py:
    - stop kblueplugd kbluetooth when the upgrade starts to
      avoid them crashing during the upgrade 
      (thanks to Jonathan Riddell)
  * UpdateManager/backend/InstallBackendAptdaemon.py
    - setup correct window icon
  * data/glade/UpdateManager.ui:
    - switch from unicode &#x2026; to "..." until the issues with
      gettext is resolved (LP: #434107)

update-manager (1:0.125.2) karmic; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeCache.py:
    - add check for 5Mb safety buffer in /tmp, this ensures that
      dkms can run and ensure we do not run when /tmp is mounted
      in overflow mode (LP: #427035)
  * data/glade/UpdateManager.ui:
    - remove dialog title for the battery warning and fix button
      order (thanks to Matthew Paul Thomas)
  * data/glade/UpdateManager.ui:
    - fix duplicated accelerator keys (LP: #425817)
  * UpdateManager/UpdateManager.py:
    - close app when ESC is pressed in the battery warning
  * UpdateManager/UpdateManager.py:
    - ensure that the changelog always matches the currently selected
      pkg by fixing race during download (LP: #424918) 
  * UpdateManager/backend/InstallBackendAptdaemon.py:
    - do not hang when cancel is clicked (LP: #426718)
  * add sed patch facility and patch the gnome debconf frontend 
    before the upgrade starts so that it can not crash when 
    perl moves from 5.8.0 to 5.10.0 (LP: #387112)
  * data/glade/UpdateManager.ui:
    - use bigger default width (LP: #418201)

  [ Brian Murray ]
  * typo fixes (thanks to Brian Murray, LP: #423409)

update-manager (1:0.125.1) karmic; urgency=low

  [ Josh Holland ]
  * Fixed several typos (LP: #93804, LP: #277731, LP: #404435)
  
  [ Rugby471 ]
  * Center window on the screen (LP: #423355)
  
  [ Michael Vogt ]
  * DistUpgrade/DistUpgrade.ui:
    - remove unused "destroy_event" handler (LP: #428842)
    - remove unused handlers to avoid RunTime warning
  * DistUpgrade/DistUpgradeQuirks.py:
    - make ARMv6 error message clearer (LP: #409523)
  * UpdateManager/Core/MetaRelease.py:
    - more robustness for invalid configuration of the meta-release
      file (LP: #428558)
    - more robustness if the server sends invalid meta-release data
  * UpdateManager/GtkProgress.py:
    - make button_cancel click event work
    - add sensible default width
  * DistUpgrade/DistUpgradeCache.py:
    - fix crash in partial upgrade (LP: #428203)

update-manager (1:0.125) karmic; urgency=low

  [ Michael Vogt ]
  * integrate base-installer as a sub-component into the
    release upgrader and use the base-installer/kernel/*.sh
    functionality to ensure we select the most appropriate
    kernel on upgrade (LP: #353534)
  * integrate automatic updates to base-installer into the
    pre-build.sh bzr hook
  * UpdateManager/Core/UpdateList.py, UpdateManager/UpdateManager.py:
    - filter warnings
  * UpdateManager/SimpleGtkbuilderApp.py:
    - use logging instead of sys.stderr
  * data/glade/UpdateManager.ui:
    - set explicit translation domain
  * integrate base-installer component into auto-upgrade-tester
  
  [ Steve Langasek ]
  * Refresh .pot file (and .po files) so that new UI strings are available
    for translation in LP.  LP: #425014.

update-manager (1:0.124.11) karmic; urgency=low

  * DistUpgrade/DistUpgradeView.py:
    - capture exceptions from pm.DoInstall() properly (fixes a 
      hang when a package fails to install)
  * DistUpgrade/DistUpgradeViewGtk.py, DistUpgrade/DistUpgradeViewKDE.py:
    - return the full status of the exited child, not only the
      return code

update-manager (1:0.124.10) karmic; urgency=low

  * DistUpgrade/removal_blacklist.cfg:
    - add update-manager so that it does not 
  * typo fixes (thanks to Brian Murray, LP: #418127)
  * merge the changes of seb128 into bzr
  * po/POTFILES.in:
    - fix ui file detection (thanks to Gabor Kelemen) LP: #420209
  * DistUpgrade/DistUpgrade.ui:
    - fix duplicated id (LP: #422665)
  * fix crash when lsmod is not installed

update-manager (1:0.124.9ubuntu1) karmic; urgency=low

  * Clean build directory

update-manager (1:0.124.9) karmic; urgency=low

  * data/glade/UpdateManager.ui:
    - don't use some duplicated ids to fix update-manager not starting
      due to the new gtk version

update-manager (1:0.124.8) karmic; urgency=low

  * make the release-upgrader auto selection for the frontend
    more robust when no DISPLAY is avaiable
  * Janitor/computerjanitor/package_cruft.py:
    - use unicode string here (thanks to liw)
  * data/glade/UpdateManager.ui:
    - fix duplicated symbol (LP: #417301)
  * UpdateManager/UpdateManager.py:
    - show the on-battery warning on first map only (LP: #416067)
  * DistUpgrade/DistUpgradeController.py:
    - do not how a error when the upgrade is canceled by the user
      during download

update-manager (1:0.124.7) karmic; urgency=low

  * UpdateManager/UpdateManager.py:
    - recalulcate the heading label size dynamically
      to work around bugzilla #101968 (thanks to
      Juergen Kazmirzak for the patch)
  * UpdateManager/backend/__init__.py:
    - fix incomplete check for aptdaemon
  * UpdateManager/backend/InstallBackendAptdaemon.py:
    - update for latest aptdaemon
  * DistUpgrade/DistUpgradeController.py:
    - merge fixes from Brian Murray (thanks!), LP: #404274

update-manager (1:0.124.6) karmic; urgency=low

  [ Oliver Grawert ]
  * DistUpgrade/DistUpgradeQuirks.py: add check for ARMv6 or 
    greater to prevent jaunty->karmic upgrades on unsupported 
    armel CPU arches

  [ Michael Vogt ]
  * UpdateManager/SimpleGtkbuilderApp.py:
    - updated to deal with widgets that overwrite get_name
  * update-manager:
    - add "--data-dir" switch
  * use aptdaemon as the install backend (if avaialble)

update-manager (1:0.124.5) karmic; urgency=low

  * debian/update-manager-core.links: change the update-motd link for
    release_upgrade to match other links (- instead of _), and move it
    to 91 (just after updates-available at 90), such that it's printed
    toward the end of the MOTD, rather than at 10, which is the beginning.

update-manager (1:0.124.4) karmic; urgency=low

  * debian/control: recommend libpam-modules, rather than update-motd

update-manager (1:0.124.3) karmic; urgency=low

  [ Michael Vogt ]
  * UpdateManager/UpdateManager.py:
    - fix description display (LP: #379945), thanks
      to Richard Thomas
    - fix crash in refresh_updates_count()
  * DistUpgrade/DistUpgradeApport.py:
    - deal with errors from apport better (LP: #357339),
      thanks to Patrick Horn)
  * UpdateManager/ChangelogViewer.py:
    - fix problem for http://host/document.html. style 
      entries (LP: #396393)

  [ Dustin Kirkland ]
  * debian/update-manager-core.links: install 10_release_upgrade
    into /etc/update-motd.d, rather than the daily; update-motd-3.0
    will now run these scripts on login, rather than at specified
    intervals

update-manager (1:0.124.2) karmic; urgency=low

  * UpdateManager/UpdateManager.py:
    - make it clearer if a package is a new install
      (as opposed to a upgrade) - thanks to Cody Sommerville
    - show amount of selected updates in the UI (LP: #330439)

update-manager (1:0.124.1) karmic; urgency=low

  * fix ftbfs

update-manager (1:0.124) karmic; urgency=low

  * AutoUpgradeTester:
    - add kubuntu, main-all, lts-server, lts-ubuntu profiles
  * ported to gtkbuilder
  * UpdateManager/UpdateManager.py:
    - warn if running on battery (LP: #377697)
    - make it less stealty by setting the stick() property if
      run in auto-open mode (LP: #369820)

update-manager (1:0.123) karmic; urgency=low

  * debian/control:
    - build auto-upgrade-tester package to allow easy upgrade
      testing with a set of default profiles
  * UpdateManager/Core/MyCache.py:
    - wording fix (thanks to Ng)
  * DistUpgrade/DistUpgradeViewNonInteractive.py:
    - fix bug in dpkg_progress_log filea
  * AutoUpgradeTester/UpgradeTestBackend.py:
    - import the http_proxy from the environment
    - make the resultdir configrable and default to
      /var/cache/auto-upgrade-tester/result/
  * AutoUpgradeTester/UpgradeTestBackendQemu.py:
    - make the path for the kvm working images configurable
      and default to /var/cache/auto-upgrade-tester
  * AutoUpgradeTester/auto-upgrade-tester:
    - move login() into the backends
  * AutoUpgradeTester/auto-upgrade-tester:
    - allow shorthand profile names like "ubuntu" instead of
      full pathes

update-manager (1:0.122) karmic; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - add handler to check for wl module and transition
      to bcmwl-kernel-source (LP: #381684)
  * DistUpgrade/DistUpgradeViewNonInteractive.py:
    - add bool option "NonInteractive/DpkgProgressLog" to write
      a timing log of the upgrade (for the foundations-karmic-pre-unpacking
      spec)
    - add "NonInteractive/DebugBrokenScripts" option that will re-run
      failed maintainer scripts with debug options
  * DistUpgrade/DistUpgrade.cfg:
    - add defaults for the NonInteractive section that match the 
      interactive upgrades (for better landscape support)
    - enable apport again
  * AutoUpgradeTester/chart_dpkg_progress.py:
    - add simple tool that can read the dpkg progress information

update-manager (1:0.121) karmic; urgency=low

  * DistUpgrade/DistUpgrade.cfg:
    - remove obsolete kubuntu-kde4-desktop meta package
  * DistUpgrade/DistUpgradeCache.py:
    - when guessing missing meta-packages stop after
      the first one was found
    - use internal _lookupPkgRecord() instead of 
      pkg._lookupRecord
  * DistUpgrade/DistUpgradeQuirks.py:
    - move the kubuntu-kde4-desktop key dependency transition
      detection to the from_hardy quirks handler (LP: #368459)
  * UpdateManager/Core/MyCache.py:
    - always disable version number range of the changes in the
      details (LP: #251349)
    - make the distro supporting the changelogs easier to customize
  * DistUpgrade/xorg_fix_proprietary.py:
    - better comment when explaining why stuff got commented out
      (LP: #300504)
  * DistUpgrade/DistUpgradeController.py:
    - after updating the sources.list, check for both existance
      and downloadability of the BaseMetaPkgs and abort if that
      is not the case (thanks to Ulrich Kalkkuhl) LP: #370062
  * UpdateManager/UpdateManager.py:
    - show origin field for other updates (like PPAs) to make it
      easier to see what comes from where (part of the 
      foundations-karmic-apturl-policy spec)

update-manager (1:0.120) karmic; urgency=low

  * The 'Ready for karmic' version
  * DistUpgrade/DistUpgradeController.py:
    - do not fail in partial upgrades if apport must be
      enabled (LP: #357755)
    - when rewriting sources.list, check for cdrom entries
      that do not have associated list files and disable
      them (LP: #366459)
    - when rewriting sources.list, deal better with apt-cacher
      apt-torrent style uris (LP: #365537)
  * DistUpgrade/xorg_fix_proprietary.py:
    - instead of replacing fglrx->ati and nvidia->nv just
      comment out the driver and let xorg figure it out
      with its own magic (LP: #351394)
    - update tests/ for the change
  * UpdateManager/UpdateManager.py:
    - use a gtk link button to point the user to further
      upgrade information
  * DistUpgrade/DistUpgradeController.py:
    - ensure ./imported/invoke-rc.d is executable (LP: #147742)
  * refactor the quirks handlers and not run them in partial
    upgrade mode
  * tests/test_sources_list.py:
    - update tests for apt-torrent style uris (LP: #365537)
  * DistUpgrade/DistUpgrade.cfg:
    - remove edubuntu-desktop from the flavour metapackages, its
      not its own flavour anymore
  * help/C/update-manager-C.omf:
    - point to file:/usr/share/gnome/help/update-manager/C/update-manager.xml
      (LP: #368140)

update-manager (1:0.111.9) jaunty-proposed; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - increase the size that the kernel requires in /boot
      (LP: #365623)
  * DistUpgrade/DistUpgradeApport.py:
    - fix apport hook integration (LP: #366048)
  * DistUpgrade/DistUpgradeController.py:
    - fix crash in partial upgrade (LP: #366048)
  * DistUpgrade/DistUpgradeQuirks.py:
    - make the gwenview upgrade transition more robust
      (LP: #365840)

update-manager (1:0.111.8) jaunty-proposed; urgency=low

  * DistUpgrade/DistUpgrade.cfg:
    - add "grub" to the list of packages to keep installed
      (LP: #363465)
    - ensure brasero is upgraded (thanks to Chris Jones for
      the report) (LP: #364136)
    - ensure guidance-power-manager is removed on upgrade 
      (LP: #364620)
  * DistUpgrade/DistUpgradeCache.py:
    - support DistUpgradeCache.markUpgrade()
  * DistUpgrade/mirrors.cfg:
    - add "mirror.files.bigpond.com" (thanks to wgrant)
  * debian/control:
    - build-depend on latest nvidia-common (LP: #363500) to ensure
      the nvidia-common if is included in the internal copy of
      u-m
  * DistUpgrade/DistUpgradeQuirks.py:
    - when the upgrade starts, remove old hal.postinst to prevent
      the trigger from running that causes network-manager to shutdown
      all connections (LP: #327053)
  * UpdateManager/Core/MetaRelease.py, UpdateManager/MetaReleaseGObject.py:
    - fix "no longer supported" message (LP: #364583)

update-manager (1:0.111.7) jaunty; urgency=low

  * DistUpgrade/ReleaseAnnouncement:
    - updated for the final release
  * DistUpgrade/DistUpgradeQuirks.py:
    - ensure qwenview is upgraded (LP: #360222)

update-manager (1:0.111.6) jaunty; urgency=low

  * UpdateManager/UpdateManager.py:
    - fix crash in free space check (LP: #362066)

update-manager (1:0.111.5) jaunty; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - do not crash when patch is not installed (LP: #361194)
  * DistUpgrade/DistUpgradeCache.py:
    - more debug output

update-manager (1:0.111.4) jaunty; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py:
    - make the pyqt4 logger less verbose
  * DistUpgrade/DistUpgradeController.py:
    - deal with pre-configure errors more cleanly (LP: #356781)
  * DistUpgrade/DistUpgradeMain.py:
    - fix error when the backup log dir already exists
  * DistUpgrade/DistUpgrade.cfg:
    - stop enabling apport
  * DistUpgrade/DevelReleaseAnnouncement:
    - update text for the release candidate
  * po/*.po:
    - translation updates from rosetta

update-manager (1:0.111.3) jaunty; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - cleanup the quirks handling for the StartUgrade
      phase and move the code in here
    - apply patch for install-docs if the user can not install
      the fix from {hardy,intrepid}-proposed

update-manager (1:0.111.2) jaunty; urgency=low

  * UpdateManager/Core/MyCache.py:
    - when calculating what category a update should be put in,
      make sure that candidate versions for "other updates" always
      end up there
    - do not try to get changelogs for packages that do not have
      a ubuntu origin (LP: #354740)
  * DistUpgrade/removal_blacklist.cfg:
    - add skype to the removal blacklist (thanks to Nick Lally)

update-manager (1:0.111.1) jaunty; urgency=low

  * DistUpgrade/DistUpgrade.cfg:
    - ensure that dontzap is installed on kubuntu (LP: #349263)
    - ensure to not upgrade to a known broken python2.6 (e.g.
      if the mirrors do not catch up)
  * DistUpgrade/DistUpgradeController.py:
    - avoid conffile prompt because we enabled apport (LP: #348301)
    - deal better with apt ordering bugs and restore the system
      cleanly in this case
    - when commenting out third party sources, leave a space
      between previous comments (thanks to Sidnei da Silva)
  * DistUpgrade/DistUpgradeCache.py:
    - add "BadVersions" config option
  * UpdateManager/Core/MetaRelease.py:
    - ignore bad header line errors (LP: #353335)
  * UpdateManager/UpdateManager.py:
    - start minimized when run with --no-focus-on-map (LP: #353195)
    - set urgency hint when in the background (LP: #353195)
  * po/*.po:
    - updated translations from rosetta

update-manager (1:0.111.0) jaunty; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - fix pre r6xx/7xx fglrx->ati transition
  * DistUpgrade/DistUpgradeQuirks.py:
    - fix incorrect variable name
  * DistUpgrade/DistUpgradeView.py:
    - remove old crash files on upgrade (thanks to
      Martin Pitt)

update-manager (1:0.110.1) jaunty; urgency=low

  * DistUpgrade/DistUpgrade.cfg.hardy:
    - support hardy->jaunty upgrade for kubuntu
  * po/POTFILES.{in,missing}:
    - add missing files (thanks to Gabor Kelemen)
      LP: #347040
  * po/*.po:
    - updated translations from launchpad

update-manager (1:0.110.0) jaunty; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - take changes in update-initramfs into account when
      calculating the space requirements in /boot (LP: #287826)
    - when doing the space calculation, show the required space
      for each directory (if multiple need more space) LP: #219416
  * DistUpgrade/DevelReleaseAnnouncement:
    - updated for beta
  * UpdateManager/DistUpgradeFetcher.py:
    - set 5s timeout for the ReleaseNotes fetching (LP: #109397)
  * UpdateManager/UpdateManager.py:
    - pass the correct FetchProgress to the release-upgrade fetching
      code instead of the incorrect OpProgress

update-manager (1:0.101.1) jaunty; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeCache.py:
    - catch cache.update() errors that do not raise exceptions
  * DistUpgrade/DistUpgradeController.py:
    - when calculating the obsolete packages, add extra paranoia
      for odd network failures (LP: #335154)
  * DistUpgrade/DistUpgradeAufs.py:
    - do not overlay /var/cache/apt/archives so that the user
      does not have to download the packages twice
    - honor the TMPDIR environment (by using tempfile)
  * DistUpgrade/DistUpgrade.cfg:
    - add powernowd to the forced obsoleted packages (the kernel
      does handle that with the builin ondemand governor now)

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgrade.cfg:
    - remove gtk-qt-engine in Kubuntu upgrades

update-manager (1:0.101.0) jaunty; urgency=low

  [ Brian Murray ]
  * UpdateManagerHildon/UpdateManagerHildon.py:
     - wording fix "will be" to "are being" (LP: #338943)
  
  [ Michael Vogt ]
  * UpdateManager/UpdateManagerText.py:
    - fix crash in changelog display (LP: #341577)
      (thanks to Steve Beattie)
    - support NEWS.Debian from the server as well
  * DistUpgrade/DistUpgradeAufs.py:
    - fix in is_submount detection (thanks to liw for reporting)

  [ Gabor Kelemen ]
  * data/glade/UpdateManager.glade:
    - fix missing "translatable" property (LP: #342011)

update-manager (1:0.100.1) jaunty; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - fix crash (LP: #340828) when config is undefinied
  * UpdateManager/UpdateManager.py:
    - explicitely cast time.time() to int (LP: #340755)

update-manager (1:0.100) jaunty; urgency=low

  [ Andy Whitcroft ]
  * DistUpgrade/cdromupgrade:
    - if cdromupgrade is run with a relative path we will fail to find the
      installer components and error out.  Ensure that the path is absolute.
      (LP: #335360)

  [ Michael Vogt ]
  * fix crash when help is not avaialble (LP: #338098)
  * data/glade/UpdateManager.glade:
    - remove the "Keep your system up-to-date" text (design team, 
      LP: #336800)
  * fix crash when no network is avaialble for changelog fetching
    (LP: #334002)
  * debian/control:
    - add conflict against update-manager-kde to update-manager-hildon
      (LP: #333464)
  * UpdateManager/Core/MyCache.py:
    - show proper urls for sources with epochs (LP: #328164), thanks
      to Richie
  * UpdateManager/ChangelogViewer.py:
    - support copy to clipboard for URLs (LP: #85644), thanks to
      Richie
  * UpdateManager/UpdateManager.py:
    - disable fixed-hight mode, it can cause incorrect height 
      calculation (thanks to Richie), LP: #273184
  * DistUpgrade/DistUpgradeController.py:
    - do not allow gtk/kde upgrades over ssh session (LP: #322482)
  * merged aufs branch (disabled by default but useful for testing)

update-manager (1:0.99) jaunty; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeController.py:
    - enable apport crash capturing during upgrades
  * DistUpgrade/DistUpgradeView.py:
    - create /var/lib/pycentral/pkgremove before the upgrade to
      help pycentral transition to the new python policy (thanks
      to doko)
  * ensure pidgin-libnotify is upgraded (LP: #332328)
  * better wording for aborts (thanks to Gabor Kelemen and
    Jean-Baptiste Lallement), LP: #289303
  * wording fixes, thanks to Brian Murray and Gabor Kelemen 
    LP: #269583
  * i18n fix, thanks to Gabor Kelemen, LP: #331821
  * support /etc/update-manager/release-upgrades.d/ directory
    for local overrides of the upgrade process. Useful to force
    certain site-specific options (like third party repository
    handling)
  * allow "[FreeSpace]\nSkipCheck=yes" override to skip free 
    space checks (useful for testing)
  * support "[Sources"]\nAllowThirdParty=yes" override to skip
    commenting out of unknown repositories (LP: #147080)
  * debian/*.install:
    - updated for the new python layout (/u/l/p/dist-packages instead of
      /u/l/p/site-packages)
  * debian/rules:
    - use DH_PYCENTRAL=include-links instead of "nomove"
    - use "--install-layout=deb" in distutils
  * debian/control:
    - use "XS-Python-Version: all" instead of current
  * DistUpgrade/DistUpgradeCache.py:
    - fix modalias path in NvidiaDetector
  * data/glade/UpdateManager.glade:
    - add "settings" button
  * UpdateManager/UpdateManager.py:
    - open software-properties when settings button
      is clicked (LP: #334959)
    - keep track of launch times via gconf
      (/apps/update-manager/launch_time)
  * debian/control:
    - recommend software-properties-gtk

  [ Brian Murray ]
  * DistUpgrade/multiple files:
    - fixed typographical error
  * DistUpgrade/DistUpgradeViewText.py:
    - change "Restart required" default to N (LP: #328452)

update-manager (1:0.98.1) jaunty; urgency=low

  * reenable the demotions.cfg generation and mirror updates
  * setup.py cleanup (thanks to liw)

update-manager (1:0.98) jaunty; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeController.py:
    - fixes in the error string (thanks to Jean-Baptiste 
      Lallement, LP: #298296)
  * support getting NEWS.Debian information in addition
    to the changelog
  * debian/update-manager-core.links:
    - fix typo (thanks to tjaalton)
  * merge the 'computer-janitor' core and quirks code into
    update-manager-core (part of the jaunty-cruftremover-improvements
    spec)
  * conflicts with the current version of computer-janitor

  [ Brian Murray ]
  * DistUpgrade - Release Announcements:
    - Modified reporting bugs sections to recommend using ubuntu-bug instead
      of filing bugs directly in Launchpad. (LP: #327800)

update-manager (1:0.97.1) jaunty; urgency=low

  [ Michael Vogt ]
  * UpdateManager/UpdateManager.py:
    - make the gconf handling more robust (LP: #320586)
  * UpdateManager/Core/MyCache.py:
    - fix crash when no changelog can be found (LP: #320894)
  * UpdateManager/Core/MetaRelease.py:
    - do not crash on disk full (LP: #321872)
  * DistUpgrade/DistUpgradeController.py:
    - when commenting out third party repositories add a comment
      why they were disabled and update them to the current dist  
      to make re-enabling easier
  * DistUpgrade/DistUpgradeQuirks.py:
    - run dpkg --forget-old-unvail after the upgrade finished
    - add "PostCleanup" hook 
  * DistUpgrade/cdromupgrade:
    - fixed typo (LP: #312184)
  * add "--no-focus-on-map option to bring update-manager up
    in the background (UX team)
  * change default text and add /apps/update-manager/first_run
    gconf key for the first run welcome message (UX team)
  * UpdateManager/ChangelogViewer.py:
    - support "LP: #nr:" linking in changelog entries (LP: #274737)

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgrade.cfg
    - remove guidance-power-manager on kubuntu-desktop upgrade

  [ Andy Whitcroft ]
  * DistUpgrade/cdromupgrade
    - move to using dists/$CODENAME to locate the installer eliminating
      any dependance on symlinks in the image.  This allows usb-creator based
      images to be used unmodified.  (LP: #326856)

update-manager (1:0.97) jaunty; urgency=low

  * UpdateManager/Core/MetaRelease.py:
    - remove debug message (LP: #310046)
  * UpdateManager/Common/utils.py:
    - when  initializing the proxy configuration, do in this
      order:
      * check apt setting
      * check synaptic setting
      * check users gconf
      * check http_proxy environment 
    (LP: #24250)
  * UpdateManager/Core/DistUpgradeFetcherCore.py:
    - ensure correct error message if downloading failed
      (LP: #113658)
    - when fetching from mirrors, add fallback if the mirror
      is too loaded to cope
    - improve logic that detects what mirror is in use by
      sources.list inspection (LP: #107983)
  * DistUpgrade/DistUpgradeMain.py, dist-upgrade.py:
    - re-factor and make code more modular
    - do not overwrite existing log files on upgrade
      (LP: #111819)
  * reorganize the imports and get rid of "Common" submodule 
    and merge that all into "Core"
  * improve the debug output via the "DEBUG_UPDATE_MANAGER"
    environment

update-manager (1:0.96.4) jaunty; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - do not generate apport report against update-manager if 
      cache.commit() failed. the report is generated against
      the failing package instead (LP: #311220)
    - honor RELEASE_UPRADER_ALLOW_THIRD_PARTY environment and do   
      not  comment out third party repositories in this case 
      (useful internal repositories, make sure that sudo does 
       not clean this env when you make use of it)
  * DistUpgrade/DistUpgrade.cfg:
    - remove powermanagement-interface on upgrades for ubuntu 
      and kubuntu (no longer needed by them)
  * DistUpgrade/DevelReleaseAnnouncement:
    - include a different release announcement for the 
      development releases
  * pre-build.sh:
    - fix version parsing

update-manager (1:0.96.3) jaunty; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - when syncing inconsitent components, only sync those
      we know about (LP: #312092)
  * tests/test_sources_list.py:
    - add regression test for #312092

update-manager (1:0.96.2) jaunty; urgency=low

  * AutoUpgradeTester/UpgradeTestBackendQemu.py:
    - add "NonInteractive","NoVirtio" switch 
    - enable virtio in the kvm backend by default
  * AutoUpgradeTester/profile/server/DistUpgrade.cfg:
    - updated for intrepid->jaunty
    - add missing kernel removal section
  * DistUpgrade/DistUpgrade.cfg:
    - update KernelRemoval section for intrepid->jaunty
  * DistUpgrade/DistUpgradeApport.py, README:
    - add new RELEASE_UPRADER_NO_APPORT environement that can
      be used to force the upgrader to not run apport on pkg failures
  * DistUpgrade/DistUpgradeViewNonInteractive.py:
    - use RELEASE_UPRADER_NO_APPORT in the non-interactive upgrade tests
  * AutoUpgradeTester/profile/ubuntu/DistUpgrade.cfg:
    - updated for intrepid->jaunty
  * DistUpgrade/DistUpgrade.cfg:
    - enable DistUpgrade/xorg_fix_proprietary.py to transition users
      from proprietary drivers to free drivers if the proprietary
      driver is no longer available after the upgrade

update-manager (1:0.96.1) jaunty; urgency=low

  * DistUpgrade/DistUpgradeController.py: 
    - deal better with upgrades from EOL releases by
      testing if the new release is on the country mirror
      or archive.ubuntu.com or still on old-releases.ubuntu.com
      (LP: #264181)
  * debian/control:
    - disable the auto-upgrader-tester package, its not quite
      ready yet

update-manager (1:0.96) jaunty; urgency=low

  * UpdateManager/Core/MetaRelease.py:
    - deal with full disks better when downloading
      the meta-release information (LP: #98666)
  * DistUpgrade/DistUpgradeView.py:
    - make the FuzzyTimeToStr() function not display
      minutes when the total time is > 3h (LP: #144455)
  * build update-manager-text package with text/newt based
    update-manager frontend (update-manager-text)
  * DistUpgrade/DistUpgradeQuirks.py:
    - check if both grub and lilo are installed and remove
      the one that is not used (LP: #314004)
  * po/POTFILES.in, po/POTFILES.skip:
    - updated
  * po/update-manager.pot:
    - refreshed

update-manager (1:0.95.2) jaunty; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py: 
    - check the support of fglrx against the current
      PCI card (LP: #284408)
  * DistUpgrade/xorg_fix_intrepid.py:
    - do not rewrite multiseat configs (LP: #292774)
  * UpdateManager/Common/MyCache.py,
    UpdateManager/Common/UpdateList.py:
    - move the cache,updatelist implementation out into  
      its own file
  * fix free space check on regular update-manager 
    invocations (LP: #105113)
  * debian/rules 
    - remove the arch-build target
  * DistUpgrade/DistUpgradeController.py:
    - improvements to the sources.list rewriting, better tests
    - when rewriting sources.list check for inconsistencies between what
      components are enabled in intrepid vs intrepid-updates and 
      intrepid-security and automatically enable missing ones for
      intrepid-updates and intrepid-security
    - new test if the upgrade is run from a remote 
      login (LP: #301787)

update-manager (1:0.95.1) jaunty; urgency=low

  * DistUpgrade/DistUpgrade.glade, DistUpgrade/window_main.ui:
    - show 9.04 upgrade target
  * debian/rules:
    - calculate demotions based on intrepid->jaunty
  * DistUpgrade/DistUpgradeCache.py:
    - when the dist-upgrade calculation fails, show the reason
      why in the error dialog (LP: #281286)
    - when a meta package can not be upgraded, show a proper
      error message with the package in question
  * DistUpgrade/DistUpgradeQuirks.py:
    - abort upgrade from hardy if evms is used in /proc/mounts
      evms got removed from the archive in intrepid (LP: #292179)
    - do not add "relatime" if "noatime" is already given (thanks
      to  Ken Geis)
  * DistUpgrade/removal_blacklist.cfg:
    - remove overly broad postgresql regexp
  * DistUpgrade/DistUpgradeCache.py:
    - do not limit the removal blacklist to downloadable packages,
      this limits it too much
  * check-new-release:
    - install check for new releases into update-motd.d/daily

update-manager (1:0.95) jaunty; urgency=low

  * updated for jaunty

update-manager (1:0.93.34) intrepid-proposed; urgency=low

  * UpdateManager/UpdateManager.py:
    - simply the changelog download logic and make changelog
      fetching work properly again (now that the server side
      got improved as well) LP: #40058

update-manager (1:0.93.33) intrepid; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeQuirks.py:
    - add detection for cards no longer supported via fglrx 
      and ensure transition to "ati" (LP: #284408) 
  * DistUpgrade/DistUpgradeCache.py:
    - check if the package is actually downloadable in the 
      removal blacklist checking (LP: #293486)

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeViewKDE.py:
    - handle translations of non-ascii string on Cancel button 
      correctly (LP: #291115)

update-manager (1:0.93.32) intrepid; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - when transitioning from kubuntu-kde4-desktop to kubuntu-desktop
      consider key dependencies as well even if kubuntu-kde4-desktop
      is no longer installed (LP: #277285)

update-manager (1:0.93.31) intrepid; urgency=low

  * DistUpgrade/DistUpgrade.cfg:
    - remove goubuntu-desktop from metapackages, we do no
      longer build it (LP: #283712)
  * DistUpgrade/DistUpgradeCache.py: 
    - never remove packages in the "KeepInstalled" section
    - keep the GUI alive when calculating the packages
      to cleanup
  * DistUpgrade/DistUpgradeQuirks.py:
    - mark "language-pack-$lang" as manual installed to
      workaround changes in "language-support-$lang" 
      (LP: #287551)
   * po/:
     - updated to the latest translations.launchpad.net
       version

update-manager (1:0.93.30) intrepid; urgency=low

  * DistUpgrade/DistUpgradeViewText.py:
    - ignore "default" argument handling in askYesNoQuestion
      to fix incorrect prompt for cdrom question
  * DistUpgrade/DistUpgradeQuirks.py:
    - ensure "landscape-common" is not marked auto-install
      (LP: #288051)
  * DistUpgrade/ReleaseAnnouncement:
    - updated for final release
  * DistUpgrade/DistUpgradeAptCdrom.py:
    - ignore "dist-upgrader" dirs when scanning for 
      packages (LP: #288169)

update-manager (1:0.93.29) intrepid; urgency=low

  * fix incorrect case and typo in cpuHasSSESupport(), thanks
    to Steve Langasek

update-manager (1:0.93.28) intrepid; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - do not install nvidia-glx-{173,177} on systems without
      the "sse" cpu extension (LP: #272498)
    - fix case-sensitive parsing when checking for the xorg
      driver
  * DistUpgrade/DistUpgrade.cfg:
    - make sure that libflashsupport gets removed on upgrade
      (LP: #285657)
  * DistUpgrade/ReleaseAnnouncement:
    - updated for the release candidate

update-manager (1:0.93.27) intrepid; urgency=low

  * DistUpgrade/xorg_fix_intrepid.py:
    - only update the InputDevices if xserver-xorg-core
      actually is version 2:1.5.0 or higher
    - make section checks case-insensitive (thanks to
      Alberto Milone)
  * DistUpgrade/DistUpgrade.glade:
    - remove has_focus default in the conffiel dialog

update-manager (1:0.93.26) intrepid; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - workaround kde tmpfile permissions (LP: #277431)
  * UpdateManager/Common/utils.py:
    - do not crash if gconfd is not availabe/unusable 
      (LP: #281248)
  * DistUpgrade/DistUpgradeViewKDE.py:
    - do not use "kde" frontend during the upgrade, it
      crashes because of the kde3->kde4 transition
      if run at the wrong time (LP: #283942)
  * DistUpgrade/DistUpgradeView.py:
    - ignore SIGPIPE when forking the Dpkg::Pre-Install
      scripts to fix error with etckeeper (LP: #283642)
  * po/
    - updated from rosetta

update-manager (1:0.93.25) intrepid; urgency=low

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeQuirks.py:
    - Fix crash from not having gettext imported
  
  [ Michael Vogt ]
  * revert the fglrx->ati transition (LP: #247376)

update-manager (1:0.93.24) intrepid; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - disable the apt.cron.daily script during the upgrade
      (LP: #277079)
  * DistUpgrade/DistUpgradeAptCdrom.py:
    - work around the problem that the hardy "apt-cdrom add" will
      fail when no uncompressed Packages files are on the CD
      (LP: 276349)

update-manager (1:0.93.23) intrepid; urgency=low

  * DistUpgrade/xorg_fix_intrepid.py:
    - comment out input devices from xorg.conf (handled via 
      hal now). Thanks to Alberto Milone for his help, 
      LP: #247608

update-manager (1:0.93.22) intrepid; urgency=low

  * DistUpgrade/DistUpgradeQuirks.py:
    - add rule to force kdelibs5-dev upgrade (LP: #279621),
      thanks to ScottK
  * DistUpgrade/DistUpgradeViewGtk.py:
    - do not hang if a script fails to run (LP: #280236)
  * DistUpgrade/DistUpgradeController.py:
    - do not run post-upgrade quirks handler in partial upgrade
      mode because they only apply to real release upgrades

update-manager (1:0.93.21) intrepid; urgency=low

  * Add useDevelopmentRelease and useProposed to DistUpgradeFetcherKDE.py
  * Fix call to error() in DistUpgradeFetcherCore.py

update-manager (1:0.93.20) intrepid; urgency=low

  * DistUpgrade/DistUpgradeGettext.py:
    - translated the empty "" into "" (the qt frontend
      may call this on empty strings in translate_widget)
  * DistUpgrade/DistUpgradeQuirks.py:
    - make sure to write a final newline in /etc/fstab
      when adding the relatime option (LP: #279093)

update-manager (1:0.93.19) intrepid; urgency=low

  * UpdateManager/Core/MetaRelease.py:
    - fix crash in CDROM upgrade  (LP: #276363)
  * DistUpgrade/DistUpgradeQuirks.py:
    - fix crash in nvidia handling (thanks to 
      Spencer Janssen)

update-manager (1:0.93.18) intrepid; urgency=low

  * DistUpgrade/DistUpgrade.cfg:
    - add KeepInstalled rule for adept to help
      the dependency resolver (thanks to MvG)
    - add kubuntu-kde4-desktop metapackage so that
      the meta package detection works for kde4 (LP: #274706)
  * DistUpgrade/DistUpgradeCache.py:
    - fix log for kept packages
    - make the log of the obsolete removal less verbose
    - fix kubuntu-kde4-desktop upgrades (LP: #274706)
  * DistUpgrade/ReleaseAnnouncement:
    - udpated for BETA
  * DistUpgrade/DistUpgradeViewGtk.py:
    - fix typo and unfuzzy translations. Thanks to Brian Murray
      for the patch, LP: #272726)
  * UpdateManager/UpdateManager.py:
    - add gconf key /apps/update-manager/show_versions to show
      version information (disabled by default, LP: #189406)
  * DistUpgrade/DistUpgradeQuirks.py:
    - add intrepidPreUpgrade() handler that detects
      fglrx in xorg.conf and warns about it before the upgrade 
    - consolidate the various quirks into this file
    - add check for the nvidia-glx-71 and nvidia-glx-96 drivers 
      and warn if they will be required
  * DistUpgrade/xorg_fix_intrepid.py:
    - add script that is run after the upgrade that ensures that
      the xorg.conf file gets transitioned to a free driver if
      the proprietary one does not work for intrepid
    - transition from fglrx and nvidia-glx-{71,96} to the free
      driver (LP: #274303)

update-manager (1:0.93.17) intrepid; urgency=low

  [ Michael Vogt ]
  * UpdateManager/UpdateManager.py:
    - fix typo (thanks to "Richie", LP: #271139)
  * DistUpgrade/DistUpgradeCache.py:
    - remove the landscape-client stub package on
      desktop upgrades

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeViewKDE.py fix crash when translating dialogue

update-manager (1:0.93.16) intrepid; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeController.py:
    - automatically add "relatime" to the mount options
      of ext2/ext3
  * UpdateManager/Core/MetaRelease.py:
    - fix typo (thanks to Daniel Garcia)
  * DistUpgrade/DistUpgradeCache.py:
    - fix the removal of obsolete kernel packages when the 
      old kernel abi package gets removed from -update and/or
      -security
  * UpdateManager/UpdateManager.py:
    - be more robust against server errors when fetching the
      changelogs (LP: #262982)
  * debian/control:
    - update the version dependency for python-apt, we need
      stuff from 0.7.5 (LP: #257781)
  * DistUpgrade/DistUpgradeView.py:#
    - make FuzzyTimeToStr() properly deal with plural forms
      (LP: #267234)
  
  [ Brian Murray ]
  * UpdateManager/UpdateManager.py:
    - preserve epoch in package version for changelogs at 
      launchpad.net (LP: #270527)

update-manager (1:0.93.15) intrepid; urgency=low

  * UpdateManager/Core/DistUpgradeFetcherCore.py:
    - fix incorrect import

update-manager (1:0.93.14) intrepid; urgency=low

  * po/*.po:
    - updated to the latest launchpad translations
  * DistUpgrade/DistUpgradeGettext.py:
    - add more robust version of gettext() that does not
      crash if incorrect number arguments is passed (LP: #269379)

update-manager (1:0.93.13) intrepid; urgency=low

  * DistUpgrade/DistUpgrade.cfg:
    - better KeyDependencies for ubuntu-desktop to make the 
      detection more robust

update-manager (1:0.93.12) intrepid; urgency=low

  * DistUpgrade: load DistUpgradeViewKDE not KDE4
  * DistUpgradeViewKDE: Fix various translations
  * DistUpgradeViewKDE: Add window icon

update-manager (1:0.93.11) intrepid; urgency=low

  [ Jonathan Riddell ]
  * DistUpgradeViewKDE: don't use setHeaderHidden, doesn't exist in Qt 4.3
  * DistUpgradeViewKDE: Disable terminal button until terminal exists
	
  [ Michael Vogt ]
  * rename DistUpgradeViewKDE4.py to DistUpgradeViewKDE.py
    because adept runs this frontend explicitely (instead
    of letting dist-upgrade.py decide)

update-manager (1:0.93.10) intrepid; urgency=low

  [ Jonathan Riddell ]
  * Add missing debian/update-manager-kde.install
  
  [ Michael Vogt ]
  * transition landscape.canonical.com to the main repository
    (LP: #268551)

update-manager (1:0.93.9) intrepid; urgency=low

  * do not build depend on nvidia-common for lpia

update-manager (1:0.93.8) intrepid; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeCache.py:
    - transition "kubuntu-desktop-kde4" to "kubuntu-desktop"
      (thanks to Jonathan Riddell)
  * DistUpgrade/DistUpgradeCache.py,
    DistUpgrade/DistUpgradeController.py:
    - fixes in the "AllowUnauthenticated" code (thanks to Adam
      Conrad)
  * debian/update-manager-hildon.install:
    - install only selected bits from Comon/
  
  [ Emmet Hikory ]
  * Removed check to set automatic notifications in update-manager-hildon

update-manager (1:0.93.7) intrepid; urgency=low

  * Move Common/utils.py to update-manager-core
  * Fix build when rebuilding with -nc
  * UpdateManager/DistUpgradeFetcherKDE.py shouldn't import ReleaseNotesViewer
  * DistUpgrade/cdromupgrade should be intrepid

update-manager (1:0.93.6) intrepid; urgency=low

  * Make DistUpgradeFetcherKDE.py work as a module not just a standalone script

update-manager (1:0.93.5) intrepid; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeCache.py:
    - install new recommends on the hardy->intrepid upgrade
      (unless overwriten with the RELEASE_UPGRADE_NO_RECOMMENDS
       environment)
  * AutoUpgradeTester/UpgradeTestBackendQemu.py:
    - run ssh in the auto tester with "-t"
  * UpdateManager/UpdateManager.py:
    - fix plural forms (thanks to Bruce Cowan, LP: #189921)
  * DistUpgrade/DistUpgradeViewGtk.py:
    - show kB/sec (LP: #257778)

  [ Jonathan Riddell ]
  * Add KDE upgrade checking tools for use by Adept

update-manager (1:0.93.4) intrepid; urgency=low

  * DistUpgrade/removal_blacklist.cfg:
    - add openssh-blacklist-extra and openssh-extra
  * UpdateManager/UpdateManager.py:
    - do not crash if lsb_release can not be run (LP: #255319)
  * DistUpgrade/DistUpgradeApport.py:
    - do not generate apport reports against a package if
      the error indicates that its a full disk, this is a bug
      in update-manager than (failed to do the full disk checking)
  * DistUpgrade/DistUpgrade.cfg:
    - force obsoletion of cups-pdf on ubuntu-desktop, kubuntu-desktop
      and xubuntu-desktop
  * DistUpgrade/DistUpgradeController.py:
    - increase KERNEL_INITRD_SIZE a bit

update-manager (1:0.93.3) intrepid; urgency=low

  * fix ftbfs on powerpc

update-manager (1:0.93.2) intrepid; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - work around problem with packages with no priority
      (LP: #253255)
  * DistUpgrade/DistUpgradeViewGtk.py:
    - detect ctrl-c presses in the terminal and warn the 
      user that it will kill the upgrade (LP: #90866)
  * DistUpgrade/DistUpgrade.cfg:
    - when being run by the sandbox-upgrader, do not 
      reboot automatically after the upgrade finished
  * DistUpgrade/DistUpgradeController.py:
    - when a upgrade is cancelt due to network errors, 
      inform that the downloaded files will be kept 
      (LP: #242111)

update-manager (1:0.93.1) intrepid; urgency=low

  * UpdateManager/UpdateManager.py:
    - make the init_proxy stuff look for the apt.conf proxy 
      as well (thanks to vega--)
  * do-release-upgrade:
    - unify proxy configuration between gtk and cli UI
  * fix FBTFS by removing the kdepyuic calls during build
    (no longer needed in qt4)

update-manager (1:0.93) intrepid; urgency=low

  [ Michael Vogt ]
  * UpdateManager/UpdateManager.py:
    - fix typo (LP: #252195)
  * DistUpgrade/DistUpgradeController.py:
    - fix crash in cleanup code
  
  [ Jonathan Riddell ]
  * port the kde frontend to qt4

update-manager (1:0.92) intrepid; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - use nvidia-common to detect what driver package is needed
      and install it if the user had a previous nvidia driver 
    (thanks to Alberto Milone)
  * improvements to the NonInteractive frontend

update-manager (1:0.91.10) intrepid; urgency=low

  * UpdateManager/Core/DistUpgradeFetcherCore.py:
    - improved error handling for people who run
      /tmp with noexec (LP: #219518)
  * DistUpgrade/ReleaseAnnouncement:
    - fixes in the announcement text (thanks to 
      Brian Murray, LP: #250693)
  * DistUpgrade/removal_blacklist.cfg:
    - remove nvidia-glx from the removal blacklist,
      the naming schema changed in intrepid and the
      old packages need to go way (LP: #249329)

update-manager (1:0.91.9) intrepid; urgency=low

  * UpdateManager/Core/MetaRelease.py:
    - make the default meta-release location easily 
      changable via /etc/update-manager/meta-release
  * data/meta-release:
    - make the default configuration easier configurable
  * data/release-upgrades:
    - default to "normal" upgrades for intrepid

update-manager (1:0.91.8) intrepid; urgency=low

  * data/glade/UpdateManager.glade:
    - make the shortcut key in the auto-updates dialog
      consistent with the main one (LP: 246321)
  * DistUpgrade/ReleaseAnnouncement:
    - updated for intrepid (LP: #246538)

update-manager (1:0.91.7) intrepid; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - add logging for kept packages
    - make the "use-network" question on cdrom upgrades
      more clear (LP: #229508)
    - do not just exit on upgrades with errors but show
      a proper finished message
  * DistUpgrade/DistUpgradeApport.py:
    - only run apport-{gtk,qt} if DISPLAY is set
  * DistUpgrade/DistUpgradeView{Gtk,KDE}.py:
    - do not show a error dialog for folloup errors from
      earlier errors (thanks to Alexander Sack for the report)

update-manager (1:0.91.6) intrepid; urgency=low

  * Make "--mode={server,desktop}" obsolete by adding automatic
    detection for this. This eliminates the bugreports where
    people run the text do-release-upgrade client that defaults
    to server mode
  * UpdateManager/UpdateManager.py:
    - improve the changelog version number scanner
    - if no information is available yet, display a launchpad link
      for interested people (not fetching from there automatically to
      not hammer LP too much)

update-manager (1:0.91.5) intrepid; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - support "old-releases.ubuntu.com" as a valid mirror and
      auto transition from that to the regular archive 
      (LP: #235527)
    - add extra paraonoia when adding a missing admin group
      (thanks to LaMont Jones) LP: #241723
  * UpdateManager/ChangelogViewer.py:
    - support "exo-open" (xfce) too (LP: #240473)
  * DistUpgrade/mirrors.cfg:
    - remove ftp.caliu.info (LP: #231966)
  * DistUpgrade/DistUpgradeController.py:
    - fix typo and unfuzzy translations (LP: #220505)
  * UpdateManager/UpdateManager.py, data/update-manager.schemas.in:
    - provide a gconf key /apps/update-manager/autoclose_install_window
      to make it possible to prevent automatic closing of the installation
      window (LP: #183209)
  * DistUpgrade/DistUpgrade.cfg.dapper:
    - remove ports.ubuntu.com from powerpc, it is not available on
      ports.ubuntu.com but on archive.ubuntu.com (LP: #241729)

update-manager (1:0.91.4) intrepid; urgency=low

  * update-manager:
    - string fixes (LP: #230865)
  * UpdateManager/UpdateManager.py:
    - support selecting/dselecting entire update 
      categories by double clicking on the list header

update-manager (1:0.91.3) intrepid; urgency=low

  * DistUpgrade/mirrors.cfg:
    - remove ftp.caliu.info (LP: #231966)
  * UpdateManager/UpdateManager.py, data/update-manager.schemas.in:
    - provide a gconf key /apps/update-manager/autoclose_install_window
      to make it possible to prevent automatic closing of the installation
      window (LP: #183209)

update-manager (1:0.91.2) intrepid; urgency=low

  [ Brian Murray ]
  * String fix for "a unresolvable problem" (LP: #196269)
  * String fix for "A upgrade to" (LP: #196229)
  * String fix for "is in a inconsistent state" (LP: #197015)

update-manager (1:0.91.1) intrepid; urgency=low

  * debian/control:
    - add missing python-vte dependency to update-manager-hildon

update-manager (1:0.91) intrepid; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - fix bug in withNetwork value propergation (LP: #227197)
  * DistUpgrade/DistUpgradeController.py:
    - fix bug with sources.list rewriting when mixed
      deb http://unknown-miror\ndeb-src http://known-mirror 
      entries are used (#221730)
  * UpdateManager/Common/utils.py:
    - fix inhibit path (LP: #140754), thanks to 
      Andreas Dalsgaard
  * DistUpgrade/DistUpgradeViewText.py:
    - use sensible-pager first and fallback to "more" if
      that is not available (thanks to Mithrandir)
  * DistUpgradeView{Gtk,KDE,Text}.py:
    - only overwrite the DEBIAN_FRONTEND if it is not set
      already (thanks to Guy Sheffer)
  * UpdateManagerHildon/UpdateManagerHildon.py:
    - add hildon support (thanks to Tollef Fog Heen and
      Emmet Hikory)

update-manager (1:0.90.0) intrepid; urgency=low

  * merged branches:
    - ~alefteris/update-manager/alefteris (thanks!)
  * UpdateManager/Core/DistUpgradeFetcherCore.py:
    - do not crash if the tarfile can not be read (LP: #203504)
  * fix a bunch of spelling mistakes (LP: #213040), thanks
    to Peter Cordes
  * AutoUpgradeTester/automatic-upgrade-testing:
    - add "--additional-pkgs" argument that can be used to install
      the given packages (seperated with ",") into the VM before 
      the upgrade is performed
  * DistUpgrade/DistUpgradeConfigParser.py:
    - write error to log in getListFromFile() if file is not
      found
  * DistUpgrade/DistUpgradeCache.py:
    - fix plural form text (LP: #226695)
  * update-manager-core.install, update-manager.install:
    - move the DistUpgrade part into update-manager-core
  * DistUpgrade/DistUpgradeController.py, update-manager, dist-upgrade.py:
    - move partialUpgrade() functionality into the controller and
      expose it with --partial in dist-upgrade.py
  * DistUpgrade/DistUpgrade.cfg:
    - prepare for hardy->intrepid upgrades

update-manager (1:0.87.27) hardy-proposed; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - make networkless upgrades more robust (LP: #227197)
  * po/ko.po:
    - fix translation for y/n prompt so that korean users
      can actually continue (LP: #223419)
  * DistUpgrade/DistUpgradeViewGtk.py:
    - work around hang in svg loader (LP: #186465)

update-manager (1:0.87.26) hardy-proposed; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - run in server mode on a server CD (LP: #222895)
    - deal with the landscape.canonical.com repository
      (LP: #224308)
  * DistUpgrade/DistUpradeCache.py:
    - make the code more robust against unavailable
      package records (LP: #223619)
  * DistUpgrade/cdromupgrade:
    - allow passing of arguments (like --mode=server)
      to better support server upgrades with the dvd
      (LP: #222895)
  * po/uk.po:
    - fix translation so that it gets the expected 
      number of arguments (LP: #224294)

update-manager (1:0.87.25) hardy-proposed; urgency=low

  * DistUpgrade/DistUpgradeApport.py:
    - fix typo in log dir (LP: #223743)
  * DistUpgrade/DistUpgradeController.py:
    - if the "Crux" theme is used on dapper during the upgrade, 
      switch to "Human" because Crux is known to crash 
      (LP: #69124)
  * DistUpgrade/DistUpgradeCache.py:
    - do not crash if a meta package is not available in 
      the cache (e.g. xubuntu-desktop that moved from main 
      to universe)
  * DistUpgrade/DistUpgrade.cfg.dapper:
    - fix incorrect xubuntu-desktop detection
  * DistUpgrade/DistUpgradeView.py:
    - make sure that self.confirmChangesMessage is always 
      initialized (LP: #221023)
  * DistUpgrade/mirrors.cfg:
    - added missing russion mirror (LP: #221730)
    - fixed incorrect mirror lines
  * DistUpgrade/DistUpgrade.cfg:
    - better detection to missing dependencies to fix
      ubuntustudio-desktop upgrade problem (LP: #219659)
  * util/demotions.py:
    - do not consider powerpc anymore, its not available on
      archive.ubuntu.com anymore
  * debian/rules:
    - do not run tests in arch-build target (only useful
      when there is a development release available to upgrade to)

update-manager (1:0.87.24) hardy; urgency=low

  * DistUpgrade/ReleaseAnnouncement:
    - modified https url to http so it is clickable (LP: #220386)
  * po/en_GB.po:
    - unfuzzy typo correction

update-manager (1:0.87.23) hardy; urgency=low

  * DistUpgrade/DistUpgrade.cfg.dapper:
    - Add 'bash' to BaseMetaPkgs. This is needed because ubuntu-meta
      was uploaded into dapper-updates and that means that we the
      detection of a missing main archive in sources.list will not
      work correctly (LP: #220078)
  * DistUpgrade/ReleaseAnnouncement:
    - updated in preparation for the final release

update-manager (1:0.87.22) hardy; urgency=low

  * UpdateManager/UpdateManager.py:
    - only set http proxy if hostname/port is valid (LP: #219227)
  * DistUpgrade/DistUpgradeController.py: 
    - some more debug logging 
    - fix missing cache open
    - smaller default network time out
    - run the initial cache.update() on the unmodified sources.list
      with only a single retry because it may contain sources that 
      do not respond

update-manager (1:0.87.21) hardy; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - transition sparc users to ports.ubuntu.com on upgrade
  * DistUpgrade/DistUpgrade.cfg.dapper:
    - point to ports.ubuntu.com when fetching 
      release-upgrader-{apt,dpkg} on dapper->hardy upgrades

update-manager (1:0.87.20) hardy; urgency=low

  * DistUpgrade/DistUpgradeView.py:
    - fix incorrect _() call (thanks to Timo Jyrinki)
  * DistUpgrade/mirrors.cfg:
    - fix ports.ubuntu.com mirror URI (LP: #215346)
  * run dpkg with --force-overwrite by default on the server
    too to make the upgrade more robust. this can be overwriten
    with the RELEASE_UPGRADE_NO_FORCE_OVERWRITE environment

update-manager (1:0.87.19) hardy; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - only try to upgrade held-back packages in the 
      edgyQuirks handler if they are actually upgradable 
      (thanks to Lamont Jones and James Troup)
  * po/fi.po
    - unfuzzy string (thanks to Timo Jyrinki)

update-manager (1:0.87.18) hardy; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - remove mail-notificaton, gnome-translate from hardy 
      quirks list (LP: #215690)
  * UpdateManager/DistUpgradeFetcher.py:
    - use sensible gksu prompt when asking for release
      upgrade (LP: #161888)

update-manager (1:0.87.17) hardy; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - when run from a CDROM upgrade on dapper, ensure to
      fetch the right files on tryUpdateSelf() (#215673)
    - ensure that language-support-$lang packages get
      upgraded if they are installed
  * UpdateManager/Core/MetaRelease.py:
    - support forceLTS option (#215673)
  * DistUpgrade/DistUpgradeView.py:
    - work around gutsy->hardy nvidia-glx uprade problem
      when libqt-perl is used (#205079)
  * DistUpgrade/ReleaseAnnouncement:
    - updated for RC

update-manager (1:0.87.16) hardy; urgency=low

  * DistUpgrade/DistUpgradeViewText.py:
    - show prompt again after showing details 
    - use pager for long change entries
    (thanks to James Troup)
    - fix text wrap to not break lines on "-" (e.g. in package 
      names)
  * DistUpgradeController.py:
    - do not leave 20archive.save files around
    - make the code that asks about starting a new ssh daemon
      (if run under ssh) more robust
    - set status to "Calculating changes" again after displaying
      demoted packages
    - improve logging if prerequisites download fails
  * DistUpgrade/DistUpgradeCache.py:
    - improve the evms detection/removal (thanks to Lamont Jones)
  * DistUpgrade/DistUpgrade.cfg.dapper:
    - add "lvm2" to the KeepInstalledPkgs (LP: #211488)
    - sync RemoveObsoletes, ForcedObsoletes, KeepInstalledSections
      with DistUpgrade.cfg
    - text wrap questions too
  * po/*.po:
    - updated translations (LP: #210699)

update-manager (1:0.87.15) hardy; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - fix fd leak 
  * DistUpgrade/DistUpgradeController.py:
    - abort when debsig-verify is installed, it makes any
      upgrade fail (LP: #208957)
    - run migrate-fstab-to-uuid.sh as PostInstallScript (LP: #209347)
    - set RELEASE_UPGRADE_MODE={server,desktop} environment
  * DistUpgrade/DistUpgradeViewKDE.py:
    - fix crash/race in terminal key press handler (LP: #205445)
    - fix encoding issue (LP: #208390)
    - call it 8.04 LTS (LP: #204659)
  * DistUpgrade/DistUpgradeViewGtk.py:
    - fix incorrect pango attribute assignment (LP: #207742)
    - call it 8.04 LTS (LP: #204659)
  * UpdateManager/UpdateManager.py:
    - do not crash if gconf database is not writable (LP: #208687)
    - do not crash on BadStatusLine exceptions (LP: #204075)
  * po/*.po:
    - make update-po

update-manager (1:0.87.14) hardy; urgency=low

  * DistUpgrade/ReleaseAnnouncement:
    - Fix typo
  * DistUpgrade/DistUpgradeViewKDE.py:
    - Add show/hide to upgrade package list
  * DistUpgrade/window_main.ui:
    - Sync strings with GTK frontend to pick up translations
    - Update icon to Oxygen

update-manager (1:0.87.13) hardy; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - only ask once about the sshd (LP: #156625)
  * DistUpgrade/DistUpgradeCache.py:
    - add hardyQuirks handler to deal with a
      gnome-translate upgrade issues (thanks to Daniel Holbach)
    - fix naming of the quirksHandlers
  * DistUpgrade/DistUpgrade.cfg:
    - add "ksplash-engine-moodin" to ForcedObsoletes
  * DistUpgrade/removal_blacklist.cfg:
    - add "^postgresql-.*"to the removal blacklist
  * DistUpgrade/DistUpgradeViewText.py:
    - flush() output in updateStatus()
    - show the demoted packages in a more readable
      manner
    - use textwrap when displaying text
  * DistUpgrade/DistUpgradeCache.py:
    - fix bug that prevented proper error message on 
      upgrade calculation error in the text frontend
    - fix text download progress
  * DistUpgrade/ReleaseAnnouncement
    - updated for BETA

update-manager (1:0.87.12) hardy; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py:
    - fix display of non-ascii chars
    - improve editing capabilities of the terminal (should be 
      fine with the readline fontend now)

update-manager (1:0.87.11) hardy; urgency=low

  * DistUpgrade/DistUpgradeControler.py:
    - when upgrading without network and with a empty sources.list,
      do not ask to add network sources
  * DistUpgrade/DistUpgradeCache.py:
    - do not crash if lookupRecords() failed (LP: #199482)
  * UpdateManager/UpdateManager.py:
    - use absolute path when calling gksu (LP: #194166),
      Thanks to Mihai Varzaru and James Westby
  * data/update-manager.desktop.in:
    - improve consistency with the rest of gnome (LP: #150205)
  * DistUpgrade/DistUpgradeViewKDE.py:
    - do no longer use konsole during upgrades but use a dumb
      terminal instead that only supports basic editing
    - log terminal activity to /var/log/dist-upgrade/term.log

update-manager (1:0.87.10) hardy; urgency=low

  * remove code duplication in the confirmChanges() code and make the
    warning more readable (LP: #188724)
  * DistUpgrade/DistUpgradeController.py:
    - when adding prerequists, ensure that no duplicated lines are
      added, plus add test for this (thanks to Kolbjørn Barmen)
    - honor APT::Get::AllowUnauthenticated (thanks to Kolbjørn 
      Barmen)
  * DistUpgrade/cdromupgrade:
    - updated to hardy
    - fix bug in path handling (LP: #155833)
  * DistUpgrade/prerequists-sources.list:
    - remove cruft

update-manager (1:0.87.9) hardy; urgency=low

  * rebuild due to python-central issues

update-manager (1:0.87.8) hardy; urgency=low

  * deal with packages in broken reqreinst state by
    offering to remove them (LP: #1922578)
  * UpdateManager/UpdateManager.py:
    - display a meaningful message when no information
      of the last update can be found (LP: 192328)

update-manager (1:0.87.7) hardy; urgency=low

  [ Michael Vogt ]
  * UpdateManager/Core/MetaRelease.py:
    - honor DEBUG_UPDATE_MANAGER environment and give some
      debug output on the meta-release fetching/parsing
  * UpdateManager/DistUpgradeFetcher.py:
    - cancel if the ReleaseNotes window is closed via the 
      window close control (thanks to Matthew Paul Thomas)
  * DistUpgrade/DistUpgradeViewGtk.py:
    - show update details in smaller font instead of italic
  * more UI improvements as suggested by Matthew Paul Thomas
  * DistUpgrade/DistUpgradeControler.py:
    - enforce KeepInstalledSection rule only when running on
      a network, otherwise we run into CD upgrade issues
    - when fetching the prerequists, be more robust in the 
      mirror selection (and add tests for this)
  * DistUpgrade/DistUpgrade.cfg:
    - add slocate to the force obsoletes, mlocate replaces it
  
  [ Brian Murray ]
  * Dialog enhancements and typo fixes (LP: 182055)

update-manager (1:0.87.6) hardy; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - fix removal of obsolete packages (regression from 0.87.5)

update-manager (1:0.87.5) hardy; urgency=low

  * UpdateManager/UpdateManager.py:
    - use /var/lib/apt/periodic/update-success-stamp for the
      calculation when the last update was performed (LP: #185894)
  * DistUpgrade/DistUpgradeController.py:
    - if the upgrade can not be calculated in partial upgrade mode,
      do not recommend reporting a bug (most likely transient anyway)
  * DistUpgradeView/DistUpgradeViewText.py:
    - make the restart required question more clear (LP: #155554)
  * UpdateManager/Core/DistUpgradeFetcherCore.py:
    - tidy up output when show authentication message
  * data/update-manager.8:
    - man page fixes (LP: #185615)
  * update-manager:
    - run gtk.init_check() to catch errors when DISPLAY is not
      set (pygtk does not do that automatically)

update-manager (1:0.87.4) hardy; urgency=low

  * UpdateManager/UpdateManager.py:
    - run the partial upgrader with error correction
      if the dependencies on the system are not ok
      (it will fix most problems)
  * DistUpgrade/DistUpgradeController.py, DistUpgradeCache.py:
    - if dpkg was interrupted, run "dpkg --configure -a" 
      automatically
    - if the prerequists can not be authenticated, 
  * DistUpgradeView/DistUpgradeView.py:
    - when calculating the download time in estimatedDownloadTime, 
      use the average download speed so far (if available)

update-manager (1:0.87.3) hardy; urgency=low

  * add ports.ubuntu.com to the valid mirrors (LP: #184663)
  * add --proposed to the options for do-release-upgrade
    (LP: #109290)
  * fix crash in apport report duplicate checking

update-manager (1:0.87.2) hardy; urgency=low

  * DistUpgrade/DistUpgradeApport.py:
    - better detection for followup errors when a package failed
      earlier
  * DistUpgrade/DistUpgradeController.py:
    - Be more tolerant against errors in the initial apt-get update
      operation. We disable third party sources on the later 
      sources.list rewrite anyway

update-manager (1:0.87.1) hardy; urgency=low

  * UpdateManager/UpdateManager.py:
    - fix crash if /var/lib/apt/periodic/update-stamp does not exists
      (LP: #181390)
    - fix misleading string when cache is rebuild (LP: #179354)
  * DistUpgrade/DistUpgradeCache.py:
    - be more careful with the obsoletes checking and get not
      confused if the hardy version is older than the gutsy one
      (LP: #181201)

update-manager (1:0.87) hardy; urgency=low

  * typo fixes (thanks to Brian Murray, LP: #99513, LP: #158175)
  * fix incorrect textual description (thanks to Brian Murray, 
    LP: #145130)
  * support release-upgrades from dapper for architectures on
    ports.ubuntu.com
  * UpdateManager/UpdateManager.py:
    - remove the "from $version to $version" from the main 
      list as this is duplicated information from the details tab
    - wording fixes (thanks to Matthew Paul Thomas)
    - if the update was successful, automatically close the install
      window
    - when no updates are available, display the information when the 
      last apt-get update like operation was performed
    - if there are broken dependencies on the system, try to fix 
      them on startup
  * data/UpdateManager.glade:
    - do not display what software updates are in startup progress
      dialog, this is already displayed in the main UI 
      (thanks to Matthew Paul Thomas)
    - align the ""Download size:" text so that it matches the text
      inside the buttons

update-manager (1:0.86) hardy; urgency=low

  * DistUpgrade/DistUpgradeController.py:
    - merged fixes from Brian Murray (thanks!);
      LP: #162978, LP: #64473
    - fix getting prerequists for ports.ubuntu.com
      (thanks to lamont)
  * DistUpgrade/DistUpgradeCache.py:
    - keep the lists dir locked all the time to avoid a 
      possible race
  * DistUpgrade/DistUpgrade.cfg:
    - added gobuntu-desktop to the list of supported
      meta-packages
  * data/update-manager.desktop.in:
    - remove deprecated entries (thanks to Kmos)
  * UpdateManager/Core/MetaRelease.py:
    - add support to prompt only for specifc release upgrades 
      (e.g. lts->lts)
  * data/release-upgrades:
    - set the default prompting for hardy to "Prompt only for
      a new lts version"
  * DistUpgrade/DistUpgrade.cfg.dapper,
    DistUpgrade/prerequists-sources.list.dapper:
    - add support for dapper->hardy upgrades
  * DistUpgrade/DistUpgradeConfigParser.py:
    - add overwrite support for the configuration to support
      upgrades to multiple target releases with the same
      upgrader
  * data/update-manager.schemas.in:
    - /apps/update-manager/check_dist_upgrades is deprecated
  * utils/demotions.py:
    - make it more flexible to support generating both 
      dapper and gutsy demotions

update-manager (1:0.85.4) hardy; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - do not use python2.5 try:/expect:/finally: - we need to run
      on 2.4 as well for dapper->hardy (LP: #164947)

update-manager (1:0.85.3) hardy; urgency=low

  * DistUpgrade/DistUpgrade.cfg, 
    DistUpgrade/DistUpgrade.glade,
    DistUpgrade/ReleaseAnnouncement,
    DistUpgrade/window_main.ui:
    - updated for hardy
  * DistUpgrade/DistUpgradeControler.py,:
    DistUpgrade/DistUpgradeCache.py:
    - better description whats happening when calculating the 
      release-upgrade
    - keep the GUI responsive while calculating the upgrade

update-manager (1:0.85.2) hardy; urgency=low

  * debian/control:
    - added missing "XS-Vcs-Bzr" header (thanks to Brian 
  * debian/rules:
    - dh_iconcache is obsolete, use dh_icons instead

update-manager (1:0.85.1) hardy; urgency=low

  * fix FTBFS

update-manager (1:0.85) hardy; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - fix crash when packages get downgraded (LP: #154257)
  * DistUpgrade/DistUpgradeController.py:
    - fix typo in classname (thanks to Matt T. Proud)
  * DistUpgrade/DistUpgrade.cfg:
    - update for hardy

update-manager (1:0.81) gutsy; urgency=low

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeViewKDE.py:
   - Add word wrap to quesiton dialogue
  
  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeControler.py:
    - make the commercial archive transition more robust
    - when forcing the evms removal, ensure that all 
      evms rdepends get obsoleted so that the safety checks
      in the upgrader do not kick in and prevent the removal
    - when calculating the size required in /boot take into account
      that installed initramfs images create a .bak file
  * updated list of demoted packages
  * updated ReleaseAnnouncement to include final text
  * updated demotions and mirrors to current gutsy

update-manager (1:0.80) gutsy; urgency=low

  * DistUpgrade/DistUpgradeControler.py:
    - enable transition to gutsy partner repository on 
      upgrade now that we have a archive
    - workaround kde tempdir handling (LP: #149186)

update-manager (1:0.79) gutsy; urgency=low

  * DistUpgrade/DistUpgradeControler.py:
    - do not log apts debug output to the user in server
      upgrade mode
    - when running in partial upgrade mode, do not run apport,
      this is handled by the libapt apport integration now, 
      (LP:#139394)
  * DistUpgrade/DistUpgradeCache.py,DistUpgradeControler.py:  
    - detect and workaround upgrade issues with envy
  * update-manager:
    - show version with --version (LP: #137353)
  * DistUpgrade/DistUpgradeViewKDE.py:
    - fix crash with invalid utf-8 in polish locale (LP: #145351)
  * UpdateManager/UpdateManager.py:
    - remove debug output (LP: #145494)
  * DistUpgrade/DistUpgradeControler.py:
    - fix lock detection (LP: #145463)
  * UpdateManager/Common/utils.py:
    - show "0 KB" download size if there is nothing to download 
      (LP: #145308)
  * DistUpgrade/demoted.cfg, utils/demotions.py:
    - do not display demotions if they are replaced by something that is
      in main (e.g. gaim->pidgin, LP: #145767)
  * DistUpgrade/ReleaseAnnouncement:
    - update for the beta release
  * DistUpgrade/DistUpgradeControler.py:
    - fix typo in pre-requists (thanks to Stuart Bishop)
  * debian/control:
    - tighten update-manager depend on update-manager-core
  * UpdateManager/Core/DistUpgradeFetcherCore.py:
    - move country_mirror code into Core (LP: #145116)
  * UpdateManager/Core/MetaReleaseCore.py, 
    tests/interactive_fetch-release_upgrader.py:
    - fix test failure

update-manager (1:0.78) gutsy; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py:
    - Fix button in conffile dialogue

update-manager (1:0.77) gutsy; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py:
    - fix crash in conffile dialogue setup

update-manager (1:0.76) gutsy; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeCache.py:
    - ensure that the util-linux -> nfs-common transition
      happens (LP: #141559)

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeViewKDE.py:
    - copy Xauthority file if necessary

update-manager (1:0.75) gutsy; urgency=low

  * DistUpgrade/DistUpgradeViewGtk.py:
    - work around broken vte forkpty() env add
  * DistUpgrade/DistUpgradeControler.py:
    - fix type of installed_demotions from apt.Package to pkgname
      (LP: #144417)
  * po/*.po:
    - updated from latest launchpad translations
  * UpdateManager/DistUpgradeFetcherCore.py:
    - fix missing command line propergation when run as non-root
      (LP: #144451)

update-manager (1:0.74) gutsy; urgency=low

  * DistUpgrade/DistUpgradeCache.py:
    - ensure that users with the "lowlatency" kernel get 
      transitioned correctly to a new kernel (LP: #129458)
  * DistUpgrade/DistUpgradeControler.py:
    - work around kde being too clever in tempdirs (LP: #139319)
  * po/POTFILES.in:
    - add missing files (LP: #141033)

update-manager (1:0.73) gutsy; urgency=low

  * UpdateManager/UpdateManager.py:
    - display new installs in the list
  * UpdateManager/Common/utils.py:
    - fix countrymirror to deal with non-utf8 locales (LP: #138299)
  * tests/test_update_origin.py:
    - added test for this country_mirror()
  * DistUpgrade/DistUpgradeControler.py:
    - check trust of pre-requists files before downloading them
    - support pre-requists on the CD as well
    - preserve the logs on self update from the net
  * DistUpgrade/build-tarball.sh:
    - fix auto-generation of target distro in cdromupgrade 
      script (LP:#138354) 
  * data/update-manager.8:
    - new manpage (thanks to  Bruno Mangin, LP: #107015)

update-manager (1:0.72) gutsy; urgency=low

  * UpdateManager/Core/MetaRelease.py:
    - fix target filename for meta-release files so that 
      correct I-M-S information is used
  * DistUpgrade/DistUpgrade.cfg:
    - use "release-upgrader-dpkg", "release-upgrader-apt" as
      update-pre-requists to fully support dpkg triggers (LP: #134000)
    - add mythubuntu-desktop to the valid metapackages
  * DistUpgrade/DistUpgradeControler.py:
    - fix pre-requists fetching, do not run the resolver as the udebss
      are not installable on a regular system
    - generate more log information to make diagnosing problems easier
    - setup RELEASE_UPGRADE_IN_PROGRESS environemnt
    - use custom invoke-rc.d during the upgrade so that failures to
      restart a daemon are not fatal
  * DistUpgrade/prerequists-sources.list:
    - point to the archive for the pre-requists now

update-manager (1:0.71) gutsy; urgency=low

  [ Michel Vogt ]
  * DistUpgrade/DistUpgradeViewGtk.py:
    - fix crash in _terminal_log code
  * DistUpgrade/DistUpgradeControler.py:
    - disable archive.canonical.com for now until
      a gutsy repository is created there
    - fix size requirement reporting (LP: #137539)

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeViewKDE.py
    - Implement show/hide button on conf file dialogue
  * DistUpgrade/removal_blacklist.cfg
    - Add xubuntu-desktop and gobuntu-desktop

update-manager (1:0.70) gutsy; urgency=low

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeViewKDE.py
    - Use apport for crashes
    - Don't use dcop, it doesn't work with kdesudo
    - Fix UI layout

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeControler.py:
    - show human readable size when displaying "not enough free space" 
      error
    - when rewriting sources.list, transition the commercial
      package archive to the new location and "partner" name
  * DistUpgrade/DistUpgradeCache.py:
    - fix bogus log messages about missing "required" priority packages
  * DistUpgrade/DistUpgradeViewGtk.py:
    - remove debug messages
  * DistUpgrade/DistUpgrade.cfg:
    - remove gnome-cups-manager on upgrade, system-config-printer 
      replaces it (LP: #107766)
    - set cursor to the start of the details list (LP: #134873)
    - added ubuntustudio-desktop, ichthux-desktop to valid metapackages
      (LP: #131936)
  * DistUpgrade/dist-upgrade.py, DistUpgrade/DistUpgradeViewText.py,
    DistUpgrade/DistUpgradeViewKDE.py, DistUpgrade/DistUpgradeViewGtk.py:
    - make logdir a config option too
  * UpdateManager/UpdateManager.py, UpdateManager/Common/utils.py:
    - move inhibit_sleep(), allow_sleep() into common code and call
      the freedesktop dbus interface instead of the deprecated gnome
      interface (LP: #136617)
  * tests/test_sources_list.py, tests/data-sources-list-test:
    - added tests for sources.list rewriting

update-manager (1:0.69) gutsy; urgency=low

  [ Michael Vogt ]
  * UpdateManager/Core/MetaRelease.py:
    - remove zero size meta-release files (LP: #127263)
  * utils/demoted.cfg:
    - updated to current gutsy
  * DistUpgrade/DistUpgrade.cfg:
    - added "esound", "esound-common" to forced obsoleted
      packages (replaced by pulseaudio)

  [ Jonathan Riddell ]
  * Change version text from 7.04 to 7.10 in KDE frontend

update-manager (1:0.68) gutsy; urgency=low

  * UpdateManager/DistUpgradeFetcherCore.py:
    - be extra paranoid when using ${countrymirror} 
  * DistUpgrade/DistUpgradeControler.py:
    - support countrymirror in prerequists.sources.list file
      too
  * UpdateManager/Common/utils.py:
    - added country_mirror() function

update-manager (1:0.67) gutsy; urgency=low

  * UpdateManager/UpdateManager.py,
    tests/test_update_origin.py:
    - when checking for update category (Security, Important, ...)
      not only check candidateVersion but all intermediate versions
      too
    - added test for the new matcher behaviour
  * DistUpgrade/DistUpgradeControler.py:
    - fix PreRequists fetching 
    - better error checking/logging
  * DistUpgrade/DistUpgradeViewGtk.py,
    DistUpgrade/DistUpgradeViewKDE.py,:
    - improve error message when a package fails to install
      (thanks to Chris Jones)
  * DistUpgrade/DistUpgradeViewGtk.py:
    - show "cancel" button while fetching stuff
  * UpdateManager/DistUpgradeFetcher.py, 
    UpdateManager/DistUpgradeFetcherCore.py:
    - support ${countrymirror} in meta-release information
  * setup.py, setup.cfg:
    - updated for new python-distutils-extra

update-manager (1:0.66) gutsy; urgency=low

  * DistUpgrade/DistUpgradeControler.py:
    - support listing and fetching of upgrade PreRequists
    - transition archive.canonical.com to new layout
    - mark evms as obsolete if it is not in use
    - transition powerpc users to ports.ubuntu.com
    - implement Depends checking for the selected
      View
  (as speced in https://wiki.ubuntu.com/UpgradePrerequisites)
  * DistUpgrade/Core/DistUpgradeFetcherCore.py:
    - added ignore-time-conflict when calling gpg (thanks to
      Evan)
  * utils/demoted.cfg, DistUpgrade/mirrors.cfg, 
    DistUpgrade/ReleaseAnnouncement:
    - updated for current gutsy 
  * DistUpgrade/DistUpgrade.cfg:
    - mark desktop-effects as obsolete on ubuntu-desktop upgrades
      (the appearance capplet replaces it)

update-manager (1:0.65) gutsy; urgency=low

  * debian/rules:
    - add test for fetching the upgrader to release to
      arch-build target
  * update-manager.py:
    - fix breakage in "partial upgrade" mode

update-manager (1:0.64) gutsy; urgency=low

  * UpdateManager/DistUpgradeFetcher.py:
    - add missing "import os"
  * update-manager.py:
    - fix incorrect STEP_FETCH_INSTALL import (Fixes LP:#120484)

update-manager (1:0.63) gutsy; urgency=low

  * fix i18n issue (Fixes LP:#114207)
  * DistUpgrade/DistUpgradeCache.py:
    - if "386" (UP) kernel is installed on SMP machine, automatically 
      switch to SMP kernel (Fixes LP: #106387)
  * DistUpgrade/DistUpgrade.cfg:
    - set python2.3 to remove list to ensure smooth upgrade 
      (Fixes LP: #108147)
  * DistUpgrade/DistUpgradeControler.py:
    - show total needed space in not-enough-free-space message
      (Fixes LP: #46775)
    - fix in snapshot feature (Fixes LP: #108413)
    - deal better with very slow downloads (disable cache cleanup)
    - improve free space calculation in /boot (Fixes LP: #116163, #104337)
    - implement SystemCleanup spec kernel removal
    - implement SystemCleanup spec unused dependencies removal
  * Separate downloading and upgrading (Fixes LP: #91978)
  * Show demotions before runing the upgrade (Fixes LP: #91998)
  * UpdateManager/UpdateManager.py:
    - re-check for new releases too when the user clicks on 
      "Check" (Fixes LP: #107452)

update-manager (1:0.62) gutsy; urgency=low

  * revert locking fix, it broke release upgrades
  * fix upgrade string

update-manager (1:0.61) gutsy; urgency=low

  * add missing dh_gconf (LP#114569)
  * fix mispelled entry in removal_blacklist (LP#107558)
  * fix locking problem (LP#108446)
  * make the wording of the free space message more clear

update-manager (1:0.60) gutsy; urgency=low

  * DistUpgrade/DistUpgradeControler.py:
    - fix free space check when the dir checked is a symlink
      (LP#106804)
    - increase minAge for the apt cleanup cron job during the upgrade
      to fix race for people with very slow network (LP#109548)
    - deal with invalid lines in /proc/mounts when calculating 
      the free space (LP#108284)
  * cdromupgrade:
    - do not call any authentication mechanism, that is the
      responsibility of the user (LP#107431)
  * DistUpgrade/DistUpgradeViewKDE.py:
    - fix a bug in the cdrom progress (LP#107451)
  * DistUpgrade/DistUpgradeViewText.py:
    - send correct package failure information to log (LP#109209)
  * DistUpgrade/crashdialog.ui
    - Fix bug report URL in crash dialogue (LP#108969)
  * UpdateManager/Core/MetaRelease.py:
    - fix in I-M-S 304 handling (LP#109216)
  * DistUpgrade/DistUpgradeCache.py:
    - check RemovalBlacklist early when removing a package to
      work-around crash in problem resolver (LP#109014)
  * DistUpgrade/DistUpgrade.cfg:
    - updated for gutsy
    - add "ltsp-client", "ltspfsd" to the remove list to ensure that
      it does not get installed on a regular system (LP#109638)
  * DistUpgrade/DistUpgradeApport.py:
    - protect against errors when launching apport (LP#108131)

update-manager (1:0.59.21) feisty-proposed; urgency=low

  * UpdateManager/Core/MetaRelease.py:
    - send pragma: no-cache (LP#107716)
    - fix bug in time representation for i-m-s (LP#107716)

update-manager (1:0.59.20) feisty; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py:
    - do not crash in utf8() if the str is already unicode 
      (LP#106863)

update-manager (1:0.59.19) feisty; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py:
    - disable apt-listchanges in the kde frontend too
    - fix broken terminal interaction (LP#106367)
    - ensure that there is only a single konsole widget 
      visible (LP#106541)

update-manager (1:0.59.18) feisty; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeViewKDE.py:
    - fix i18n initialization (LP#106221)

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeViewKDE.py:
    - fix encoding in dialog_error (LP#106221)

update-manager (1:0.59.17) feisty; urgency=low

  * DistUpgrade/DistUpgradeViewGtk.py:
    - fix crash in on_window_main_delete_event() (LP#104701)
  * DistUpgrade/apt-autoinst-fixup.py:
    - set mdadm to manually installed (LP#105663)
  * DistUpgrade/DistUpgradeControler.py:
    - add python symlink sanity check (LP#75557)
  * DistUpgrade/ReleaseAnnouncement:
    - prepare for the final version
  * po/
    - updated to the latest translations from rosetta

update-manager (1:0.59.16) feisty; urgency=low

  * set useDevelopmentRelease=False in the self updater on 
    the CD (LP#99171)
  * fix another issue with a unresponsive GUI
  * work around upgrade issue with pango-libthai (LP#104384)

update-manager (1:0.59.15) feisty; urgency=low

  * DistUpgrade/DistUpgradeControler.py:
    - keep the GUI alive while calculating the obsolete
      packages

update-manager (1:0.59.14) feisty; urgency=low

  * DistUpgrade/DistUpgradeControler.py:
    - fix sources.list rewriting for people with internal or
      unofficial mirrors (LP#73463)
  * DistUpgrade/DistUpgradeCache.py:
    - workaround apache2/php5 upgrade failures (LP#95325)

update-manager (1:0.59.13) feisty; urgency=low

  * po/POTFILES.in:
    - reomove [type: ] this confused intltool
  * DistUpgradeControler.py:
    - work around problem with kde tempfile extraction 
      (LP#99380)

update-manager (1:0.59.12) feisty; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py:
    - set debian frontend to "kde"
  * DistUpgrade/DistUpgradeCache.py:
    - do not crash when uname -r can't be parsed (LP#97663)
    - remove the nfs upgrade question again, the kernel team
      fixed the regression
  * DistUpgrade/DistUpgradeApport.py:
    - do not crash if no apport gui is available (LP#97498)
  * DistUpgrade/DistUpgradeViewText.py:
    - support details in text-mode (LP#94129)
  * DistUpgrade/DistUpgradeControler.py:
    - fix incorrect auto-installed information from meta-pkgs 
      (LP#86921)
    - rewrite /etc/fstab cdrom entries (LP#86424,#79327)
    - fix upgrade for people with no admin group (LP#93279)
    - when encountering a error, first show the error dialog,
      then run the recover (LP#92366)
  * dist-upgrade.py:
    - support fallback when a frontend view can not be imported
      (LP#89568)
    - log the version of the upgrader as well
  * DistUpgrade/mirrors.cfg:
    - updated with the current mirror RSS feed from LP

update-manager (1:0.59.11) feisty; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py:
    - fix crash in mediaChange (LP#96849)
  * DistUpgrade/DistUpgradeViewText.py:
    - fix crash on broken packages (LP#96444)
  * DistUpgrade/DistUpgradeCache.py:
    - ensure that the latest kernel is always selected (LP#96196)
    - added nfs-common check in feistyQuirks and ask to install
      it if it appears to be missing
  * DistUpgrade/DistUpgradeControler.py:
    - add any additional sanity check at the start of the upgrade
      to check if the base distro is supported

update-manager (1:0.59.10) feisty; urgency=low

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeViewKDE.py:
    - i18n KDE frontend fixes, LP#95638, LP#94927
    - set text on confirm dialogue buttons
    - (re)spawn embedded konsole for each fork, 
      fixes crash when removing packages
    - Add on_window_main_delete_event, stops the user closing the window

update-manager (1:0.59.9) feisty; urgency=low

  [Sebastian Heinlein]
  * Hide help button - the outdated documentation is confusing (LP#44944)
  [Michael Vogt]
  * Use .update-manager-core dir
  * Fix bug in writable check for /var/lib/update-manager (LP#95599)
  * Ensure that /var/lib/update-manager is available
  * inhibit sleep when runing the release upgrader(LP#70058)
  * make sure that we do not run with a interactive debconf frontend 
    on server upgrade (for packages like quagga)
  * fix race condition in free space checking (LP#96482), thanks
    to Jane Silber for reporting

update-manager (1:0.59.8) feisty; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py:
    - fix crash in error dialog (LP#94229)
    - i18n KDE frontend
  * DistUpgrade/DistUpgradeCache.py:
    - mention xubuntu-desktop too (LP#94443)
  * DistUpgrade/DistUpgradeCache.py:
    - fix in the logfile handling in server mode
  * DistUpgrade/DistUpgrade.cfg:
    - fix KeyDependency for xubuntu detection
  * UpdateManager/UpdateManager.py:
    - do not crash if UnInhibit dbus signal can not be send 
      (LP#86572)

update-manager (1:0.59.7) feisty; urgency=low

  * NEWS: removed empty file (LP#92250)
  * DistUpgrade/DistUpgradeControler.py:
    - fix wording of the "use network" question
    - better apport integration
    - fix in the progress reporting where the report was off-by-one
  * DistUpgrade/DistUpgradeFetcherSelf.py:
    - fix run_options argument
  * UpdateManager/Core/MetaRelease.py:
    - fix race conditin in download thread (thanks to Matt
      Zimmerman for reporting the issue)
  * do-release-upgrade:
    - added option --frontend, --mode

update-manager (1:0.59.6) feisty; urgency=low

  * DistUpgrade/DistUpgradeView.py, DistUpgradeControler.py:
    - fixes in the apport integration

update-manager (1:0.59.5) feisty; urgency=low

  * UpdateManager/fakegconf.py:
    - Fix missing {get,set}_string() in fakegconf
  * DistUpgrade/dialog_changes.ui
    - Fix alignment of image
  * DistUpgrade/dialog_error.ui
    - Fix caption
    - Make text box read only
  * DistUpgrade/DistUpgradeViewKDE.py
    - remove unused argument to reportBug()
    - fix caption of information box
    - show close button on error box

update-manager (1:0.59.4) feisty; urgency=low

  * data/glade/UpdateManager.glade:
    - improve the wording of the dist-upgrade required dialog (LP#88706)
  * update-manager:
    - set better dialog caption (LP#88706)
  * DistUpgrade/DistUpgradeControler.py:
    - supress reboot notification when a upgrade is in progress (LP#91999)

update-manager (1:0.59.3) feisty; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py:
    - Fix incorrect variable name, LP No 91887

update-manager (1:0.59.2) feisty; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py:
    - Fix reference to konsole_frame (LP No 84717 comment 33)

update-manager (1:0.59.1) feisty; urgency=low

  [ Michael Vogt ]
  * DistUpgrade/DistUpgradeViewGtk.py:
    - do not fail if loading the svg pixbuf loader fails (LP#91593)

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeViewKDE.py:
    - import KRun, closes https://launchpad.net/bugs/91072
    - fix non-existant variable use, closes https://launchpad.net/bugs/91386
    - fix incorrect method name, closes https://launchpad.net/bugs/91295

update-manager (1:0.59) feisty; urgency=low

  * DistUpgrade/DistUpgradeViewKDE.py
    - quit any running instances of Adept
  * DistUpgrade/dist-upgrade.py
    - improve error message when failing to load frontend

update-manager (1:0.58) feisty; urgency=low

  * UpdateManager/UpdateManager.py:
    - do not crash if download size can not be calculated (LP#90547)
  * fix build for all python versions (thanks to doko for help!) 
    (LP#90269)
  * strip changelog epoch too (LP#45566)
  * fix spelling mistakes (thanks to Bruce Cowan, LP#90833)
  * update download size if "check/uncheck" all was selected from 
    right-click menu
  * correct download speed string (LP#73721)
  * fix in the german translation (LP#68384)

update-manager (1:0.57.8) feisty; urgency=low

  * debian/rules:
    - moved dist-upgrade_$version generation to binary-indep

update-manager (1:0.57.7) feisty; urgency=low

  * DistUpgrade/DistUpgradeView.py:
    - revert earlier commit in FuzzyTimeToStr() to make it not crash
  * debian/rules:
    - strip the epoch before runing dpkg-addfiles

update-manager (1:0.57.6) feisty; urgency=low

  [ Jonathan Riddell ]
  * DistUpgrade/DistUpgradeViewKDE.py
    - Fix crash with incorrect connect() calls

  [ Michael Vogt ]
  * UpdateManager/ChangelogViewer.py:
    - fix some margins (thanks to Sebastian Heinlein)

update-manager (1:0.57.5) feisty; urgency=low

  * UpdateManager/UpdateManager.py:
    - check for None in toggled() (LP#88032)

update-manager (1:0.57.4) feisty; urgency=low

  * DistUpgrade/DistUpgradeControler.py:
    - workaround problem in python-apt (no support for PyLong in SizeToStr)
      LP#84019
  * DistUpgrade/DistUpgradeViewGtk.py:
    - keep a reference of the svg pibbuf loader around (LP#86699)
  * UpdateManager/fakegconf.py:
    - fix crash on xubuntu when gconf is not available (LP#86673)

update-manager (0.57.3) feisty; urgency=low

  * debian/rules:
    - build a raw-dist-upgrader in additon to the debs
  * data/glade/UpdateManager.glade:
    - fix bad grammar (thanks to Matthew Thomas) LP#85258
    - make Update Manager the consistent name (thanks to Matthew Thomas) 
      LP#85253
  * merged ReleaseAnnouncement wording update from Brian Murray
  * UpdateManager/Core/MetaRelease.py:
    - fix missing import (LP#85515)

update-manager (0.57.2) feisty; urgency=low

  * fix crash in upgrade mode (LP#84915)

update-manager (0.57.1) feisty; urgency=low

  * fix proxy authentication parser (lp: #83563)
  * fix crash in check_all_updates_installable() (LP#84776)
  * fix exception when strange permissions are set on meta-release
    file (LP#84724)
  * fix error dialog if cache init fails (LP#83185)

update-manager (0.57) feisty; urgency=low

  * added clickable CVE and buglinks

update-manager (0.56.1) feisty; urgency=low

  * fix FTBFS 
  * update po/

update-manager (0.56) feisty; urgency=low

  * added --proposed switch to fetch a release-upgrader from a different
    location (similar to the -proposed pocket in the archive)
  * split into update-manager and update-manager-core and support
    cli release upgrades with the later
  * added fdsend module to support file descriptor passing over sockets
    this will allow a better seperation between frontend and backend
    in the future

update-manager (0.55.1) feisty; urgency=low

  * fix FTBFS (missing cdbs b-d)

update-manager (0.55) feisty; urgency=low

  * moved software-properties into its own source package to
    support a kde frontend

update-manager (0.53.6) feisty; urgency=low

  * properly extract the package name that fails before 
    calling out to apports package_hook
  * fix crash on exit before the main loop is run (lp: #82744)

update-manager (0.53.5) feisty; urgency=low

  * update to the new exceptions from python-dbus in
    setupDBus (lp: #81802)
  * fix FTFBS

update-manager (0.53.4) feisty; urgency=low

  * fix python dependency (lp: #80976)
  * add apport support to send in bugreports

update-manager (0.53.3) feisty; urgency=low

  * fix python dependency (lp: #80976)
  * fix the GenericName in update-manager and software-properties 
    (lp: #78932)
  * workaround problem when a meta-release file is created by root
    in the users homedir (lp: #80713)

update-manager (0.53.2) feisty; urgency=low

  * fix the cdromupgrade script to use feisty

update-manager (0.53.1) feisty; urgency=low

  * Build-depend on python-dev.

update-manager (0.52) feisty; urgency=low

  * UpdateManager/UpdateManager.py:
    - more robust error reporting from libapt (lp: #74797)
  * SoftwareProperties/SoftwareProperties.py:
    - do not crash if template is missing (lp: #70580)
  * updated to latest python policy

update-manager (0.51) feisty; urgency=low

  * data/channels/Ubuntu.info.in:
    - updated for feisty

update-manager (0.50) feisty; urgency=low

  * support --disable-component (AlwaysEnableUniverseMultiverse spec)
  * look for lsb_release in PATH instead of hardcoding it (lp: #73075)

update-manager (0.45.1) edgy-updates; urgency=low

  * handle unexpected data from data more gracefuly (lp: #68553)

update-manager (0.45) edgy; urgency=low

  * debian/control:
    - added dependency on python-gconf
    - removed recommends on python-gnome2

update-manager (0.44.17) edgy; urgency=low

  * memory leak fixed (lp: #43096)

update-manager (0.44.16) edgy; urgency=low

  * fix proxy usage when runing in non-root mode (lp: #40626)

update-manager (0.44.15) edgy; urgency=low

  * added missing python-vte dependency (lp: #63609)
  * added missing gksu dependency (lp: #63572)
  * don't remove xchat automatically anymore on upgrade (leftover
    from breezy->dapper) (lp: #63881)
  * do not come up with bogus dist-upgrade suggestions
  * fix bad english grammar (lp: #63761, #63474)
  * fix in the edgyUpdates quirks handler (lp: #63723)
  * catch error from _tryMarkObsoleteForRemoval() (lp: #63617)
  * fix plural forms for ro, pl (lp: #46421)
  * properly escape comments before displaying them (lp: #63475)

update-manager (0.44.14) edgy; urgency=low

  * fix some incorrect i18n markings (lp: #62681)

update-manager (0.44.13) edgy; urgency=low

  * fix missing i18n declarations (lp: #62519)
  * data/glade/SoftwareProperties.glade:
    - fix missing "translatable" property (lp: #62681)
  * DistUpgrade:
    - deal better with the python transition and the hpijs 
      upgrade (lp: #62948)
  * UpdateManager/UpdateManager.py:
    - put the cancel button inside the text-area to avoid flickering
    - make sure that src_ver is always initialized (thanks to
      Simira for reporting)
    - filter python-apt future warning (especially for seb128)
  * DistUprade/DistUpgradeControler.py:
    - check for self.sources, self.aptcdrom before using it (lp: #61852)

update-manager (0.44.12) edgy; urgency=low

  * DistUpgrade/DistUpgradeViewGtk.py:
    - use '%d' instead of '%s' where appropriate (lp: #60239)
  * fixed lots of typos (lp: #60633)

update-manager (0.44.11) edgy; urgency=low

  * UpdateManager/UpdateManager.py:
    - fix error in get_changelog (lp: #59940).
      Thanks to Denis Washington
    - bugfix in the ListStore
    - use the update-manager desktop file when runing synaptic
      as the backend to get a consistent UI
    - UI improvements (thanks to Sebastian Heinlein!)
    - remove branding

update-manager (0.44.10) edgy; urgency=low

  * aptsources.py:
    - fix add_component() to avoid duplicated components
    - added MirrorsFile key to DistInfo code to have a better idea
      about the available mirrors
  * debian/control:
    - updated dbus dependencies (lp: #59862)

update-manager (0.44.9) edgy; urgency=low

  * SoftwareProperties/SoftwareProperties.py:
    - bugfix in the popcon enable code (lp: #59540)

update-manager (0.44.8) edgy; urgency=low

  * fix missing /var/log/dist-upgrade

update-manager (0.44.7) edgy; urgency=low

  * UpdateManager/UpdateManager.py:
    - be more accurate about dependencies when the user selects only
      a supset of the packages

update-manager (0.44.6) edgy; urgency=low

  * SoftwareProperties/SoftwareProperties.py:
    - fix inconsistency in the new software-sources dialog
  * integrate DistUpgrade code into UpdateManager to make sure
    that after e.g. a CDROM upgrade the rest of the system can still
    be fully upgraded over the net

update-manager (0.44.5) edgy; urgency=low

  * install the DistUpgrade package too
  * data/channels/Ubuntu.info.in:
    - warty is no longer officially supported 

update-manager (0.44.4) edgy; urgency=low

  * SoftwareProperties/SoftwareProperties.py:
    - don't bomb when searching for the mirror (lp: #57015)
  * UpdateManager/UpdateManager.py:
    - added "%s-proposed" to the list of known origins

update-manager (0.44.3) edgy; urgency=low

  * help/C/update-manager-C.omf:
    - fix url (thanks to daniel holbach, lp: #45548)
  * show the units better
  * don't jump around on row activation 
    (thanks to Sebastian Heinlein)
  * send "inhibit sleep" to power-manager while applying 
    updates  (lp #40697)

update-manager (0.44.2) edgy; urgency=low

  * added select all/unselect all (thanks to Sebastian Heinlein)
  * wording fixes
  * fix update counting bug 

update-manager (0.44.1) edgy; urgency=low

  * make UpdateManager check for new distribution releases by
    default again
  * fix dist-upgrade fetching when run as non-root. 
  * sort the package list by the origin (UpdateManagerEdgy spec)

update-manager (0.44) edgy; urgency=low

  * new SoftwareProperties GUI (thanks to Sebastian Heinlein)
  * support easy Popcon pariticipation

update-manager (0.43) edgy; urgency=low

  * fixes in the changelog reading code
  * speedup in the cache clear code
  * runs as user by default now
  * uses dbus to implement singleton behaviour
  * updated the software-properties code to know about edgy

update-manager (0.42.2ubuntu22) dapper; urgency=low

  * UpdateManager/UpdateManager.py:
    - fix a 'brown paperback' bug when the Meta-Release file
      checked (#46537)

update-manager (0.42.2ubuntu21) dapper; urgency=low

  * UpdateManager/UpdateManager.py:
    - when a distribution release becomes available, display the 
      version, not the codename (as per 
      https://wiki.ubuntu.com/CodeNamesToVersionNumbers)
    - fix a string that was not marked transltable

update-manager (0.42.2ubuntu20) dapper; urgency=low

  * SoftwareProperties/aptsources.py, channels/Ubuntu.info.in:
    - remove the codenames from the releases (as per 
      https://wiki.ubuntu.com/CodeNamesToVersionNumbers)

update-manager (0.42.2ubuntu19) dapper; urgency=low

  * help/C/figures:
    - applied "pngcrush" on the figures in the manual,
      this saves 4 MB uncompressed (ubuntu: #45901)

update-manager (0.42.2ubuntu18) dapper; urgency=low

  * data/SoftwareProperties.glade:
    - fix missing 'translatable="yes"' property (ubuntu: #44409)
    - increase width to 620 (ubuntu: #40540)

update-manager (0.42.2ubuntu17) dapper; urgency=low

  * debian/control:
    - depend on later python-apt (#45325)
  * SoftwareProperties/SoftwareProperties.py:
    - fix key updating after import (ubuntu #44927)
  * UpdateManager/UpdateManager.py:
    - remove debug output

update-manager (0.42.2ubuntu16) dapper; urgency=low

  * use version and section of the source package (if this information is
    available) when building the changelog URL (ubuntu #40058)
  * SoftwareProperties/SoftwareProperties.py:
    - if no config is found create a new one (ubuntu: #37560)
  * UpdateManager/UpdateManager.py:
    - fix problem in changelog reading code when matching against
      installed versions with epochs (ubuntu: #40058)

update-manager (0.42.2ubuntu15) dapper; urgency=low

  * disable the install button if there no updates (ubuntu: #42284)
    (Thanks to Sebastian Heinlein)
  * show main window *after* restoring the size (ubuntu: #42277)
    (Thanks to Sebastian Heinlein)
  * fix broken spelling, typos, wording (ubuntu: #42431, #28777, 
    #40425, #40727)
  * help/C: merged from the docteam svn (ubuntu: 36092)

update-manager (0.42.2ubuntu14) dapper; urgency=low

  * wording/glade file fixes (thanks to Sebastian Heinlein)
  * many updates to the dist-upgrader code

update-manager (0.42.2ubuntu13) dapper; urgency=low

  * po/POTFILES.in: add missing desktop file (ubuntu: #39410)
  * UpdateManager/UpdateManager.py: 
    - fix in the get_changelog logic (ubuntu: #40058)
    - correct a error in the changelog parser (ubuntu: #40060)
    - fix download size reporting (ubuntu: #39579)
  * debian/rules: added dh_iconcache
  * setup.py: install the icons into the hicolor icon schema
    (thanks to Sebastian Heinlein)

update-manager (0.42.2ubuntu12) dapper; urgency=low

  * channels/*.in: typo fix
  * po/POTFILES.in: add missing files (ubuntu: #38738)
  * fix the help string in update-manager (ubuntu: #23274)
  * fix the bad grammar in "Cannot install all available updates"
    (ubuntu: #32864)
  * don't inform about new distro release on dapper by default (can be
    changed via a gconf setting/commandline switch)
  * fix UI issue of the edit dialog for given templates (thanks to
    Chipzz for the patch)

update-manager (0.42.2ubuntu11) dapper; urgency=low

  * debian/control: 
    - depend on unattended-upgrades
    - move python-gnome2 to recommends (we only use gconf from it)
  * UpdateManager/fakegconf.py: update for xubuntu (thanks to Jani Monoses)

update-manager (0.42.2ubuntu10) dapper; urgency=low

  * update-manger: fix a missing import (#36138)
  * typo fix (#36123)
  * correct dapper version number (#36136)
  * keybindings fixed (#36116)
  * calc the update before downloading the changelog (#36140)
  * add a fake gconf interface for xubuntu (nop for normal ubuntu)
    (Thanks to Jani Monoses for the patch)

update-manager (0.42.2ubuntu9) dapper; urgency=low

  * Better English (tm)  (fixes #35985)
  * Use the the number of available and not selected updates to determinate
    if the system is up-to-date (fixes #35300)
  * fix ui problem with software preferences (fixes #35987)
  * fix width problem in SoftwareProperties

update-manager (0.42.2ubuntu8) dapper; urgency=low

  * fix a FTBFS

update-manager (0.42.2ubuntu7) dapper; urgency=low

  * various spelling fixes and ui-glitches 

update-manager (0.42.2ubuntu6) dapper; urgency=low

  * po/pt_BR.po: updated translation 
    (thanks to Carlos Eduardo Pedroza Santiviago)
  * po/pt.po: updated Portugise translation (thanks to Rui Azevedo)
  * debian/control: arch: all now
  * debian/rules: undo the detection in favour of the simpler update of
                  the desktop files
  * data/gnome-software-properties.desktop.in, update-manager.desktop.in:
    - added X-Ubuntu-Gettext-Domain
  * help/*: updated to latest svn

update-manager (0.42.2ubuntu5) dapper; urgency=low

  * debian/rules: Add gettext domain to .server and .desktop files to get
    language pack support for them. (Similarly to cdbs' gnome.mk)

update-manager (0.42.2ubuntu4) dapper; urgency=low

  * removed some of the gnome dependencies (gconf still in)
  * the ReleaseNotes dialog has clickable links now (thanks to Sebastian 
    Heinlein)

update-manager (0.42.2ubuntu3) dapper; urgency=low

  * fixed description of the ubuntu repository (#30813)
  * use the new synaptic --parent-window-id switch when runing the backend

update-manager (0.42.2ubuntu2) dapper; urgency=low

  * SoftwareProperties/SoftwareProperties.py:
    - re-added the internet update options (#27932)
  * data/gnome-software-properties.desktop:
    - use gksu instead of gksudo (#30057)
  * wording fixes (#30296)

update-manager (0.42.2ubuntu1) dapper; urgency=low

  * UpdateManager/MetaRelease.py: 
    - never offer a upgrade to a unsupported (i.e. developer) dist
  * data/gnome-software-properties.desktop.in: use X-KDE-SubstituteUID=true
  * small UI layout changes (should fix the cancel/close button problem)

update-manager (0.42.1ubuntu1) dapper; urgency=low

  * UpdateManagert:
    improved the HIG complicane more, removed some of the uglines
    from the last version (Malone #22090)
  * SoftwareProperties:
    improved the HIG complicane (Malone #28530)
  (thanks to Sebastian Heinlein)

update-manager (0.42ubuntu1) dapper; urgency=low

  * improved the HIG comlicane, thanks to Sebastian Heinlein:
    - Rename the button "close" to "cancel"
    - Move status bar to a separate dialog
    - Wording
    - Add a wider border around the changelog and
      description
     - Align and capitalize the button "Cancel downloading"
    (ubuntu: #28453)
  * bugfixes in the cache locking

update-manager (0.40.2) dapper; urgency=low

  * SoftwareProperties/SoftwareProperties.py:
    - fix a problem with transient/parent window in custom apt line
      dialog (ubuntu #21585)
    - fix a problem in the conf file writer that can lead to absurdly
      large files

update-manager (0.40.1) dapper; urgency=low

  * SoftwareProperties/SoftwareProperties.py:
    - make it embedded friendlier

update-manager (0.40) dapper; urgency=low

  * new upstream release:
    - switched from autotools to distutils
    - massive code cleanups 
    - use SimpleGladeApp now
    - SoftwareProperties has a new GUI
    - UpdateManager has support for upgrading from one dist to another
      now (given that the required "recipe" for the upgrade is available)
      See https://wiki.ubuntu.com/AutomaticUpgrade for details
    - use python-apt for "reload" and "add cdrom" now
    - improved the handling of sources.list a lot (including support for
      /etc/apt/sources.list.d)
  * support for the AutomaticUpgrades spec added via the meta-release 
    information
  * data/update-manager.desktop.in: 
    - use X-KDE-SubstituteUID added and use gksu now

update-manager (0.37.1+svn20050404.15) breezy; urgency=low

  * added intltool to build-depends (for rosetta)

update-manager (0.37.1+svn20050404.14) breezy; urgency=low

  * debian/rules:
    - run intltool-update -p for rosetta
  * src/update-manager.in:
    - release the lock before runing gnome-software-properties (ubuntu #17022)

update-manager (0.37.1+svn20050404.13) breezy; urgency=low

  * src/update-manager.in:
    - use the right column for type-ahead searching (ubuntu #16853)

update-manager (0.37.1+svn20050404.12) breezy; urgency=low

  * added locking support
  * use explicit path to python2.4 (thanks anthony!) (Ubuntu #16087)
  * CTRL-{w,q} close the update-manager window (Ubuntu #15729)

update-manager (0.37.1+svn20050404.11) breezy; urgency=low

  * fix a typo in the reload tooltip (thanks to P Jones) (ubuntu #14699)

update-manager (0.37.1+svn20050404.10) breezy; urgency=low

  * fix for a typo in the source of the last upload (*cough*) 

update-manager (0.37.1+svn20050404.9) breezy; urgency=low

  * do a "save" dist-upgrade (add only, no removes)

update-manager (0.37.1+svn20050404.8) breezy; urgency=low

  * if repository window is running from inside synaptic, don't show "Add
    cdrom" button (it's available in the synaptic menu already)

update-manager (0.37.1+svn20050404.7) breezy; urgency=low

  * if running from inside another application (e.g. synaptic), make sure 
    the dialogs get a correct parent (ubuntu #14001)
  * if nothing changed, do not run "reload" if runing from inside synaptic

update-manager (0.37.1+svn20050404.6) breezy; urgency=low

  * remove (parts of) ubuntu branding from the application
  * make it run only with python2.4 (ubuntu #10876)
  * make sure to always properly escape the strings displayed
    in the treeview

update-manager (0.37.1+svn20050404.5) breezy; urgency=low

  * updates where not shown sometimes, fixed that (ubuntu #13410)

update-manager (0.37.1+svn20050404.4) breezy; urgency=low

  * re-read the sources.list after a "add-custom" (ubuntu #9855)
  * settings window has a title (ubuntu #10756)
  * default actions for the buttons (ubuntu #10741)
  * various typos fixed (ubuntu #9866)
  * make sure that no dialogs are opened without a parent (ubuntu #10284)

update-manager (0.37.1+svn20050404.3) breezy; urgency=low

  * use breezy as default for newly created sources (ubuntu #13009)
  * be more carefull with preserving the mirror
  * a better explaination for the "Reload" button (ubuntu #11432)

update-manager (0.37.1+svn20050404.2) breezy; urgency=low

  * fix a small problem in the parsing code (ubuntu #8754)

update-manager (0.37.1+svn20050404.1) hoary; urgency=low

  * pickup the correct proxy settings from apt (#8668)

update-manager (0.37.1+svn20050404) hoary; urgency=low

  * translation updates:
    - xh, fr

update-manager (0.37.1+svn20050403) hoary; urgency=low

  * translation updates:
    - pt_BR, tw
  * documentation updates (thanks to Sean Wheller and
    Jeff Schering)
  * small fixes:
    - make sure to not duplicate sources.list entires (even for
      mirrors)
    - added the hoary-updates to the templates and matchers (#8600)
    - some missing i18n strings marked as such (thanks to Zygmunt Krynicki)
    - don't fail on missing net connections
    - always update the status label

update-manager (0.37.1+svn20050323) hoary; urgency=low

  * translation updates
  * gui can set the new apt cache properties now
  * warn about broken packages (#7688)
  * only ask to reload the package list if something changed (#7871)
  * various focus fixes (#7900)

update-manager (0.37.1+svn20050314) hoary; urgency=low

  * new svn snapshot, lot's of bugfixes and i18n updates.
    - fix for a ui problem (#6837)
    - read pined packages correctly (#7058)
    - update list correctly after reload (#7182)
    - tell user when dist-upgrade is needed (#7271)
    - cdrom sources can be added now too (#7315)
    - meta-release file bugfix (#7330)
    - translation updates (da, fr, es, ro, pl)

update-manager (0.37.1+svn20050304) hoary; urgency=low

  * new snapshot, use python-apt depcache now

update-manager (0.37.1+svn20050301) hoary; urgency=low

  * new snapshot, better de.po, better i18n support

update-manager (0.37.1+svn20050228.1) hoary; urgency=low

  * fixed a FTBFS (because of the "cleanfiles" in Makefile.am)

update-manager (0.37.1+svn20050228) hoary; urgency=low

  * get the correct candidate version for updatable packages
    (ubuntu #6825)

update-manager (0.37.1+svn20050221) hoary; urgency=low

  * new svn snapshot, fixes:
    - #6756: window size too big 
    - #6767, #6780: gnome-software-properties window broken

update-manager (0.37.1+svn20050219) hoary; urgency=low

  * new svn snapshot, fixes:
    - #6565, #6565 (typo)
    - #6634 (remeber last details state)
    - #6635 (progress dialog merged in main window)
    - #6578 (hide details if no updates are available)

update-manager (0.37.1) hoary; urgency=low

  * typo (#6542)
  * package list is sorted now
  * applied "hide details if system is update-to-date" patch 
    (#6578, thanks to Jorge Bernal)

update-manager (0.37) hoary; urgency=low

  * test for lock file and show error if the lock is already taken
  * use utf8 for the description
  * changelogs are fetched from http://changelogs.ubuntu.com/ now 
    (closes: #6315)
  * handle 404 from http and set the error accordingly
  * set main_window to not sensitive when downloading changelogs
  * if no updates are available, hide the checkbox column (closes: #6443)

update-manager (0.36.6) hoary; urgency=low

  * various bugfixes and embedding of synaptics progress windows

update-manager (0.36.5) hoary; urgency=low

  * disabled sources can now be displayed too (optional preference)
  * comments can be added
  * various bugfixes

update-manager (0.36.4) hoary; urgency=low

  * regression of the last upload fixed
  * gnome-software-properties can be embedded into other windows now
    (usefull for e.g. synaptic)

update-manager (0.36.3) hoary; urgency=low

  * updates to the main window design

update-manager (0.36.2) hoary; urgency=low

  * new main window layout in update-manager 
    (Michiel design, looks _so_ nice)

update-manager (0.36.1) hoary; urgency=low

  * columns are resizable now (closes: #5541)
  * lot's of typo/gui-glitches fixes (closes: #5200,  #5816, #5801, #5802)

update-manager (0.36) hoary; urgency=low

  * new upstream release, added support to control APT::Periodic::*
    variables in gnome-software-properties

update-manager (0.35) hoary; urgency=low

  * new upstream release
    - typo fix (closes: #5200)

update-manager (0.34) hoary; urgency=low

  * new upstream release

update-manager (0.33) hoary; urgency=low

  * new upstream release, featuring the gnome-software-properties

update-manager (0.32) hoary; urgency=low

  * new upstream release

update-manager (0.31-1ubuntu1) hoary; urgency=low

  * Update Build-Deps and fix FTBFS.

update-manager (0.31-1) hoary; urgency=low

  * new upstream release, added icon, desktop file and bugfix

update-manager (0.3-1) hoary; urgency=low

  * New upstream release, inital ubuntu release

update-manager (0.2-1) unstable; urgency=low

  * New upstream release.

update-manager (0.1-2) unstable; urgency=low

  * Um Yeah.

update-manager (0.1-1) unstable; urgency=low

  * Initial Release.
This commit is contained in:
Kevin Duan 2022-10-27 17:31:10 +08:00 committed by KevinDuan
commit d53aac9b40
71 changed files with 34806 additions and 0 deletions

4
Makefile Normal file
View File

@ -0,0 +1,4 @@
all:updater
updater:
cd backend && ./setup.py build

86
README.MD Normal file
View File

@ -0,0 +1,86 @@
### Software Updater for apt
- 目录架构:
```shell
backend debian Makefile plugin README.MD
```
- 其中分为控制面板插件目录`plugin` and 更新后端目录`backend`,两个模块相互隔离,公用一个包来安装
- GitLab分支介绍
- backend_dev:后端更新代码维护的分支
- plugin_dev:控制面板插件维护的分支
- dev:分支只要负责将后端更新代码和插件的代码进行合并编包测试的分支,最新的代码在此分支上
- master:负责最终出版本的分支dev上验证成功后将代码合并到master上进行编包
- 安装依赖
```
sudo apt install dh-python python3-all python3-distutils-extra gir1.2-snapd-1 apt-clone intltool at-spi2-core -y
```
-
### 后端服务:
- 后端服务主要负责更新、安装、升级等等各种安装和下载的过程处理
- 查看后端日志:`tail -f /var/log/kylin-system-updater/kylin-system-updater.log.1`
- 调试后端代码:
- 进入backend目录下直接运行`kylin-system-updater`
- 调试参数
```shell
-d 日志直接输出到终端不输出到log文件中
-n 不更新摸板不刷新source.list and important 列表
-r 替换已经运行的后端程序
-c 关闭源过滤等各种过滤代码
```
### 配置文件
- 名称:`system-updater.conf`
- 路径:`/var/lib/kylin-system-updater`
- 配置项:
```shell
#自动更新使用
[AutoUpgrade]
#升级列表,自动更新使用
upgradelist =
#系统状态
[SystemStatus]
#标志是否异常强制关闭
isabnormalreboot = False
```
### 文档
#### Aptdaemon
- https://pythonhosted.org/aptdaemon/aptdaemon.client.html?highlight=commit_packages#aptdaemon.client.AptClient.commit_packages
#### python-apt
- https://apt-team.pages.debiahn.net/python-apt/library/apt_pkg.html
#### 方法与信号接口文档
- 参考interface.md 文档

View File

@ -0,0 +1,103 @@
# AlertWatcher.py
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
#
# Copyright (c) 2010 Mohamed Amine IL Idrissi
#
# Author: Mohamed Amine IL Idrissi <ilidrissiamine@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
from __future__ import absolute_import
import logging
from gi.repository import GObject
import dbus
from dbus.mainloop.glib import DBusGMainLoop
class AlertWatcher(GObject.GObject):
""" a class that checks for alerts and reports them, like a battery
or network warning """
__gsignals__ = {"network-alert": (GObject.SignalFlags.RUN_FIRST,
None,
(GObject.TYPE_INT,)),
"battery-alert": (GObject.SignalFlags.RUN_FIRST,
None,
(GObject.TYPE_BOOLEAN,)),
"network-3g-alert": (GObject.SignalFlags.RUN_FIRST,
None,
(GObject.TYPE_BOOLEAN,
GObject.TYPE_BOOLEAN,)),
}
def __init__(self):
GObject.GObject.__init__(self)
DBusGMainLoop(set_as_default=True)
self.bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM)
# make it always connected if NM isn't available
self.network_state = 3
def check_alert_state(self):
try:
#network
obj = self.bus.get_object("org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager")
obj.connect_to_signal(
"StateChanged",
self._on_network_state_changed,
dbus_interface="org.freedesktop.NetworkManager")
interface = dbus.Interface(obj, "org.freedesktop.DBus.Properties")
self.network_state = interface.Get(
"org.freedesktop.NetworkManager", "State")
self._network_alert(self.network_state)
# power
# obj = self.bus.get_object('org.freedesktop.UPower',
# '/org/freedesktop/UPower')
# obj.connect_to_signal("Changed", self._power_changed,
# dbus_interface="org.freedesktop.UPower")
# self._power_changed()
# 3g
# self._update_3g_state()
except dbus.exceptions.DBusException as e:
logging.error(str(e))
pass
def _on_network_state_changed(self, state):
self._network_alert(state)
# self._update_3g_state()
# def _update_3g_state(self):
# from .roam import NetworkManagerHelper
# nm = NetworkManagerHelper()
# on_3g = nm.is_active_connection_gsm_or_cdma()
# is_roaming = nm.is_active_connection_gsm_or_cdma_roaming()
# self._network_3g_alert(on_3g, is_roaming)
# def _network_3g_alert(self, on_3g, is_roaming):
# self.emit("network-3g-alert", on_3g, is_roaming)
def _network_alert(self, state):
self.network_state = state
self.emit("network-alert", state)
# def _power_changed(self):
# obj = self.bus.get_object("org.freedesktop.UPower",
# "/org/freedesktop/UPower")
# interface = dbus.Interface(obj, "org.freedesktop.DBus.Properties")
# on_battery = interface.Get("org.freedesktop.UPower", "OnBattery")
# self.emit("battery-alert", on_battery)

View File

@ -0,0 +1,602 @@
# DataAcquisition.py
# supervisory control and data acquisition
#!/usr/bin/python3
import os
import json
import dbus
import uuid
import time
import socket
import base64
import shutil
import hashlib
import logging
import tarfile
import requests
import datetime
import threading
from email import message
from datetime import datetime
from binascii import a2b_hex
from Crypto.PublicKey import RSA
from urllib import parse, request
from PyQt5.QtCore import QSettings
from SystemUpdater.Core import enums
from Crypto.Cipher import PKCS1_OAEP
from json.decoder import JSONDecodeError
from dbus.exceptions import DBusException
from SystemUpdater.Core.UpdaterConfigParser import UpgradeConfig
LOCALTIDDIR = "/var/lib/kylin-system-updater/"
LOCALTIDFILE = "tidfile.conf"
MSGSNDDIR = "/var/lib/kylin-system-updater/sendinfos/"
SOURCE_PKGNAME = {
'Kylin System Updater': 'kylin-system-updater',
'Kylin Unattended Upgrade': 'unattended-upgrades'
}
class UpdateMsgCollector():
ACTION_DEFUALT_STATUS = -1
ACTION_UPDATE = 0
ACTION_INSTALL = 1
ACTION_INSTALL_DEB = 2
ACTION_CHECK_RESOLVER = 3
ACTION_DOWNLOADONLY = 4
ACTION_FIX_BROKEN = 5
ACTION_REMOVE_PACKAGES = 6
ACTION_FIX_INCOMPLETE = 7
ACTION_CLEAN = 8
ACTION_INSTALL_SHUTDOWN = 9
MODE_DEFAULT_STATUS = -1
#1、ACTION_INSTALL 安装的子类
#部分升级
MODE_INSTALL_PARTIAL = 0
#全部升级
MODE_INSTALL_ALL = 1
#系统全盘升级
MODE_INSTALL_SYSTEM = 2
#后端内部安装包使用 目前 更新配置包和升级本身使用
MODE_INSTALL_SINGLE = 3
#2、更新的子类
MODE_UPDATE_CACHE = 0
MODE_UPDATE_ALL = 1
mode_map = {
MODE_INSTALL_PARTIAL:"upgrade_system",
MODE_INSTALL_ALL:"upgrade_all",
MODE_INSTALL_PARTIAL:"upgrade_partial"
}
action_map = {
ACTION_CHECK_RESOLVER:enums.MONIT_DEPRESOLUT,
ACTION_INSTALL:enums.MONIT_INSTALL,
ACTION_INSTALL_DEB:enums.MONIT_INSTALLDEB,
10:enums.MONIT_FINISH,
"finish-update":enums.MONIT_FINISH,
"finish-install":enums.MONIT_FINISH
}
messageType_map = {
# InstallBackend.ACTION_CHECK_RESOLVER:"UpdateDetect",
ACTION_CHECK_RESOLVER:"DepResolution",
# InstallBackend.ACTION_CHECK_RESOLVER:"Downloading",
ACTION_INSTALL:"Installing",
# InstallBackend.ACTION_CHECK_RESOLVER:"UpgradeFinish",
ACTION_INSTALL_DEB:"InstallerInfo",
10:"Background-Upgrade",
"finish-update":"UpdateInfos",
"finish-install":"InstallInfos"
}
def __init__(self, manager=None):
self.uuid = ''
self.status = ''
self.upgrade_mode = ''
self.upgrade_action = ''
self.UploadMessage = {}
self.PackageInfo = {}
self.UpdateInfos = {}
self.background_version = {}
self.background_upgradable = []
self.background_list = []
self.upgrade_list = []
self.waitSendList = []
self.cache = None
self.updateManager = manager
# 转换 & 加密
self.convertor = FormatConvert(self)
# 发送器
self.sender = MessageSend(self)
logging.info("Initialize Update MessageSend Collector to success...")
def GenUploadMessage(self, dict_message, local_uuid = ''):
UploadMessage = {}
# 获取将要上传的数据,获取东八区时间
UploadMessage['createTimeStamp'] = get_east_8_time()
try:
if "packageName" in dict_message.keys():
dict_message.pop("packageName")
for key in dict_message.keys():
UploadMessage[key] = dict_message[key]
if local_uuid != '':
UploadMessage['UUID'] = str(local_uuid)
else:
UploadMessage['UUID'] = str(uuid.uuid1())
except Exception as e:
logging.error(str(e))
json_UploadMessage = self.convertor.dictConvertJson(UploadMessage)
logging.debug('Generate UploadMessage: %s.',json_UploadMessage)
self.UploadMessage = UploadMessage.copy()
UploadMessage.clear()
def GenPackageInfo(self, messageType, packageName):
PackageInfo = {}
PackageInfo['messageType'] = str(messageType)
PackageInfo['packageName'] = str(packageName)
key = str(packageName)+'_'+str(messageType)
# 获取本地tid
self.sender.GetLocalTid(key)
PackageInfo["tid"] = str(self.sender.localtid)
json_PackageInfo = self.convertor.dictConvertJson(PackageInfo)
logging.debug('Generate PackageInfo: %s.',json_PackageInfo)
self.PackageInfo = PackageInfo.copy()
PackageInfo.clear()
def setUploadMessage(self, KeyValue):
# FIXME:数据获取顺序问题
pass
def UpdateMsg(self, messageType, json_message, uuid = ''):
# para: messageType(消息类型): "UpdateInfos"、 "InstallInfos"、 "RemoveInfo"
# para: dict_message(数据内容): 必须包含 "packageName"、"source"", 采集器会进行检测
dict_message = self.convertor.JsonConvertDict(json_message)
if messageType == "":
messageType = "SystemUpdate"
if type(dict_message) != type(dict) and "appname" not in dict_message.keys():
raise AttributeError("'%s' object has no attribute '%s'" % ("dict message", "appname"))
# 生成UploadMessage与PackageInfo
try:
self.GenPackageInfo(messageType, "kylin-system-updater")
self.GenUploadMessage(dict_message, local_uuid = uuid)
except Exception as e:
logging.error(str(e))
# sha256
json_UploadMessage = self.convertor.dictConvertJson(self.UploadMessage)
json_PackageInfo = self.convertor.dictConvertJson(self.PackageInfo)
shaValue = self.convertor.Sha256Value(json_UploadMessage)
encodeMsg = self.convertor.EncodeRSAtoBase64(shaValue)
# dbus发送
try:
self.sender.MsgSendToServer(json_UploadMessage, json_PackageInfo, encodeMsg)
except Exception as e:
logging.error(e)
def Generate_Msg(self, upgrade_list, mode):
try:
self.upgrade_list = upgrade_list
self.upgrade_mode = mode
self.uuid = str(uuid.uuid1())
self.UpdateInfos.update({"upgradeMode":self.mode_map.get(self.upgrade_mode, "default-mode")})
except DBusException as e:
logging.error(e)
def Upgrade_Process_Msg(self, action, dict_msg = {}):
if self.updateManager.configs_uncover.getWithDefault("SystemStatus", "upload_upgrade_log", False) == True:
tmp_dict = {}
tmp_dict.update(dict_msg)
try:
self.UpdateInfos.update({"step":self.action_map.get(action, "")})
if self.upgrade_mode == self.MODE_INSTALL_SYSTEM:
self.UpdateInfos.update({"appname":"Upgrade System"})
tmp_dict.update(self.UpdateInfos)
json_file = json.dumps(tmp_dict.copy())
self.UpdateMsg(self.messageType_map.get(action, ""), json_file, self.uuid)
else:
if action == self.ACTION_INSTALL_DEB:
tmp_dict.update({"step":self.action_map.get(action, "")})
json_file = json.dumps(tmp_dict.copy())
self.UpdateMsg(self.messageType_map.get(action, ""), json_file, self.uuid)
else:
tmp_dict.update(self.UpdateInfos)
json_file = json.dumps(tmp_dict.copy())
self.UpdateMsg(self.messageType_map.get(action, ""), json_file, self.uuid)
except Exception as e:
logging.error(e)
tmp_dict.clear()
def make_background_version(self,pkg):
if pkg.is_installed == True:
self.background_version.update({pkg.name:pkg.installed.source_version})
else:
self.background_version.update({pkg.name:"Unknown"})
self.background_list.append(pkg.name)
def Msg_Clean(self):
self.UploadMessage = {}
self.PackageInfo = {}
self.UpdateInfos = {}
class FormatConvert():
def __init__(self, DataCollector):
#秘钥
self.publickey = UniqueKey()
self.collector = DataCollector
def dictConvertJson(self, dict_msg):
#字典转换为json格式字符串
json_file = ''
try:
json_file = json.dumps(dict_msg)
except JSONDecodeError as e:
logging.error(str(e))
return json_file
def JsonConvertDict(self, json_file):
# json格式字符串转换为字典
dict_file = {}
try:
dict_file = json.loads(json_file)
except JSONDecodeError as e:
logging.error(str(e))
return dict_file
def Sha256Value(self, json_file):
# 计算sha256值
hsobj = hashlib.sha256()
try:
hsobj.update(json_file.encode("utf-8"))
except ValueError as e:
logging.error("SHA256 value error: %s.",str(e))
except Exception as e:
logging.error(str(e))
return hsobj.hexdigest()
def EncodeRSAtoBase64(self, value):
# 将value进行RSA加密并base64转码
try:
# 计算hex值
value_hex = a2b_hex(value)
# 加载公钥,填充格式OAEP
uniqueKey = self.publickey.keyvalue.encode('utf-8')
uniqueKeyorig = base64.b64decode(uniqueKey) # 公钥文件
rsa_pubkey = RSA.importKey(uniqueKeyorig) # RSA公钥
oaep_pub = PKCS1_OAEP.new(rsa_pubkey) # OAEP填充
# 加密数据
encodemsg = oaep_pub.encrypt(value_hex)
# 加密数据Base64转码
enMsg = base64.b64encode(encodemsg)
except ValueError:
logging.error("Value error: %s.", value)
except TypeError:
logging.error("RSA key has no private half.")
return enMsg
class MessageSend():
ERR_PARA_FROMAT = 1
ERR_NO_LOACLTID = 2
ERR_ABNORMAL_SHA = 3
ERR_UPLOADMSG_SHA = 4
ERR_UPLOADMSG_CTS = 5
def __init__(self, DataCollector=None) -> None:
# self.convertor = FormatConvert()
if DataCollector == None:
self.collector = UpdateMsgCollector()
else:
self.collector = DataCollector
def MsgSendToServer(self, UploadMessage, PackageInfo, encodeMsg):
daqbus = dbus.SystemBus()
try:
daqobj = daqbus.get_object('com.kylin.daq', '/com/kylin/daq')
daqinterface = dbus.Interface(daqobj, dbus_interface='com.kylin.daq.interface')
except DBusException as e:
logging.error("kylin-daq service error: "+str(e))
return
try:
retval,retid = daqinterface.UploadMessage(PackageInfo, UploadMessage, encodeMsg)
except AttributeError:
logging.error("Call UploadMessage: Attribute Error.")
self.Send_finally(retval, retid, PackageInfo, UploadMessage, encodeMsg)
def Send_finally(self, retval, retid, json_PackageInfo, json_UploadMessage, encodeMsg):
# 根据发送结果进行处理
result = ''
PackageInfo = self.collector.convertor.JsonConvertDict(json_PackageInfo)
if retval != 0:
if retval == self.ERR_PARA_FROMAT:
result = "Parameter format error"
logging.debug("Sent Status: false - packageName: %s : result: %s.", PackageInfo['packageName'], result)
elif retval == self.ERR_NO_LOACLTID:
result = "The tid value in packageInfo is abnormal, but the message is saved successfully"
logging.debug("Sent Status: false - packageName: %s : result: %s.", PackageInfo['packageName'], result)
# 将返回的tid保存到本地
key = PackageInfo['packageName']+'_'+PackageInfo['messageType']
self.SaveTid(key, retid)
elif retval == self.ERR_ABNORMAL_SHA:
result = "Abnormal UploadedMessage Sha256"
logging.debug("Sent Status: false - packageName: %s : result: %s.", PackageInfo['packageName'], result)
elif retval == self.ERR_UPLOADMSG_SHA:
result = "Description The UploadedMessageSha256 was decrypted incorrectly"
logging.debug("Sent Status: false - packageName: %s : result: %s.", PackageInfo['packageName'], result)
elif retval == self.ERR_UPLOADMSG_CTS:
result = "The createTimeStamp field of UploadedMessage is abnormal"
logging.debug("Sent Status: false - packageName: %s : result: %s.", PackageInfo['packageName'], result)
elif retval == self.ERR_UPLOADMSG_CTS:
result = "Invalid key included in \"uploadedMessage\" or \"packageInfo\": <@timestamp>,<_id>,<_index>,<_type>,<createTime>,<highlight>,<sn>,<sort>, check upload field"
logging.debug("Sent Status: false - packageName: %s : result: %s.", PackageInfo['packageName'], result)
else:
logging.debug("Sent Status: false - packageName: %s : retval: %s.", PackageInfo['packageName'], retval)
# 上传失败写入本地json
if retval != self.ERR_NO_LOACLTID or retval == self.ERR_NO_LOACLTID:
self.WriteToJson(PackageInfo['messageType'], json_PackageInfo, json_UploadMessage, encodeMsg)
elif retval == 0:
result = "Send to server success"
logging.debug("Sent Status: True - packageName: %s : result: %s.", PackageInfo['packageName'], result)
def GetLocalTid(self, key):
# 试图获取本地tid
try:
# 存放至数据库
tid = self.collector.updateManager.sqlite3_server.select_from_tid("tid",key)
if tid == "None" or tid == None:
self.localtid = ""
else:
self.localtid = tid
except Exception as e:
logging.error(str(e))
def SaveTid(self, key, localtid):
if len(localtid) == 0:
return
_localtid = str(localtid)
try:
# 写入数据库
self.collector.updateManager.sqlite3_server.insert_into_tid(key, _localtid)
except Exception as e:
logging.error(str(e))
def WriteToJson(self, messageType, json_PackageInfo, json_UploadMessage, encodeMsg):
#发送失败时写入本地json中定时发送
Msg = {}
Msg["PackageInfo"] = json_PackageInfo
Msg["UploadMessage"] = json_UploadMessage
Msg["encodeMsg"] = str(encodeMsg)
json_file = self.collector.convertor.dictConvertJson(Msg)
# 保存信息
try:
if not os.path.exists(MSGSNDDIR):
os.mkdir(MSGSNDDIR)
# 根据messageType保存信息
with open(MSGSNDDIR+messageType+".json","a") as f:
f.write(json_file)
f.write("\n")
except Exception as e:
logging.error(str(e))
def _TimedTransmission(self, file_path = MSGSNDDIR):
classify_list = [name for name in os.listdir(file_path) if name.endswith(".json")]
for f in classify_list:
# 循环发送每一个文件
self._ReadFromFile(os.path.join(file_path, f))
def _ReadFromFile(self, json_path):
new_lines = []
# 从本地文件读取
if not os.path.exists(json_path):
return
with open(json_path, "r+") as f:
lines = f.readlines()
# file is empty and path is exit -> remove file
if len(lines) == 0 and os.path.exists(json_path):
os.remove(json_path)
return
#send installinfo or updateinfo
for line in lines:
(retval,retid) = self._file_send_server(line)
if retval != 0: # success
new_lines.append(line)
if os.path.exists(json_path):
os.remove(json_path)
if len(new_lines) != 0:
with open(json_path, "w+") as f:
for line in lines:
f.write(line)
def _file_send_server(self, json):
UploadMessage = {}
PackageInfo = {}
encodeMsg = ''
dict_msg = self.collector.convertor.JsonConvertDict(json)
if 'UploadMessage' in dict_msg.keys():
UploadMessage = dict_msg['UploadMessage']
UploadMessage = self.collector.convertor.dictConvertJson(UploadMessage)
if 'PackageInfo' in dict_msg.keys():
PackageInfo = dict_msg['PackageInfo']
PackageInfo = self.collector.convertor.dictConvertJson(PackageInfo)
if 'encodeMsg' in dict_msg.keys():
encodeMsg = str(dict_msg['encodeMsg'])
if len(UploadMessage) == 0 or len(PackageInfo) == 0 or encodeMsg == '':
logging.error("Msg error")
return 6, ''
daqbus = dbus.SystemBus()
try:
daqobj = daqbus.get_object('com.kylin.daq', '/com/kylin/daq')
daqinterface = dbus.Interface(daqobj, dbus_interface='com.kylin.daq.interface')
except DBusException as e:
logging.error(str(e))
try:
retval,retid = daqinterface.UploadMessage(PackageInfo, UploadMessage, encodeMsg)
except AttributeError:
logging.error("Call UploadMessage: Attribute Error.")
return (retval,retid)
class UniqueKey():
keyvalue = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FR\
OEFNSUlCQ2dLQ0FRRUFzdW1NTFJEdlFNb0tEQkRJODRqSgpqc1A0Mk55V0pWVEZob2Jra3ZiT05j\
dExYTXVzRmo2TzJUblZYU3Z6VlVLSjRqZkpwT2l2WEphOVB5Z2wzYTRnClBzSU40enNCMEdOY0tr\
R3VsS2RrV2x6S3lWQ2xlTzhiQnN6SjkwbTc3cWF6YWg3a1A0TUl0WTVFczBpSkpiR0oKN1MxcERj\
MlJkNnVFQWJLaXJyRTFlNzlFTEd4am5VN2V5NWkyRDE2WWJoZEQwZ2lNa2RHR3piQXBKTWZWRVJR\
TQo1NXorMFVqdS8zSFJhNFY3b3p2TGRPRE5HUURaeWNJU0l3VHBLbFR3RjBxazdCNjVhTUlJenQ1\
dnhOK1lxYU1GClppZFRLNzcxNjdqNEExZ3F3MG45bjlybWVXUGRWZ3dudnRtVXp4Q1krNk05SXpK\
TDI3eWpRUTV1WGQ3RVdMT3IKbndJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="
class PHPServer(threading.Thread):
LOG_PATH = "/var/log/kylin-system-updater"
KYLIN_SOFTWARE_PROPERTIES_LOG = "/var/log/kylin-software-properties.log"
PINGBACK_INTERNET_URL = "http://archive1.kylinos.cn:32294/kylin-update-manager-server/main.php?"
PINGBACK_INTERNET_FILE_URL = "http://archive1.kylinos.cn:32294/kylin-update-manager-server/get_file.php?"
PINGBACK_INTRANET_URL = "http://archive.kylinos-intranet.cn/kylin-update-manager-server/main.php?"
PINGBACK_INTRANET_FILE_URL = "http://archive.kylinos-intranet.cn/kylin-update-manager-server/get_file.php?"
SYSTEM_VERSION_PATH = "/etc/kylin-version/kylin-system-version.conf"
def get_values(self, _appname="", _appversion="", _state='', _errorcode='', _errorstring=""):
self.appname = _appname
self.appversion = _appversion
self.status = _state
self.errorcode = _errorcode
self.errorstring = _errorstring
def run(self):
# 获取本机ip
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80))
host_ip = s.getsockname()[0]
except:
host_ip = 'Ip failed to get'
# 获取系统版本
with open('/etc/lsb-release', 'r') as f:
for line in f.readlines():
if line.strip().startswith('DISTRIB_DESCRIPTION='):
versions = line.strip().split('=')
if "V10" in line and "SP1" in versions[1]:
version = "V10SP1"
else:
version = "V10Pro"
break
# 获取软件版本
output = os.popen('dpkg -l|grep kylin-system-updater').readlines()
if output:
soft_version = output[0].strip().split()[2]
# 获取时间
nowtime = time.strftime('%Y-%m-%d-%H:%M:%S', time.localtime(time.time()))
# 获取Mac
mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
host_mac = ":".join([mac[e:e + 2] for e in range(0, 11, 2)])
# 获取序列号
if os.path.exists("/etc/.kyinfo"):
settings = QSettings("/etc/.kyinfo", QSettings.IniFormat)
settings.beginGroup("servicekey")
key = str(settings.value("key")).strip()
settings.endGroup()
else:
key = "0"
try:
# 用于收集源管理器的更新日志
if self.status != "success":
# nowtime = datetime.utcnow( ).strftime ( '%Y-%m-%d %H:%M:%S.%f' )[:-3]
nowtime = get_east_8_time()
log_dir = os.path.join(self.LOG_PATH, host_mac + "_" + nowtime)
log_file_gzip = log_dir + ".tar.gz"
os.makedirs(log_dir, exist_ok=True)
#get updater log
updater_path = os.path.join(log_dir,"kylin-system-updater")
os.makedirs(updater_path, exist_ok=True)
#get updater log
if os.path.exists("/var/log/kylin-system-updater/kylin-system-updater.log.1"):
shutil.copy("/var/log/kylin-system-updater/kylin-system-updater.log.1", log_dir)
if os.path.exists("/var/log/kylin-system-updater/kylin-system-updater.log.1.1.gz"):
shutil.copy("/var/log/kylin-system-updater/kylin-system-updater.log.1.1.gz", log_dir)
#get apt log
if os.path.exists("/var/log/apt/history.log"):
shutil.copy("/var/log/apt/history.log", log_dir)
if os.path.exists("/var/log/apt/term.log"):
shutil.copy("/var/log/apt/term.log", log_dir)
#get version file
if os.path.exists(self.SYSTEM_VERSION_PATH):
shutil.copy(self.SYSTEM_VERSION_PATH, log_dir)
gZipFile(log_dir, log_file_gzip)
header = {'Content-Type': "multipart/form-data", "Accept-Encoding": "gzip"}
try:
with open(log_file_gzip, "rb") as f:
requests.post(self.PINGBACK_INTRANET_FILE_URL + "filename=" + os.path.basename(log_file_gzip),
data=f.read(), headers=header)
except:
with open(log_file_gzip, "rb") as f:
requests.post(self.PINGBACK_INTERNET_FILE_URL + "filename=" + os.path.basename(log_file_gzip),
data=f.read(), headers=header)
shutil.rmtree(log_dir)
os.remove(log_file_gzip)
else:
log_file_gzip = ""
kmg_tmp = {'ip': host_ip, 'version': version, 'soft_version': soft_version, 'datetime': nowtime,
'host_mac': host_mac, 'appname': self.appname, 'appversion': self.appversion, 'serial_number': key,
'state': self.status, 'filename': log_file_gzip, 'errorcode': self.errorcode, 'errorstring': self.errorstring}
kmg = parse.urlencode(kmg_tmp)
logging.debug("PHPServer UpdateInfos: %s .", kmg_tmp)
# 优先使用内网服务器,再使用外网
try:
url = self.PINGBACK_INTRANET_URL + kmg
req = request.urlopen(url=url, timeout=3)
logging.info("The Intranet log server is successfully accessed, pkgname:%s .",self.appname)
except:
url = self.PINGBACK_INTERNET_URL + kmg
req = request.urlopen(url=url, timeout=3)
logging.info("The external log server is successfully accessed, pkgname:%s .",self.appname)
except Exception as e:
logging.error("Failed to access the external log server: %s, pkgname:%s .", e, self.appname)
if os.path.isfile(log_file_gzip):
os.remove(log_file_gzip)
def PHPSeverSend(_appname="", _appversion="", _statue="", _errorcode="", _errorstring=""):
send_thread = PHPServer()
send_thread.get_values(_appname=_appname, _appversion=_appversion, _state=_statue, _errorcode=_errorcode, _errorstring=_errorstring)
send_thread.start()
def gZipFile(src, dst):
with tarfile.open(dst, "w:gz") as tar:
tar.add(src, arcname=os.path.basename(src))
def get_east_8_time():
import time
# UTC时间
utc_time = datetime.utcnow()
# 转时间字符串
utc_time = utc_time.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
time_suffix = utc_time.split(".")[1]
# 字符串转时间元祖
utc_time = time.strptime(utc_time, "%Y-%m-%d %H:%M:%S.%f")
# 时间元祖转时间戳
utc_time = time.mktime(utc_time)
# 生成东八区时间时间戳
now_time = utc_time + 8*60*60
# 时间戳转时间元祖
now_time = time.localtime(now_time)
# 时间元祖转字符串
now_time = time.strftime("%Y-%m-%d %H:%M:%S",now_time)
now_time = now_time + "." +time_suffix
return now_time
# return 0
if __name__ == "__main__":
# 执行定时发送
ms = MessageSend()
ms._ReadFromFile("/var/lib/kylin-system-updater/sendinfos/testMsg.json")

View File

@ -0,0 +1,400 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os
import logging
import sqlite3
from operator import itemgetter
from gettext import gettext as _
from optparse import OptionParser
DB_UPDATER = "/var/cache/kylin-update-manager/kylin-update-manager.db"
DB_UPGRADE = "/var/cache/kylin-system-updater/kylin-system-updater.db"
VER_DB = "/usr/share/kylin-system-updater/kylin-system-updater.db"
def dateMigration(options=None, old_db=None, old_db_cursor=None, new_db=None, new_db_cursor=None):
print(_("Loading Sqlite3Server..."))
if options==None:
old_path = DB_UPDATER
new_path = DB_UPGRADE
try:
if old_db==None and old_db_cursor==None:
old_db = sqlite3.connect(old_path, check_same_thread=False)
old_db_cursor = old_db.cursor()
if new_db==None and new_db_cursor==None:
new_db = sqlite3.connect(new_path, check_same_thread=False)
new_db_cursor = new_db.cursor()
except Exception as e:
print(e)
sql_commnd = ""
old_cfg_dict = {}
new_cfg_dict = {}
# step 1: 更新旧配置数据
try:
print("更新旧配置数据")
sql_commnd = "SELECT * FROM display where id=1"
old_db_cursor.execute(sql_commnd)
old_cfg = old_db_cursor.fetchone()
for od in old_db_cursor.description:
old_cfg_dict.update({str(od[0]):old_cfg[old_db_cursor.description.index(od)]})
new_db_cursor.execute(sql_commnd)
new_cfg = new_db_cursor.fetchone()
for od in new_db_cursor.description:
new_cfg_dict.update({str(od[0]):new_cfg[new_db_cursor.description.index(od)]})
if "download_limit" in new_cfg_dict.keys() and "download_limit_value" in new_cfg_dict.keys():
if new_cfg_dict['download_limit'] != None or new_cfg_dict['download_limit_value'] != None:
print("目标数据库有更新的配置项")
else:
sql_commnd = "UPDATE display set check_time='"+old_cfg_dict['check_time']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
sql_commnd = "UPDATE display set update_time='"+old_cfg_dict['update_time']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
sql_commnd = "UPDATE display set auto_check='"+old_cfg_dict['auto_check']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
sql_commnd = "UPDATE display set system_version='"+old_cfg_dict['system_version']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
if old_cfg_dict['auto_backup'] != None:
sql_commnd = "UPDATE display set auto_backup='"+old_cfg_dict['auto_backup']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
if 'download_limit' in old_cfg_dict.keys() and old_cfg_dict['download_limit'] != None:
sql_commnd = "UPDATE display set download_limit='"+old_cfg_dict['download_limit']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
if 'download_limit_value' in old_cfg_dict.keys() and old_cfg_dict['download_limit_value'] != None:
sql_commnd = "UPDATE display set download_limit_value='"+old_cfg_dict['download_limit_value']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
except Exception as e:
print(e)
print("更新配置文件错误")
return
# step 2: 更新installed
try:
print("更新installed")
update_record_dict = {}
tmp_update_record_dict = []
sql_commnd = "SELECT * FROM installed"
old_db_cursor.execute(sql_commnd)
update_record = old_db_cursor.fetchall()
sql_commnd = "SELECT * FROM updateinfos"
new_db_cursor.execute(sql_commnd)
new_update_record = new_db_cursor.fetchall()
for ur in update_record:
id,appname,version,time,description,icon,statue,keyword,errorcode = ur
if errorcode in range(200):
errorcode = 'null'
update_record_dict.clear()
update_record_dict.update({"appname":appname})
update_record_dict.update({"version":version})
update_record_dict.update({"time":time})
update_record_dict.update({"description":description})
update_record_dict.update({"icon":icon})
update_record_dict.update({"statue":statue})
update_record_dict.update({"keyword":'1'})
update_record_dict.update({"errorcode":errorcode})
tmp_update_record_dict.append(update_record_dict.copy())
for ur in new_update_record:
id,appname,version,description,date,status,keyword,errorcode = ur
if errorcode in range(200):
errorcode = 'null'
update_record_dict.clear()
update_record_dict.update({"appname":appname})
update_record_dict.update({"version":version})
update_record_dict.update({"time":date})
update_record_dict.update({"description":description})
update_record_dict.update({"icon":None})
update_record_dict.update({"statue":status})
update_record_dict.update({"keyword":'1'})
update_record_dict.update({"errorcode":errorcode})
tmp_update_record_dict.append(update_record_dict.copy())
# 按时间排序
tmp_update_record_dict = sorted(tmp_update_record_dict, key=itemgetter('time'))
print("更新installed success")
except Exception as e:
print(e)
print("更新安装记录错误")
return
try:
# 删除 tmp
# DeleteTable(options.new_path+':'+'tmp')
# 创建表
sql_commnd = "create table IF NOT EXISTS tmp('id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,\
'appname' TEXT,\
'version' TEXT,\
'description' TEXT,\
'date' TEXT,\
'status' TEXT,\
'keyword' TEXT,\
'errorcode' TEXT) "
new_db_cursor.execute(sql_commnd)
# 更新数据
for urd in tmp_update_record_dict:
new_db_cursor.execute(
"insert into tmp (appname, version, description, date, status, keyword, errorcode) values(?,"
"?,?,?,?,?,?)",
(urd['appname'], urd['version'], urd['description'], urd['time'], urd['statue'], urd['keyword'], urd['errorcode']))
new_db.commit()
# 删除updateinfos
sql_commnd = "drop table updateinfos"
new_db_cursor.execute(sql_commnd)
new_db.commit()
# 修改表名
sql_commnd = "alter table tmp rename to updateinfos"
new_db_cursor.execute(sql_commnd)
new_db.commit()
except Exception as e:
print(e)
print("安装记录迁移错误")
return
print("数据迁移成功.")
def CleanTable(db_table):
db_path, table_name = str(db_table).split(":")
if not os.path.isfile(db_path):
print("db path error.")
exit(-1)
print(_("Loading Sqlite3Server..."))
try:
db = sqlite3.connect(db_path, check_same_thread=False)
db_cursor = db.cursor()
sql_commnd = 'delete from '+table_name
db_cursor.execute(sql_commnd)
db.commit()
print("clean %s success."%table_name)
except Exception as e:
print(e)
print("clean %s error."%table_name)
def DeleteTable(db_table):
db_path, table_name = str(db_table).split(":")
if not os.path.isfile(db_path):
print("db path error.")
exit(-1)
print(_("Loading Sqlite3Server..."))
try:
db = sqlite3.connect(db_path, check_same_thread=False)
db_cursor = db.cursor()
sql_commnd = 'drop table '+table_name
db_cursor.execute(sql_commnd)
db.commit()
print("delete %s success."%table_name)
except Exception as e:
print("delete %s error: %s"%(table_name,e))
def _has_first_migration(new_db, new_db_cursor):
try:
sql_commnd = "select * from sqlite_master where type='table' and name='display';"
new_db_cursor.execute(sql_commnd)
retval = new_db_cursor.fetchone()
for rv in retval:
if "firstmigration" in str(rv):
return True
except Exception as e:
print(e)
return False
def _is_first_migration(new_db, new_db_cursor):
try:
sql_commnd = "select firstmigration from display;"
new_db_cursor.execute(sql_commnd)
retval = new_db_cursor.fetchone()
if "yes" in retval:
return True
else :
return False
except Exception as e:
print(e)
return False
def _is_display_exist_fields(field, db, db_cursor):
try:
sql_commnd = "select * from sqlite_master where type='table' and name='display';"
db_cursor.execute(sql_commnd)
retval = db_cursor.fetchone()
for rv in retval:
if field in str(rv):
return True
except Exception as e:
print(e)
return False
return False
def _is_updateinfos_exist_fields(field, db, db_cursor):
try:
sql_commnd = "select * from sqlite_master where type='table' and name='updateinfos';"
db_cursor.execute(sql_commnd)
retval = db_cursor.fetchone()
for rv in retval:
if field in str(rv):
return True
except Exception as e:
print(e)
return False
return False
def _add_display_fields(fields_default, default_table = True):
try:
if "=" not in fields_default:
print("format: field=value")
return False
field, value = fields_default.split('=')
# print(_("Loading Sqlite3Server..."))
db = sqlite3.connect(DB_UPGRADE, check_same_thread=False)
db_cursor = db.cursor()
if default_table:
if _is_display_exist_fields(field, db, db_cursor):
print("field %s is exist."%field)
return False
# 字段不存在,新增字段
sql_commnd = "alter table display add column "+field+" TEXT;"
db_cursor.execute(sql_commnd)
sql_commnd = "UPDATE display SET "+field+"='"+value+"'"
db_cursor.execute(sql_commnd)
db.commit()
else:
if _is_updateinfos_exist_fields(field, db, db_cursor):
print("field %s is exist."%field)
return False
# 字段不存在,新增字段
sql_commnd = "alter table updateinfos add column "+field+" TEXT;"
db_cursor.execute(sql_commnd)
db.commit()
except Exception as e:
print(e)
return False
print("Succeeded in adding field: '%s' "%field)
return True
def _add_new_table(table):
table = str(table).strip()
if "=" not in table:
return False
opt, fields = table.split('=')
try:
if fields == 'tid_search':
db = sqlite3.connect(DB_UPGRADE, check_same_thread=False)
db_cursor = db.cursor()
sql_commnd = "create table IF NOT EXISTS tid_search('id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,\
'key' TEXT,\
'tid' TEXT) "
db_cursor.execute(sql_commnd)
db.commit()
db.close()
except Exception as e:
print(e)
return False
def CopyData():
try:
# 判断新字段是否存在
if (os.path.exists(VER_DB) and os.path.exists(DB_UPGRADE)):
print(_("Loading Sqlite3Server..."))
try:
new_db = sqlite3.connect(DB_UPGRADE, check_same_thread=False)
new_db_cursor = new_db.cursor()
ver_db = sqlite3.connect(VER_DB, check_same_thread=False)
ver_db_cursor = ver_db.cursor()
except Exception as e:
print(e)
if (_has_first_migration(new_db, new_db_cursor)): # 存在 firstmigration
if (_is_first_migration(new_db, new_db_cursor)):
# 数据迁移
dateMigration(new_db=new_db, new_db_cursor=new_db_cursor)
sql_commnd = "UPDATE display SET firstmigration='no';"
new_db_cursor.execute(sql_commnd)
new_db.commit()
else:
print("No data migration is required ...")
else:# 不存在firstmigration
# 新增 firstmigration 字段
sql_commnd = "alter table display add column firstmigration text;"
new_db_cursor.execute(sql_commnd)
sql_commnd = "UPDATE display SET firstmigration='yes';"
new_db_cursor.execute(sql_commnd)
#数据迁移
dateMigration(new_db=new_db, new_db_cursor=new_db_cursor)
sql_commnd = "UPDATE display SET firstmigration='no';"
new_db_cursor.execute(sql_commnd)
new_db.commit()
else :
print("Not found kylin-system-updater.db, ensure that \'kylin-system-updater\' is successfully installed ... ")
exit(-1)
except Exception as e:
print(e)
if __name__ == "__main__":
# Begin parsing of options
parser = OptionParser()
parser.add_option ("-d", "--debug", action="store_true", default=False,
help=_("Show debug messages"))
parser.add_option ("-o", "--old-path", dest="old_path",
help=_("Enter the old database address"))
parser.add_option ("-n", "--new-path", dest="new_path",
help=_("Enter the new database address"))
parser.add_option ("-c", "--clean-table", dest="clean_table",
help=_("Clear the table"))
parser.add_option ("-r", "--delete-table", dest="delete_table",
help=_("Delete the table"))
parser.add_option ("-m", "--data-migration", default=False, action="store_true",
dest="data_migration", help=_("data migration"))
parser.add_option ("-f", "--add-display-fields",
dest="add_display_fields", help=_("add display fields"))
parser.add_option ("-u", "--add-updateinfos-fields",
dest="add_updateinfos_fields", help=_("add updateinfos fields"))
parser.add_option ("-t", "--add-new-table",
dest="add_new_table", help=_("add new table"))
(options, args) = parser.parse_args()
if options.clean_table:
if ":" not in options.clean_table:
print("format error: <database:table>")
else:
CleanTable(str(options.clean_table))
if options.delete_table:
if ":" not in options.delete_table:
print("format error: <database:table>")
else:
DeleteTable(str(options.delete_table))
if options.add_display_fields:
_add_display_fields(str(options.add_display_fields))
if options.add_updateinfos_fields:
_add_display_fields(str(options.add_updateinfos_fields), default_table = False)
if options.add_new_table:
_add_new_table(str(options.add_new_table))
if options.data_migration:
CopyData()
exit(0)
if options.old_path or options.new_path:
# 检查文件
if not options.old_path or not options.new_path:
print("parameter error")
exit(-1)
if not os.path.isfile(options.old_path):
print("The source database file does not exist")
exit(-1)
if not os.path.isfile(options.new_path):
print("The destination database file does not exist")
exit(-1)
dateMigration(options)

View File

@ -0,0 +1,683 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from math import log10
import os
import re
import json
import yaml
import shutil
import sqlite3
import logging
import datetime
from gettext import gettext as _
from sys import exec_prefix
from SystemUpdater.Core.DataAcquisition import PHPSeverSend
from SystemUpdater.Core.UpdaterConfigParser import UpgradeConfig
from SystemUpdater.Core.utils import get_config_patch
import apt_pkg
from ..backend import InstallBackend
DB_FILE = os.path.join("/var/cache/kylin-system-updater/kylin-system-updater.db")
# UMDB_FILE = os.path.join("/var/cache/kylin-system-updater/kylin-system-updater.db")
INSTALLED_LIST = [{"item": "errorcode", "type": "int", "default": "0"}]
DISPALY_LIST = []
class Sqlite3Server(object):
def __init__(self, updateManager):
self.connect = None
self.window_main = updateManager
self.config_path = get_config_patch()
self.init_sqlit()
# uncoverable配置文件
self.ucconfigs = UpgradeConfig(datadir = "/etc/kylin-version", name = "kylin-system-version.conf")
self._system_version_config()
# 初始化连接数据库,修改为使用时连接
def init_sqlit(self):
try:
logging.info(_("Initialize database files ..."))
if not os.path.isfile(DB_FILE):
if not os.path.isdir(os.path.dirname(DB_FILE)):
os.makedirs(os.path.dirname(DB_FILE))
shutil.copy("/usr/share/kylin-system-updater/kylin-system-updater.db", os.path.dirname(DB_FILE))
except Exception as e:
logging.error("Failed to initialize database files: %s", str(e))
#connect连接数据库
def connect_database(self):
try:
logging.debug("Connect database ...")
self.connect = sqlite3.connect(DB_FILE, check_same_thread=False)
self.cursor = self.connect.cursor()
except Exception as e:
logging.error("Failed to connect database: %s", str(e))
#disconnect连接数据库
def disconnect_database(self):
try:
logging.debug("Disconnect database ...")
if self.connect != None:
self.connect.close()
if self.connect != None:
del self.cursor
except Exception as e:
logging.error("Failed to disconnect database: %s", str(e))
# 数据库表格中动态增加新的字段用于扩展
def insert_new_field(self):
if len(INSTALLED_LIST) == 0 and len(DISPALY_LIST) == 0:
return
self.cursor.execute("select sql from sqlite_master where name='installed'")
installed_sql = self.cursor.fetchone()[0]
pattern = re.compile(r'\"\w+\"')
installed_sql_list = pattern.findall(installed_sql)
for value in INSTALLED_LIST:
for field in installed_sql_list:
if value["item"] == str(field).strip("\""):
break
elif field == installed_sql_list[len(installed_sql_list) - 1]:
try:
if value["default"] != "":
sql = 'alter table installed add column "' + value["item"] + '" ' + value["type"] \
+ ' default ' + str(value["default"])
else:
sql = 'alter table installed add column "' + value["item"] + '" ' + value["type"]
self.cursor.execute(sql)
logging.info(_("installed table insert new field: %s"), value["item"])
except:
logging.error(_("installed table failed to insert a new field:"), value["item"], exc_info=True)
self.cursor.execute("select sql from sqlite_master where name='display'")
display_sql = self.cursor.fetchone()[0]
pattern = re.compile(r'\"\w+\"')
display_sql_list = pattern.findall(display_sql)
for value in DISPALY_LIST:
for field in display_sql_list:
if value["item"] == str(field).strip("\""):
break
elif field == display_sql_list[len(display_sql_list) - 1]:
try:
if value["default"] != "":
sql = 'alter table display add column "' + value["item"] + '" ' + value["type"] \
+ ' default ' + str(value["default"])
else:
sql = 'alter table installed add column "' + value["item"] + '" ' + value["type"]
self.cursor.execute(sql)
logging.info(_("display table insert new field %s"), value["item"])
except:
logging.error(_("display table failed to insert a new field %s"), value["item"], exc_info=True)
# 写入数据到installed表中
def insert_into_installed(self, *args, **kwargs):
self.connect_database()
self.cursor.execute(
"insert into installed (appname, version, time, description, icon, statue, keyword, errorcode) values(?,"
"?,?,?,?,?,?,?)", (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]))
self.connect.commit()
logging.info("Database: Insert (%s=%s) To installed Complete ...", args[0], args[1])
self.disconnect_database()
# 写入数据到display表中
def insert_into_display(self, *args, **kwargs):
self.connect_database()
try:
sql = "update display set " + args[0] + "='" + args[1] + "' where id = 1"
self.cursor.execute(sql)
self.connect.commit()
except Exception as e:
logging.error("Insert error: %s.", str(e))
self.disconnect_database()
return False
logging.info("Database: Insert (%s=%s) To display Complete ...", args[0], args[1])
self.disconnect_database()
return True
# 写入数据到tid_search表中
def insert_into_tid(self, *args, **kwargs):
self.connect_database()
self.cursor.execute(
"insert into tid_search (key, tid) values(?,?)",
(args[0], args[1]))
self.connect.commit()
logging.info("Database: Insert (%s=%s) To tid_search Complete ...", args[0], args[1])
self.disconnect_database()
# 搜索tid_search表获取tid值
def select_from_tid(self, *args, **kwargs):
retval = ''
self.connect_database()
try:
sql = "select "+args[0]+" from tid_search where key='"+args[1]+"'"
self.cursor.execute(sql)
rets = self.cursor.fetchall()
if len(rets)!= 0:
if len(rets[0])!=0:
ret_first = rets[0]
retval = str(ret_first[0])
except Exception as e:
logging.error("Insert error: %s.", str(e))
self.disconnect_database()
logging.info("Database: Select tid_search data Complete...")
self.disconnect_database()
return retval
# 读出display表中数据
def select_from_display(self, *args, **kwargs):
self.connect_database()
try:
sql = "select "+args[0]+" from display"
self.cursor.execute(sql)
self.connect.commit()
retval = str(self.cursor.fetchone()[0])
except Exception as e:
logging.error("select error: %s.", str(e))
self.disconnect_database()
return "Error"
logging.info("Database: Search display Complete (%s) ...", args[0])
self.disconnect_database()
return retval
# 写入updateinfos表中
def insert_into_updateinfo(self, *args, **kwargs):
self.connect_database()
try:
self.cursor.execute(
"insert into updateinfos (appname, version, description, date, status, keyword, errorcode, appname_cn, status_cn, changelog) values(?,"
"?,?,?,?,?,?,?,?,?)",
(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]))
self.connect.commit()
except Exception as e:
logging.error("Insert error: %s.", str(e))
self.disconnect_database()
logging.info(_("Database: Insert To updateinfos Complete..."))
self.disconnect_database()
# 接收更新列表与信息,生成数据并插入数据库中
def insert_info(self, mode, pkg_list=[], pkg_group=[], adjust_pkg=[], success = False, error_string = '', error_desc = ''):
errstr = error_string + " " + error_desc
status = " "
status_cn = " "
appname_cn = ""
UpdateInfos = {}
InstallInfos = {}
time = datetime.datetime.now()
timestr = datetime.datetime.strftime(time, "%Y-%m-%d %H:%M:%S")
pkg_list = pkg_list.copy()
pkg_group = pkg_group.copy()
adjust_pkg = adjust_pkg.copy()
# 更新列表空,无更新
if not pkg_list and not pkg_group and mode != InstallBackend.MODE_INSTALL_SYSTEM:
logging.info("There is no update.")
return True
if success:
status = 'success'
status_cn = '成功'
else:
status = 'failed'
status_cn = '失败'
changeLog = ""
try:
# 判断更新方式
if mode == InstallBackend.MODE_INSTALL_PARTIAL: # 部分更新
pkg_adj = ""
# 判断更新包为单包或更新组
if pkg_group:
# 更新组
pkgname = pkg_group.pop(0)
pkgversion,pkgdescription,appname_cn = self.GetGroupmsg(pkgname)
#更新信息update-infos
UpdateInfos.update({"appname":str(pkgname)})
UpdateInfos.update({"source":"Kylin System Updater"})
UpdateInfos.update({"status":status})
UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)})
self.window_main.collector.Upgrade_Process_Msg("finish-update", UpdateInfos.copy())
#安装信息install-infos
InstallInfos.update({"appname":str(pkgname)})
if pkgname in self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'].keys():
InstallInfos.update({"old_version":str(self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'][pkgname])})
else:
InstallInfos.update({"old_version":'UnKnown'})
InstallInfos.update({"new_version":str(pkgversion)})
InstallInfos.update({"status":status})
InstallInfos.update({"errorCode":str(error_string+" "+error_desc)})
self.window_main.collector.Upgrade_Process_Msg("finish-install", InstallInfos.copy())
# 系统升级完成 ..判断版本号
if status == "success" and "kylin-update-desktop-system" in pkgname:
# 更新版本号
if "=" in str(pkgversion):
pkgversion = str(pkgversion).split('=')[-1]
logging.info("Complete system upgrade, refresh system version ...")
self._refresh_system_version(pkgversion)
#移除step-two标记
self._removal_of_marker()
#FIXME: 临时方案 PHP
PHPSeverSend(_appname=pkgname, _appversion=pkgversion, _statue=status, _errorcode="10000100", _errorstring=errstr)
file_path = os.path.join(get_config_patch(), str(pkgname) + ".yaml")
with open(file_path, "r") as stream:
try:
data_yaml = yaml.safe_load(stream)
changeLog = data_yaml['changelog']
except yaml.YAMLError as exc:
logging.error(exc)
elif pkg_list:
changeLog = " "
# 单包更新 # 获取单包数据插入数据库
pkgname = pkg_list.pop(0)
for adj in adjust_pkg:
if pkgname in adj:
# 该部分升级的单包为调整版本,与候选版本不一致
pkg_adj = adj
break
if pkg_adj: # 有调整的情况
try:
pkg = self.window_main.cache[pkg_adj.split("=")[0]]
for ver in pkg.versions:
if ver.version == pkg_adj.split("=")[1]:
pkg_inst_ver = ver
break
pkgname = pkg_adj.split("=")[0]
pkgversion = str(pkg_inst_ver.source_version)
pkgdescription = str(pkg_inst_ver.description)
except Exception as e:
logging.error(_("%s could not be detected in the source because the source was changed or for other reasons."), \
str(pkgname))
logging.error(str(e))
else: # 没有调整的情况
try:
pkg = self.window_main.cache[pkgname]
pkgversion = str(pkg.candidate.version)
pkgdescription = str(pkg.candidate.raw_description)
except Exception as e:
logging.error(str(e))
#更新信息update-infos
UpdateInfos.update({"appname":str(pkgname)})
UpdateInfos.update({"source":"Kylin System Updater"})
UpdateInfos.update({"status":status})
UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)})
self.window_main.collector.Upgrade_Process_Msg("finish-update", UpdateInfos.copy())
#安装信息install-infos
InstallInfos.update({"appname":str(pkgname)})
if pkgname in self.window_main.update_list.upgrade_meta.versoin_pkgs['single_upgrade'].keys():
InstallInfos.update({"old_version":str(self.window_main.update_list.upgrade_meta.versoin_pkgs['single_upgrade'][pkgname])})
else:
InstallInfos.update({"old_version":'UnKnown'})
InstallInfos.update({"new_version":str(pkgversion)})
InstallInfos.update({"status":status})
InstallInfos.update({"errorCode":str(error_string+" "+error_desc)})
self.window_main.collector.Upgrade_Process_Msg("finish-install", InstallInfos.copy())
# 软件商店获取中文名
appname_cn = self.get_cn_appname(str(pkgname))
#FIXME: 临时方案 PHP
PHPSeverSend(_appname=pkgname, _appversion=pkgversion, _statue=status, _errorcode="10000100", _errorstring=errstr)
try:
self.insert_into_updateinfo(pkgname, pkgversion, pkgdescription, timestr, status, "1", errstr, appname_cn, status_cn, changeLog)
# FIXME: 发送插入数据库成功的信号local_upgrade_list
self.window_main.dbusController.UpdateSqlitSingle(pkgname, timestr)
# 数据库文件被删除或者新增字段导致需要重新初始化数据库再写入
except Exception as e:
self.init_sqlit()
self.insert_into_updateinfo(pkgname, pkgversion, pkgdescription, timestr, status, "1", errstr, appname_cn, status_cn, changeLog)
# FIXME: 这里也需要, 发送插入数据库成功的信号
self.window_main.dbusController.UpdateSqlitSingle(pkgname, timestr)
elif mode == InstallBackend.MODE_INSTALL_ALL: # 系统全部升级
# # insert signal deb first
for i in pkg_list:
changeLog = ""
try:
pkg = self.window_main.cache[i]
except Exception as e:
logging.error(_("%s could not be detected in the source because the source was changed or for other reasons."), \
str(i))
continue
if not pkg:
continue
pkgversion = str(pkg.candidate.version)
pkgdescription = str(pkg.candidate.raw_description)
#更新信息update-infos
UpdateInfos.update({"appname":str(pkg.name)})
UpdateInfos.update({"source":"Kylin System Updater"})
UpdateInfos.update({"status":status})
UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)})
self.window_main.collector.Upgrade_Process_Msg("finish-update", UpdateInfos.copy())
#安装信息install-infos
InstallInfos.update({"appname":str(pkg.name)})
if pkg.name in self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'].keys():
InstallInfos.update({"old_version":str(self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'][pkg.name])})
else:
InstallInfos.update({"old_version":'UnKnown'})
InstallInfos.update({"new_version":str(pkgversion)})
InstallInfos.update({"status":status})
InstallInfos.update({"errorCode":str(error_string+" "+error_desc)})
self.window_main.collector.Upgrade_Process_Msg("finish-install", InstallInfos.copy())
try:
# 软件商店获取中文名
appname_cn = self.get_cn_appname(str(i))
self.insert_into_updateinfo(str(i), pkgversion, pkgdescription, timestr, status, "1", errstr, appname_cn, status_cn, changeLog)
self.window_main.dbusController.UpdateSqlitSingle(str(i), timestr)
# 数据库文件被删除或者新增字段导致需要重新初始化数据库再写入
except Exception as e:
self.init_sqlit()
self.insert_into_updateinfo(str(i), pkgversion, pkgdescription, timestr, status, "1", errstr, appname_cn, status_cn, changeLog)
self.window_main.dbusController.UpdateSqlitSingle(str(i), timestr)
#FIXME: 临时方案 PHP
PHPSeverSend(_appname=pkg.name, _appversion=pkgversion, _statue=status, _errorcode="10000100", _errorstring=errstr)
# insert group deb next
for i in pkg_group:
# FIXME: 获取组信息
pkgversion,pkgdescription,appname_cn = self.GetGroupmsg(i)
#更新信息update-infos
UpdateInfos.update({"appname":str(i)})
UpdateInfos.update({"source":"Kylin System Updater"})
UpdateInfos.update({"status":status})
UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)})
self.window_main.collector.Upgrade_Process_Msg("finish-update", UpdateInfos.copy())
#安装信息install-infos
InstallInfos.update({"appname":str(i)})
if i in self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'].keys():
InstallInfos.update({"old_version":str(self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'][i])})
else:
InstallInfos.update({"old_version":'UnKnown'})
InstallInfos.update({"new_version":str(pkgversion)})
InstallInfos.update({"status":status})
InstallInfos.update({"errorCode":str(error_string+" "+error_desc)})
json_file = json.dumps(InstallInfos.copy())
try:
self.window_main.collector.UpdateMsg("InstallInfos", json_file)
except:
pass
#FIXME: 临时方案 PHP
PHPSeverSend(_appname=i, _appversion=pkgversion, _statue=status, _errorcode="10000100", _errorstring=errstr)
file_path = os.path.join(get_config_patch(), str(i) + ".yaml")
with open(file_path, "r") as stream:
try:
data_yaml = yaml.safe_load(stream)
changeLog = data_yaml['changelog']
except yaml.YAMLError as exc:
logging.error(exc)
try:
self.insert_into_updateinfo(str(i), pkgversion, pkgdescription, timestr, status, "1", errstr, appname_cn, status_cn, changeLog)
self.window_main.dbusController.UpdateSqlitSingle(str(i), timestr)
# 数据库文件被删除或者新增字段导致需要重新初始化数据库再写入
except Exception as e:
self.init_sqlit()
self.insert_into_updateinfo(str(i), pkgversion, pkgdescription, timestr, status, "1", errstr, appname_cn, status_cn, changeLog)
self.window_main.dbusController.UpdateSqlitSingle(str(i), timestr)
# 系统升级完成 ..判断版本号
if status == "success" and "kylin-update-desktop-system" in pkg_group:
# 更新版本号
if "=" in str(pkgversion):
pkgversion = str(pkgversion).split('=')[-1]
logging.info("Complete system upgrade, refresh system version ...")
self._refresh_system_version(str(pkgversion))
#移除step-two标记
self._removal_of_marker()
elif mode == InstallBackend.MODE_INSTALL_SYSTEM: # 全盘升级
self.insert_into_updateinfo(_("Upgrade System"), "", "This is a complete system upgrade, equivalent to the implementation of apt dist-upgrade", timestr, status, "1", errstr, str("全盘升级"), status_cn, " ")
self.window_main.dbusController.UpdateSqlitSingle("Upgrade System", timestr)
# 全盘更新完成 ..判断版本号
if status == "success":
# 更新版本号
self._refresh_system_version(pseudo_version=True)
#移除step-two标记
self._removal_of_marker()
else:
logging.warning("Cache is None.")
except Exception as e:
logging.error("record update error: %s.",str(e))
# 获取group信息
def GetGroupmsg(self, appname):
jsonfile = appname+".json"
files = os.listdir(self.config_path) #获取文件夹中所有文件
if jsonfile in files: # 存在
# 读取组JSON文件
with open(self.config_path+jsonfile, "r") as f:
try :
data = json.load(f)
except json.JSONDecodeError as e:
logging.error(str(e))
try:
version = data['version']
if "=" in version:
version = version.split("=")[1].strip()
tmpdescription = data['description']
appname_cn = data['name']['zh_CN']
except Exception as e:
logging.error(str(e))
if "zh_CN" in tmpdescription and "en_US" in tmpdescription:
description = tmpdescription["zh_CN"] + ": " + tmpdescription["en_US"]
return (version,description,appname_cn)
else: # 不存在
return (None, None, None)
def refreshpkglist(self):
pkgs_install = []
pkgs_upgrade = []
pkgs_remove = []
for pkg in self.window_main.cache:
try:
if pkg.marked_install:
pkgs_install.append(pkg.name)
if pkg.marked_upgrade:
pkgs_upgrade.append(pkg.name)
elif pkg.marked_delete:
pkgs_remove.append(pkg.name)
except KeyError:
# pkg missing from fresh_cache can't be modified
pass
return pkgs_install,pkgs_upgrade,pkgs_remove
def _removal_of_marker(self):
try:
marker_path = "/var/cache/kylin-update-manager/ignoreOrDelay"
if os.path.exists(marker_path):
with open(marker_path, 'r+') as f:
line= f.readline()
if "2107" in line or "2203" in line:
f.seek(0)
f.truncate()
except Exception as e:
logging.error("Removing the upgrade success mark error: %s.",str(e))
# #查找数据库
# def find_msg_from_datebase(self, table, field, action = 'check', cid = 0):
# # 查询数据
# try:
# sql = "select "+field+" from "+table
# self.cursor.execute(sql)
# update_count = self.cursor.fetchone()[0]
# logging.info("%d history updates detected.", update_count)
# except Exception as e:
# logging.error("Check update error: %s", str(e))
def _system_version_config(self):
self.connect_database()
try:
sql = "select init_version from display where id=1"
self.cursor.execute(sql)
_is_init_verison = self.cursor.fetchone()[0]
if _is_init_verison == "yes":
update_version, os_version = self.get_default_version()
logging.info("Need to refresh version ...")
self._refresh_system_version(update_version, os_version)
sql = "update display set init_version = 'no'"
self.cursor.execute(sql)
self.connect.commit()
except Exception as e:
logging.error(str(e))
self.disconnect_database()
self.disconnect_database()
def _refresh_system_version(self, update_version='', os_version = '', pseudo_version = False):
try:
if "=" in update_version:
update_version = str(update_version).split('=')[-1]
if "=" in os_version:
os_version = str(os_version).split('=')[-1]
os_version = os_version.strip()
update_version = update_version.strip()
#刷新系统版本号:os_version
if update_version == '':
update_version, os_version = self.get_default_version()
if os_version == '' and os.path.isfile("/etc/os-release"):
with open("/etc/os-release", "r+") as f:
lines = f.readlines()
for line in lines:
if "KYLIN_RELEASE_ID" in line:
os_version = line.split('=')[1]
os_version = os_version.strip()
if not pseudo_version:
if len(os_version) != 0:
self.ucconfigs.setValue("SYSTEM","os_version",str(os_version),True)
if len(update_version) != 0:
self.ucconfigs.setValue("SYSTEM","update_version",str(update_version),True)
else:
current_update_version, current_os_version = self.get_current_version()
if current_os_version != os_version:
os_version+='*'
self.ucconfigs.setValue("SYSTEM","os_version",str(os_version),True)
if current_update_version != update_version:
update_version+='*'
self.ucconfigs.setValue("SYSTEM","update_version",str(update_version),True)
except Exception as e:
logging.error("Refresh system version error: %s.",str(e))
def get_default_version(self):
update_version = ""
os_version = ""
INPUT_CONFIG_PATH = self.config_path + 'kylin-update-desktop-system.json'
if os.path.isfile(INPUT_CONFIG_PATH): # 存在
# 读取JSON文件
with open(INPUT_CONFIG_PATH, "r") as f:
try :
data = json.load(f)
except json.JSONDecodeError as e:
logging.error(str(e))
try:
update_version = data['version']
if "=" in update_version:
update_version = update_version.split('=')[-1].strip()
except Exception as e:
logging.error("get_default_version error: %s .",str(e))
version_path = "/etc/os-release"
if os.path.isfile(version_path):
with open(version_path, "r+") as f:
lines = f.readlines()
for line in lines:
if "KYLIN_RELEASE_ID" in line:
os_version = line.split('=')[1]
os_version = eval(os_version.strip())
if update_version == "" and os_version != "":
update_version = os_version
elif update_version != "" and os_version == "":
os_version = update_version
return str(update_version),str(os_version)
def get_current_version(self):
os_version = ''
update_version = ''
try:
if not os.path.exists("/etc/kylin-version/kylin-system-version.conf"):
logging.warning("System version file doesn't exist.")
return os_version,update_version
os_version = eval(str(self.window_main.sqlite3_server.ucconfigs.get("SYSTEM","os_version")))
update_version = str(self.window_main.sqlite3_server.ucconfigs.get("SYSTEM","update_version"))
except Exception as e:
logging.error(str(e))
return update_version,os_version
logging.info('Current os_version: %s, release_id: %s .', os_version, update_version)
return str(update_version),str(os_version)
def get_cn_appname(self, name):
try:
SC_DB_FILE = "/usr/share/kylin-software-center/data/uksc.db"
if os.path.isfile(SC_DB_FILE):
connect = sqlite3.connect(SC_DB_FILE, check_same_thread=False)
cursor = connect.cursor()
else:
logging.warning("software center database isn't exist .")
return ""
sql = "select display_name_cn from application where display_name='"+name+"'"
cursor.execute(sql)
connect.commit()
retval = cursor.fetchone()
connect.close()
if retval != None and len(retval) != 0:
return str(retval[0])
else:
return ''
except Exception as e:
logging.error(_("Failed to initialize the database: %s"), str(e))
return ''
def insert_upgrade_history(self, args, caller):
caller_list = ['kylin-unattended-upgrade', "d-feet", "root"]
_in_list = False
for cl in caller_list:
if caller in cl:
_in_list = True
if _in_list == False:
logging.warning("Caller \" %s \": Operation without permission...", caller)
return False
# {"appname":GLib.Variant("s", "kylin-system-updater"), "version":GLib.Variant("s", "0.0")}
# "description":GLib.Variant("s", "Update Manager for Kylin"), "date":GLib.Variant("s", "2022-07-27 15:23:51")
# "status":GLib.Variant("s", "failed"), "keyword":GLib.Variant("s", "1")
# "errorcode":GLib.Variant("s", "System upgrade is complete. "), "appname_cn":GLib.Variant("s", "音乐")
upgrade_info = {}
try:
for it in args:
upgrade_info[str(it)] = str(args[str(it)])
logging.info("upgrade_info: %s", upgrade_info)
if "appname" in upgrade_info.keys() and "version" in upgrade_info.keys() \
and "description" in upgrade_info.keys() \
and "date" in upgrade_info.keys() \
and "status" in upgrade_info.keys() \
and "keyword" in upgrade_info.keys() \
and "errorcode" in upgrade_info.keys() \
and "appname_cn" in upgrade_info.keys() \
and "status_cn" in upgrade_info.keys() \
and "changelog" in upgrade_info.keys():
appname = upgrade_info["appname"]
if "kylin-unattended-upgrade" == appname:
upgrade_info["appname"] = self.get_cn_appname(appname)
if upgrade_info["appname"] == "":
upgrade_info["appname"] = _("kylin-unattended-upgrade")
if appname in self.window_main.cache and upgrade_info["description"] == "":
pkg = self.window_main.cache[appname]
if pkg.is_installed:
upgrade_info["description"] = pkg.installed.description
self.insert_into_updateinfo( upgrade_info["appname"], upgrade_info["version"], \
upgrade_info["description"], \
upgrade_info["date"], \
upgrade_info["status"], \
upgrade_info["keyword"], \
upgrade_info["errorcode"], \
upgrade_info["appname_cn"], \
upgrade_info["status_cn"], \
upgrade_info["changelog"] )
else:
logging.warning("Incomplete field.")
return False
except Exception as e:
logging.error(e)
return False
return True
def listtojsonstr(lists):
import json
jsonfile = json.dumps(lists)
return jsonfile

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,124 @@
import os
from gettext import gettext as _
import apt
import logging
import fcntl
import apt_pkg
class LogInstallProgress(apt.progress.base.InstallProgress):
""" Install progress that writes to self.progress_log
(/var/run/unattended-upgrades.progress by default)
"""
def __init__(self,file):
# type: (str) -> None
apt.progress.base.InstallProgress.__init__(self)
self.output_logfd = None # type: int
self.filename=file
self.error_pkg=""
self.errormsg=""
# raise Exception("for test!!!")
def error(self,pkg, errormsg):
logging.error(("Install mode - dpkg, Install error: %s"), errormsg)
self.error_pkg=self.filename
self.errormsg = errormsg
def status_change(self, pkg, percent, status):
# type: (str, float, str) -> None
logging.info(("pkg:%s,percent:%s,status:%s"),pkg,percent,status)
with open(self.progress_log, "w") as f:
f.write(("%s")%percent)
f.write(_("当前进度: %s ,正在安装:%s,当前状态:%s") % (percent, pkg,status))
f.write(_("Progress: %s %% (%s)") % (percent, pkg))
def _fixup_fds(self):
# () -> None
required_fds = [0, 1, 2, # stdin, stdout, stderr
self.writefd,
self.write_stream.fileno(),
self.statusfd,
self.status_stream.fileno()
]
# ensure that our required fds close on exec
for fd in required_fds[3:]:
old_flags = fcntl.fcntl(fd, fcntl.F_GETFD)
fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)
# close all fds
try:
# PEP-446 implemented in Python 3.4 made all descriptors
# CLOEXEC, but we need to be able to pass writefd to dpkg
# when we spawn it
os.set_inheritable(self.writefd, True)
except AttributeError: # if we don't have os.set_inheritable()
pass
proc_fd = "/proc/self/fd"
if os.path.exists(proc_fd):
error_count = 0
for fdname in os.listdir(proc_fd):
try:
fd = int(fdname)
except Exception:
print("ERROR: can not get fd for %s" % fdname)
if fd in required_fds:
continue
try:
os.close(fd)
# print("closed: ", fd)
except OSError as e:
# there will be one fd that can not be closed
# as its the fd from pythons internal diropen()
# so its ok to ignore one close error
error_count += 1
if error_count > 1:
print("ERROR: os.close(%s): %s" % (fd, e))
def _redirect_stdin(self):
# type: () -> None
REDIRECT_INPUT = os.devnull
fd = os.open(REDIRECT_INPUT, os.O_RDWR)
os.dup2(fd, 0)
def _redirect_output(self):
# type: () -> None
# do not create log in dry-run mode, just output to stdout/stderr
if not apt_pkg.config.find_b("Debug::pkgDPkgPM", False):
logfd = self._get_logfile_dpkg_fd()
os.dup2(logfd, 1)
os.dup2(logfd, 2)
def _get_logfile_dpkg_fd(self):
# type: () -> int
logfd = os.open(
"/var/log/kylin-system-updater/kylin-system-updater.log.1", os.O_RDWR | os.O_APPEND | os.O_CREAT, 0o640)
try:
import grp
adm_gid = grp.getgrnam("adm").gr_gid
os.fchown(logfd, 0, adm_gid)
except (KeyError, OSError):
pass
return logfd
def update_interface(self):
# type: () -> None
# call super class first
apt.progress.base.InstallProgress.update_interface(self)
def _log_in_dpkg_log(self, msg):
# type: (str) -> None
logfd = self._get_logfile_dpkg_fd()
os.write(logfd, msg.encode("utf-8"))
os.close(logfd)
def finish_update(self):
# if error_status == 1:
# os._exit(1)
pass
def fork(self):
pid = os.fork()
if pid == 0:
self._fixup_fds()
self._redirect_stdin()
self._redirect_output()
return pid

View File

@ -0,0 +1,69 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#参考文档: https://cuiqingcai.com/6080.html
import os
path = '/var/log/kylin-system-updater/'
numlist = []
def get_FileSize(filePath):
fsize = os.path.getsize(filePath)
fsize = fsize / float(1024 * 1024)
return round(fsize, 2)
#日志回滚
def get_logfile():
if not os.path.exists(path):
os.makedirs(path)
#优先获取当前未写满100M的日志编号文件
for i in os.listdir(path):
if "kylin-system-updater.log." in os.path.basename(path + i):
numlist.append((path + i).split(".")[2])
if get_FileSize(path + i) < 100:
return path + i
#获取1-5未使用的最小数字的标号作为日志文件
for i in range(1, 6):
if str(i) not in numlist:
return(os.path.join(path, ("kylin-system-updater.log.%s") % i))
try:
#编号1-5日志文件均写满时删除第一个往前移动日志编号获取最后一个编号作为日志文件
if len(numlist) != 0:
os.remove(os.path.join(path, "kylin-system-updater.log.1"))
for i in range(2, 6):
os.rename(os.path.join(path, ("kylin-system-updater.log.%s") % i),
os.path.join(path, ("kylin-system-updater.log.%s") % (i - 1)))
return os.path.join(path, "kylin-system-updater.log.5")
#默认情况下未生成任何日志时使用编号1的日志文件
else:
return os.path.join(path, "kylin-system-updater.log.1")
except:
return os.path.join(path, "kylin-system-updater.log.1")
def upgrade_strategies_logfile():
if not os.path.exists(path):
os.makedirs(path)
#优先获取当前未写满100M的日志编号文件
for i in os.listdir(path):
if "upgrade-strategies-daemon.log." in os.path.basename(path + i):
numlist.append((path + i).split(".")[2])
if get_FileSize(path + i) < 10:
return path + i
#获取1-5未使用的最小数字的标号作为日志文件
for i in range(1, 6):
if str(i) not in numlist:
return(os.path.join(path, ("upgrade-strategies-daemon.log.%s") % i))
try:
#编号1-5日志文件均写满时删除第一个往前移动日志编号获取最后一个编号作为日志文件
if len(numlist) != 0:
os.remove(os.path.join(path, "upgrade-strategies-daemon.log.1"))
for i in range(2, 6):
os.rename(os.path.join(path, ("upgrade-strategies-daemon.log.%s") % i),
os.path.join(path, ("upgrade-strategies-daemon.log.%s") % (i - 1)))
return os.path.join(path, "upgrade-strategies-daemon.log.5")
#默认情况下未生成任何日志时使用编号1的日志文件
else:
return os.path.join(path, "upgrade-strategies-daemon.log.1")
except:
return os.path.join(path, "upgrade-strategies-daemon.log.1")

View File

@ -0,0 +1,434 @@
# MyCache.py
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
#
# Copyright (c) 2004-2008 Canonical
#
# Author: Michael Vogt <mvo@debian.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
from __future__ import absolute_import, print_function
import warnings
warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning)
import apt
import apt_pkg
import logging
import os
from urllib.error import HTTPError
from urllib.request import urlopen
from urllib.parse import urlsplit
from http.client import BadStatusLine
import socket
import re
import SystemUpdater.Core.DistUpgradeCache
from gettext import gettext as _
try:
from launchpadlib.launchpad import Launchpad
except ImportError:
Launchpad = None
CHANGELOGS_POOL = "https://changelogs.ubuntu.com/changelogs/pool/"
CHANGELOGS_URI = CHANGELOGS_POOL + "%s/%s/%s/%s_%s/%s"
class HttpsChangelogsUnsupportedError(Exception):
""" https changelogs with credentials are unsupported because of the
lack of certitifcation validation in urllib2 which allows MITM
attacks to steal the credentials
"""
pass
class MyCache(SystemUpdater.Core.DistUpgradeCache.MyCache):
CHANGELOG_ORIGIN = "Ubuntu"
def __init__(self, progress, rootdir=None):
apt.Cache.__init__(self, progress, rootdir)
# save for later
self.rootdir = rootdir
# raise if we have packages in reqreinst state
# and let the caller deal with that (runs partial upgrade)
assert len(self.req_reinstall_pkgs) == 0
# check if the dpkg journal is ok (we need to do that here
# too because libapt will only do it when it tries to lock
# the packaging system)
if self._dpkgJournalDirty() == True:
logging.info("dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem.")
# init the regular cache
self._initDepCache()
self.all_changes = {}
self.all_news = {}
# on broken packages, try to fix via saveDistUpgrade()
# if self._depcache.broken_count > 0:
# self.saveDistUpgrade()
# assert (self._depcache.broken_count == 0
# and self._depcache.del_count == 0)
self.launchpad = None
def _dpkgJournalDirty(self):
"""
test if the dpkg journal is dirty
(similar to debSystem::CheckUpdates)
"""
d = os.path.dirname(
apt_pkg.config.find_file("Dir::State::status")) + "/updates"
for f in os.listdir(d):
if re.match("[0-9]+", f):
return True
return False
def _initDepCache(self):
self._depcache.read_pinfile()
self._depcache.init()
def clear(self):
self._initDepCache()
@property
def required_download(self):
""" get the size of the packages that are required to download """
pm = apt_pkg.PackageManager(self._depcache)
fetcher = apt_pkg.Acquire()
pm.get_archives(fetcher, self._list, self._records)
return fetcher.fetch_needed
@property
def install_count(self):
return self._depcache.inst_count
def keep_count(self):
return self._depcache.keep_count
@property
def del_count(self):
return self._depcache.del_count
def _check_dependencies(self, target, deps):
"""Return True if any of the dependencies in deps match target."""
# TODO: handle virtual packages
for dep_or in deps:
if not dep_or:
continue
match = True
for base_dep in dep_or:
if (base_dep.name != target.package.shortname
or not apt_pkg.check_dep(
target.version, base_dep.relation, base_dep.version)):
match = False
if match:
return True
return False
def find_removal_justification(self, pkg):
target = pkg.installed
if not target:
return False
for cpkg in self:
candidate = cpkg.candidate
if candidate is not None:
if (self._check_dependencies(
target, candidate.get_dependencies("Conflicts"))
and self._check_dependencies(
target, candidate.get_dependencies("Replaces"))):
logging.info(
"%s Conflicts/Replaces %s; allowing removal" % (
candidate.package.shortname, pkg.shortname))
return True
return False
def saveDistUpgrade(self):
""" this functions mimics a upgrade but will never remove anything """
#upgrade(True) 为True时使用dist-upgrade进行升级
self._depcache.upgrade(True)
wouldDelete = self._depcache.del_count
wouldDelete = 0
if wouldDelete > 0:
deleted_pkgs = [pkg for pkg in self if pkg.marked_delete]
assert wouldDelete == len(deleted_pkgs)
for pkg in deleted_pkgs:
if self.find_removal_justification(pkg):
wouldDelete -= 1
if wouldDelete > 0:
self.clear()
assert (self._depcache.broken_count == 0
and self._depcache.del_count == 0)
# else:
# assert self._depcache.broken_count == 0
self._depcache.upgrade()
return wouldDelete
def _strip_epoch(self, verstr):
" strip of the epoch "
vers_no_epoch = verstr.split(":")
if len(vers_no_epoch) > 1:
verstr = "".join(vers_no_epoch[1:])
return verstr
def _get_changelog_or_news(self, name, fname, strict_versioning=False,
changelogs_uri=None):
" helper that fetches the file in question "
# don't touch the gui in this function, it needs to be thread-safe
pkg = self[name]
# get the src package name
srcpkg = pkg.candidate.source_name
# assume "main" section
src_section = "main"
# use the section of the candidate as a starting point
section = pkg._pcache._depcache.get_candidate_ver(pkg._pkg).section
# get the source version
srcver_epoch = pkg.candidate.source_version
srcver = self._strip_epoch(srcver_epoch)
split_section = section.split("/")
if len(split_section) > 1:
src_section = split_section[0]
# lib is handled special
prefix = srcpkg[0]
if srcpkg.startswith("lib"):
prefix = "lib" + srcpkg[3]
# the changelogs_uri argument overrides the default changelogs_uri,
# this is useful for e.g. PPAs where we construct the changelogs
# path differently
if changelogs_uri:
uri = changelogs_uri
else:
uri = CHANGELOGS_URI % (src_section, prefix, srcpkg, srcpkg,
srcver, fname)
# https uris are not supported when they contain a username/password
# because the urllib2 https implementation will not check certificates
# and so its possible to do a man-in-the-middle attack to steal the
# credentials
res = urlsplit(uri)
if res.scheme == "https" and res.username:
raise HttpsChangelogsUnsupportedError(
"https locations with username/password are not"
"supported to fetch changelogs")
# print("Trying: %s " % uri)
changelog = urlopen(uri)
#print(changelog.read())
# do only get the lines that are new
alllines = ""
regexp = "^%s \\((.*)\\)(.*)$" % (re.escape(srcpkg))
while True:
line = changelog.readline().decode("UTF-8", "replace")
if line == "":
break
match = re.match(regexp, line)
if match:
# strip epoch from installed version
# and from changelog too
installed = getattr(pkg.installed, "version", None)
if installed and ":" in installed:
installed = installed.split(":", 1)[1]
changelogver = match.group(1)
if changelogver and ":" in changelogver:
changelogver = changelogver.split(":", 1)[1]
# we test for "==" here for changelogs
# to ensure that the version
# is actually really in the changelog - if not
# just display it all, this catches cases like:
# gcc-defaults with "binver=4.3.1" and srcver=1.76
#
# for NEWS.Debian we do require the changelogver > installed
if strict_versioning:
if (installed
and apt_pkg.version_compare(changelogver,
installed) < 0):
break
else:
if (installed
and apt_pkg.version_compare(changelogver,
installed) == 0):
break
alllines = alllines + line
return alllines
def _extract_ppa_changelog_uri(self, name):
"""Return the changelog URI from the Launchpad API
Return None in case of an error.
"""
if not Launchpad:
logging.warning("Launchpadlib not available, cannot retrieve PPA "
"changelog")
return None
cdt = self[name].candidate
for uri in cdt.uris:
if urlsplit(uri).hostname != 'ppa.launchpad.net':
continue
match = re.search('http.*/(.*)/(.*)/ubuntu/.*', uri)
if match is not None:
user, ppa = match.group(1), match.group(2)
break
else:
logging.error("Unable to find a valid PPA candidate URL.")
return
# Login on launchpad if we are not already
if self.launchpad is None:
self.launchpad = Launchpad.login_anonymously('update-manager',
'production',
version='devel')
archive = self.launchpad.archives.getByReference(
reference='~%s/ubuntu/%s' % (user, ppa)
)
if archive is None:
logging.error("Unable to retrieve the archive from the Launchpad "
"API.")
return
spphs = archive.getPublishedSources(source_name=cdt.source_name,
exact_match=True,
version=cdt.source_version)
if not spphs:
logging.error("No published sources were retrieved from the "
"Launchpad API.")
return
return spphs[0].changelogUrl()
def _guess_third_party_changelogs_uri_by_source(self, name):
pkg = self[name]
deb_uri = pkg.candidate.uri
if deb_uri is None:
return None
srcrec = pkg.candidate.record.get("Source")
if not srcrec:
return None
# srcpkg can be "apt" or "gcc-default (1.0)"
srcpkg = srcrec.split("(")[0].strip()
if "(" in srcrec:
srcver = srcrec.split("(")[1].rstrip(")")
else:
srcver = pkg.candidate.source_version
base_uri = deb_uri.rpartition("/")[0]
return base_uri + "/%s_%s.changelog" % (srcpkg, srcver)
def _guess_third_party_changelogs_uri_by_binary(self, name):
""" guess changelogs uri based on ArchiveURI by replacing .deb
with .changelog
"""
# there is always a pkg and a pkg.candidate, no need to add
# check here
pkg = self[name]
deb_uri = pkg.candidate.uri
if deb_uri:
return "%s.changelog" % deb_uri.rsplit(".", 1)[0]
return None
def get_news_and_changelog(self, name, lock):
self.get_news(name)
self.get_changelog(name)
try:
lock.release()
except Exception:
pass
def get_news(self, name):
" get the NEWS.Debian file from the changelogs location "
try:
news = self._get_changelog_or_news(name, "NEWS.Debian", True)
except Exception:
return
if news:
self.all_news[name] = news
def _fetch_changelog_for_third_party_package(self, name, origins):
# Special case for PPAs
changelogs_uri_ppa = None
for origin in origins:
if origin.origin.startswith('LP-PPA-'):
try:
changelogs_uri_ppa = self._extract_ppa_changelog_uri(name)
break
except Exception:
logging.exception("Unable to connect to the Launchpad "
"API.")
# Try non official changelog location
changelogs_uri_binary = \
self._guess_third_party_changelogs_uri_by_binary(name)
changelogs_uri_source = \
self._guess_third_party_changelogs_uri_by_source(name)
error_message = ""
for changelogs_uri in [changelogs_uri_ppa,
changelogs_uri_binary,
changelogs_uri_source]:
if changelogs_uri:
try:
changelog = self._get_changelog_or_news(
name, "changelog", False, changelogs_uri)
self.all_changes[name] += changelog
except (HTTPError, HttpsChangelogsUnsupportedError):
# no changelogs_uri or 404
error_message = _(
"This update does not come from a "
"source that supports changelogs.")
except (IOError, BadStatusLine, socket.error):
# network errors and others
logging.exception("error on changelog fetching")
error_message = _(
"Failed to download the list of changes. \n"
"Please check your Internet connection.")
self.all_changes[name] += error_message
def get_changelog(self, name):
" get the changelog file from the changelog location "
origins = self[name].candidate.origins
self.all_changes[name] = _("Changes for %s versions:\n"
"Installed version: %s\n"
"Available version: %s\n\n") % \
(name, getattr(self[name].installed, "version", None),
self[name].candidate.version)
if self.CHANGELOG_ORIGIN not in [o.origin for o in origins]:
self._fetch_changelog_for_third_party_package(name, origins)
return
# fixup epoch handling version
srcpkg = self[name].candidate.source_name
srcver_epoch = self[name].candidate.source_version.replace(':', '%3A')
try:
changelog = self._get_changelog_or_news(name, "changelog")
if len(changelog) == 0:
changelog = _("The changelog does not contain any relevant "
"changes.\n\n"
"Please use http://launchpad.net/ubuntu/+source/"
"%s/%s/+changelog\n"
"until the changes become available or try "
"again later.") % (srcpkg, srcver_epoch)
except HTTPError:
changelog = _("The list of changes is not available yet.\n\n"
"Please use http://launchpad.net/ubuntu/+source/"
"%s/%s/+changelog\n"
"until the changes become available or try again "
"later.") % (srcpkg, srcver_epoch)
except (IOError, BadStatusLine, socket.error) as e:
print("caught exception: ", e)
changelog = _("Failed to download the list "
"of changes. \nPlease "
"check your Internet "
"connection.")
self.all_changes[name] += changelog

View File

@ -0,0 +1,580 @@
#!/usr/bin/python3
import apt
import apt_pkg
import fnmatch
import logging
import logging.handlers
import re
import os
import sys
import string
import subprocess
import json
try:
from typing import List
from typing import Union
except ImportError:
pass
from gettext import gettext as _
SYSTEM_UPDATER_CORE_LIB_PATH="/usr/share/kylin-system-updater/"
sys.path.append(SYSTEM_UPDATER_CORE_LIB_PATH)
from SystemUpdater.Core.utils import get_config_patch
ImportantListPath="/var/lib/kylin-software-properties/template/important.list"
SOURCESLIST = "/etc/apt/sources.list"
# no py3 lsb_release in debian :/
DISTRO_CODENAME = subprocess.check_output(
["lsb_release", "-c", "-s"], universal_newlines=True).strip() # type: str
DISTRO_DESC = subprocess.check_output(
["lsb_release", "-d", "-s"], universal_newlines=True).strip() # type: str
DISTRO_ID = subprocess.check_output(
["lsb_release", "-i", "-s"], universal_newlines=True).strip() # type: str
ARCHITECTUREMAP = ['arm64','amd64','armhf','i386','loongarch64','mips64el','sw64']
RELEASEOFFSET = 1
ORIGINOFFSET = 2
HTTPTYPE = "HTTP"
FTPTYPE = "FTP"
class UpdateListFilterCache(apt.Cache):
def __init__(self, window_main):
self.window_main = window_main
# whitelist
self.upgradeList = []
# 必须升级的包
self.installList = []
self.config_path = get_config_patch()
# 获取源属性
self.origin_property = OriginProperty()
self.origin_property.get_allowed_sources()
self.origin_property.get_allowed_origin()
self.allowed_origins = get_allowed_origins(self.origin_property.allow_origin)
self.allowed_origins = deleteDuplicatedElementFromList(self.allowed_origins)
logging.info(_("Allowed origins: %s"),
self.allowed_origins)
# self.blacklist = apt_pkg.config.value_list(
# "Kylin-system-updater::Package-Blacklist")
# self.blacklist = deleteDuplicatedElementFromList(self.blacklist)
# self.whitelist = apt_pkg.config.value_list(
# "Kylin-system-updater::Package-Whitelist")
# self.whitelist = deleteDuplicatedElementFromList(self.whitelist)
# self.strict_whitelist = apt_pkg.config.find_b(
# "Kylin-system-updater::Package-Whitelist-Strict", False)
def checkInCache(self):
logging.info("start Check in cache")
tmplist = []
cache = apt.Cache()
for i in self.upgradeList:
try:
cache[i]
tmplist.append(i)
except Exception as e:
pass
self.upgradeList = tmplist
def initLocalPackagesList(self):
jsonfiles = []
tmplist = []
# 获取importantlist 本次更新推送
with open(ImportantListPath, 'r') as f:
text = f.read()
importantList = text.split()
logging.info("importantList: %s",importantList)
f.close()
if not importantList:
logging.error("importantList is empty")
exit(-1)
# 获取/usr/share/kylin-update-desktop-config/data/下所有json文件
for root,dirs,files in os.walk(self.config_path):
pass
for i in files:
if ".json" in i:
jsonfiles.append(i.split('.')[0])
# 找到importantlist中对应的json文件
for i in importantList:
if i not in jsonfiles:
# 说明这个是单独的包,不在分组中
# 加入更新列表
if i not in self.upgradeList:
self.upgradeList.append(i)
else:
# 在分组中
# 获取每个对应json文件中的upgrade_list
if i in jsonfiles:
filepath = os.path.join(self.config_path, i)
filepath = filepath+".json"
with open(filepath, 'r') as f:
pkgdict = f.read()
jsonfile = json.loads(pkgdict)
tmplist = jsonfile['install_list']
for j in tmplist:
if j not in self.upgradeList:
self.upgradeList.append(j)
f.close()
# 更改传入包列表经过源过滤返回的pkg中进行版本调整
def check_in_allowed_origin(self, pkg_lists, _is_adjust):
new_upgrade_pkgs = []
adjust_candidate_pkgs = []
for pkg in pkg_lists:
try:
new_ver = ver_in_allowed_origin(pkg, self.allowed_origins)
if _is_adjust and len(new_ver) == 0:
logging.warning("< %s > did not find a suitable version..." % pkg.name)
continue
if len(new_ver) == 0:
continue
if not pkg.installed: # 判断安装列表
if pkg.candidate == new_ver[0] and pkg not in new_upgrade_pkgs:
new_upgrade_pkgs.append(pkg)
elif new_ver[0] != pkg.candidate and pkg not in new_upgrade_pkgs:
logging.info("adjusting candidate version: %s" % new_ver[0])
if _is_adjust == True:
pkg.candidate = new_ver[0]
adjust_candidate_pkgs.append(pkg.name+"="+pkg.candidate.version)
new_upgrade_pkgs.append(pkg)
else: # 判断升级列表
for nv in new_ver:
if nv > pkg.installed and nv != pkg.candidate:
logging.info("adjusting candidate version: %s" % nv)
if _is_adjust == True:
pkg.candidate = nv
adjust_candidate_pkgs.append(pkg.name+"="+pkg.candidate.version)
break
elif nv > pkg.installed and nv == pkg.candidate:
new_upgrade_pkgs.append(pkg)
break
elif _is_adjust == True:
logging.warning("< %s > did not find a suitable version..." % pkg.name)
except NoAllowedOriginError:
logging.error("Cannot found allowed version: %s", pkg.name)
continue
return (new_upgrade_pkgs, adjust_candidate_pkgs)
def is_pkgname_in_blacklist(self, pkgs):
blacklist_filter_pkgs = []
for pkg in pkgs:
if pkg.name in self.blacklist:
pass
else :
blacklist_filter_pkgs.append(pkg)
return blacklist_filter_pkgs
def is_pkgname_in_whitelist(self, pkgs):
whitelist_filter_upgrade_pkgs = []
for pkg in pkgs:
if pkg.name in self.upgradeList:
whitelist_filter_upgrade_pkgs.append(pkg)
else :
pkg.mark_keep()
return whitelist_filter_upgrade_pkgs
class OriginProperty():
def __init__(self):
# 包含了本地所有源 http & ftp
self.local_sourcelist = {"http":[],"ftp":[]}
# 经过解析后的本地源,获取所有的分发属性
self.local_origin = {"http":[],"ftp":[]}
# 允许的源列表
self.allow_sources = []
# 允许的源+属性
self.allow_origin = {"http":[],"ftp":[]}
# 加载本地所有源
self.init_local_origin()
# 进行属性解析
self.analytic_properties(self.local_sourcelist)
def init_local_origin(self):
http_origin = {}
ftp_orgin = {}
#apt policy
sh_retval = os.popen("apt-cache policy").read().split("\n")
# policy = [ rv for rv in sh_retval if "http" in rv or "ftp" in rv or "release" in rv or "origin" in rv]
for rv in sh_retval:
if "http" in rv:
http_origin['sources'] = rv
http_origin['release'] = sh_retval[sh_retval.index(rv) + RELEASEOFFSET]
http_origin['origin'] = sh_retval[sh_retval.index(rv) + ORIGINOFFSET]
self.local_sourcelist['http'].append(http_origin.copy())
elif "ftp" in rv:
ftp_orgin['sources'] = rv
ftp_orgin['release'] = sh_retval[sh_retval.index(rv) + RELEASEOFFSET]
ftp_orgin['origin'] = sh_retval[sh_retval.index(rv) + ORIGINOFFSET]
self.local_sourcelist['ftp'].append(ftp_orgin.copy())
def merge_origin(self, source_type, source_origin):
is_append = True
if source_type == HTTPTYPE:
if self.local_origin['http']:
for lo in self.local_origin['http']:
if lo['origin_source'] == source_origin['origin_source'] and lo['dist'] == source_origin['dist']:
lo['component'] = list(set(lo['component']).union(set(source_origin['component'])))
is_append = False
if is_append:
self.local_origin['http'].append(source_origin.copy())
else:
self.local_origin['http'].append(source_origin.copy())
elif source_type == FTPTYPE:
if self.local_origin['ftp']:
for lo in self.local_origin['ftp']:
if lo['origin_source'] == source_origin['origin_source'] and lo['dist'] == source_origin['dist']:
lo['component'] = list(set(lo['component']).union(set(source_origin['component'])))
is_append = False
if is_append:
self.local_origin['ftp'].append(source_origin.copy())
else:
self.local_origin['ftp'].append(source_origin.copy())
def analytic_properties(self, local_sourcelist):
http_origin = {"component":[],"release":{}}
ftp_orgin = {"component":[],"release":{}}
dist_list = []
# 经过解析后的本地源,获取所有的分发属性
for ls in local_sourcelist['http']:
for item in filter(not_empty, ls['sources'].split(' ')):
if item.isdigit():
http_origin['policy_priority'] = item
elif "http" in item:
http_origin['origin_source'] = item
elif "/" in item:
dist_list = item.split("/")
dist_list.pop()
http_origin['dist'] = "/".join(dist_list)
http_origin['component'].append(item.split("/")[1])
elif item not in ARCHITECTUREMAP and item != "Packages":
http_origin['component'].append(item)
release_list = ls['release'].split(',')
release_list = [ rl.strip() for rl in release_list ]
if "release" in release_list[0]:
release_list[0] = release_list[0].lstrip("release").strip()
for rl in release_list:
if "=" in rl:
self.generate_dict(http_origin['release'], rl)
for item in filter(not_empty, ls['origin'].split(' ')):
if "origin" not in ls['origin']:
break
elif "origin" != item:
http_origin['origin'] = item
self.merge_origin(HTTPTYPE, http_origin)
http_origin = {"component":[],"release":{}}
for ls in local_sourcelist['ftp']:
for item in filter(not_empty, ls['sources'].split(' ')):
if item.isdigit():
ftp_orgin['policy_priority'] = item
elif "ftp" in item:
ftp_orgin['origin_source'] = item
elif "/" in item:
ftp_orgin['dist'] = item.split("/")[0]
ftp_orgin['component'].append(item.split("/")[1])
elif item not in ARCHITECTUREMAP and item != "Packages":
ftp_orgin['component'].append(item)
release_list = ls['release'].split(',')
if "release " in release_list[0]:
release_list[0] = release_list[0].lstrip("release ")
for rl in release_list:
if "=" in rl:
self.generate_dict(ftp_orgin['release'], rl)
for item in filter(not_empty, ls['origin'].split(' ')):
if "origin" not in ls['origin']:
break
elif "origin" != item:
ftp_orgin['origin'] = item
self.merge_origin(FTPTYPE, ftp_orgin)
ftp_orgin = {"component":[],"release":{}}
def generate_dict(self, dict, item):
item = item.strip()
if item == "":
logging.warning("empty match string matches nothing")
return False
(what, value) = [ s for s in item.split("=")]
if what in ('o', 'origin'):
dict['origin'] = value
elif what in ("l", "label"):
dict['label'] = value
elif what in ("a", "suite", "archive"):
dict['archive'] = value
elif what in ("c", "component"):
dict['component'] = value
elif what in ("site",):
dict['site'] = value
elif what in ("n", "codename",):
dict['codename'] = value
else:
dict[what] = value
# raise UnknownMatcherError(
# "Unknown whitelist entry for matcher %s (value %s)" % (
# what, value))
def get_allowed_sources(self):
# 源地址,在本地源列表中查找. 源服务器下发source.list为允许的源, 本模块屏蔽了sources.list.d下的源
# 获取允许的源
try:
old_sources_list = apt_pkg.config.find("Dir::Etc::sourcelist")
old_sources_list_d = apt_pkg.config.find("Dir::Etc::sourceparts")
old_cleanup = apt_pkg.config.find("APT::List-Cleanup")
apt_pkg.config.set("Dir::Etc::sourcelist",
os.path.abspath(SOURCESLIST))
apt_pkg.config.set("Dir::Etc::sourceparts", "xxx")
apt_pkg.config.set("APT::List-Cleanup", "0")
slist = apt_pkg.SourceList()
slist.read_main_list()
self.allow_sources = slist.list
except Exception as e:
logging.error(str(e))
finally:
apt_pkg.config.set("Dir::Etc::sourcelist",
old_sources_list)
apt_pkg.config.set("Dir::Etc::sourceparts",
old_sources_list_d)
apt_pkg.config.set("APT::List-Cleanup",
old_cleanup)
def get_allowed_origin(self):
# 获取允许的源
# 生成源与属性
self.local_origin
self.allow_sources
self.allow_origin
try:
for item in self.allow_sources:
for lo in self.local_origin['http']:
if item.uri.strip('/') == lo['origin_source'].strip('/') and item.dist == lo['dist']:
self.allow_origin['http'].append(lo)
for lo in self.local_origin['ftp']:
if item.uri.strip('/') == lo['origin_source'].strip('/') and item.dist == lo['dist']:
self.allow_origin['ftp'].append(lo)
except Exception as e:
logging.error(str(e))
class UnattendUpgradeFilter():
def __init__(self) -> None:
pass
def GetAllowOrigins(self):
# 获取源属性
self.origin_property = OriginProperty()
self.origin_property.get_allowed_sources()
self.origin_property.get_allowed_origin()
self.allowed_origins = get_allowed_origins(self.origin_property.allow_origin)
self.allowed_origins = deleteDuplicatedElementFromList(self.allowed_origins)
logging.info(_("Allowed origins: %s"),
self.allowed_origins)
return self.allowed_origins
def ver_in_allowed_origin(pkg, allow_origin):
# type: (apt.Package, List[str]) -> apt.package.Version
allown_versions = []
versions = _get_priority_order(pkg)
# 获取每个优先级别中 允许源的最高版本
allown_versions = _get_allowed_list(versions, allow_origin)
return allown_versions
def _get_priority_order(pkg):
versions = []
for ver in pkg.versions:
if versions:
for v in versions:
if v.policy_priority >= ver.policy_priority and v == versions[-1]:
break
elif v.policy_priority >= ver.policy_priority and v != versions[-1]:
continue
else:
index = versions.index(v)
versions.insert(index,ver)
break
if v == versions[-1] and versions[-1].policy_priority >= ver.policy_priority:
versions.append(ver)
else:
versions.append(ver)
return versions
def _get_allowed_list(versions, allow_origin):
current_priority = -100
allown_versions = []
for ver in versions:
if current_priority != ver.policy_priority:
if is_in_allowed_origin(ver, allow_origin):
allown_versions.append(ver)
current_priority = ver.policy_priority
else:
continue
return allown_versions
def get_allowed_origins(allow_origin):
""" return a list of allowed origins
"""
allowed_origins = []
origin = ''
archive = ''
uri = ''
label = ''
for ao in (allow_origin['http']+allow_origin['ftp']):
if 'origin' in ao['release']:
origin = 'o='+ao['release']['origin']
else:
origin = 'o='
if 'archive' in ao['release']:
archive = 'a='+ao['release']['archive']
else:
archive = 'a='
if 'label' in ao['release']:
label = 'l='+ao['release']['label']
else:
label = 'l='
if 'origin_source' in ao:
uri = 'uri='+ao['origin_source']
else:
uri = 'uri='
allowed_origins.append(origin+","+archive+","+label+","+uri)
return allowed_origins
def get_allowed_origins_legacy():
# type: () -> List[str]
""" legacy support for old Allowed-Origins var """
allowed_origins = [] # type: List[str]
key = "Kylin-system-updater::Allowed-Origins"
try:
for s in apt_pkg.config.value_list(key):
# if there is a ":" use that as seperator, else use spaces
if re.findall(r'(?<!\\):', s):
(distro_id, distro_codename) = re.split(r'(?<!\\):', s)
else:
(distro_id, distro_codename) = s.split()
# unescape "\:" back to ":"
distro_id = re.sub(r'\\:', ':', distro_id)
# escape "," (see LP: #824856) - can this be simpler?
distro_id = re.sub(r'([^\\]),', r'\1\\,', distro_id)
distro_codename = re.sub(r'([^\\]),', r'\1\\,', distro_codename)
# convert to new format
allowed_origins.append("o=%s,a=%s" % (substitute(distro_id),
substitute(distro_codename)))
except ValueError:
logging.error(_("Unable to parse %s." % key))
raise
return allowed_origins
def substitute(line):
# type: (str) -> str
""" substitude known mappings and return a new string
Currently supported ${distro-release}
"""
mapping = {"distro_codename": get_distro_codename(),
"distro_id": get_distro_id()}
return string.Template(line).substitute(mapping)
def get_distro_codename():
# type: () -> str
return DISTRO_CODENAME
def get_distro_id():
# type: () -> str
return DISTRO_ID
def is_in_allowed_origin(ver, allowed_origins):
# type: (apt.package.Version, List[str]) -> bool
if not ver:
return False
for origin in ver.origins:
if is_allowed_origin(origin, allowed_origins):
return True
return False
def is_allowed_origin(origin, allowed_origins):
# type: (Union[apt.package.Origin, apt_pkg.PackageFile], List[str]) -> bool
for allowed in allowed_origins:
if match_whitelist_string(allowed, origin):
return True
return False
def match_whitelist_string(whitelist, origin):
# type: (str, Union[apt.package.Origin, apt_pkg.PackageFile]) -> bool
"""
take a whitelist string in the form "origin=Debian,label=Debian-Security"
and match against the given python-apt origin. A empty whitelist string
never matches anything.
"""
whitelist = whitelist.strip()
if whitelist == "":
logging.warning("empty match string matches nothing")
return False
res = True
# make "\," the html quote equivalent
whitelist = whitelist.replace("\\,", "%2C")
for token in whitelist.split(","):
# strip and unquote the "," back
(what, value) = [s.strip().replace("%2C", ",")
for s in token.split("=")]
# logging.debug("matching %s=%s against %s" % (
# what, value, origin))
# support substitution here as well
value = substitute(value)
# first char is apt-cache policy output, send is the name
# in the Release file
if what in ("o", "origin"):
match = fnmatch.fnmatch(origin.origin, value)
elif what in ("l", "label"):
match = fnmatch.fnmatch(origin.label, value)
elif what in ("a", "suite", "archive"):
match = fnmatch.fnmatch(origin.archive, value)
elif what in ("c", "component"):
match = fnmatch.fnmatch(origin.component, value)
elif what in ("site",):
match = fnmatch.fnmatch(origin.site, value)
elif what in ("n", "codename",):
match = fnmatch.fnmatch(origin.codename, value)
elif what in ("uri",):
match = True
else:
raise UnknownMatcherError(
"Unknown whitelist entry for matcher %s (token %s)" % (
what, token))
# update res
res = res and match
# logging.debug("matching %s=%s against %s" % (
# what, value, origin))
return res
def deleteDuplicatedElementFromList(list):
resultList = []
for item in list:
if not item in resultList:
resultList.append(item)
return resultList
def not_empty(s):
return s and s.strip()
class UnknownMatcherError(ValueError):
pass
class NoAllowedOriginError(ValueError):
pass

View File

@ -0,0 +1,633 @@
# UpdateList.py
from gettext import gettext as _
import logging
import os
import json
import yaml
import shutil
from gi.repository import Gio
from .OriginFilter import UpdateListFilterCache
from .errors import *
from .enums import *
from SystemUpdater.Core.utils import get_config_patch
class LocalUpgradeDataList:
"""
Represent the (potentially partial) results of an unattended-upgrades
run
"""
def __init__(self,
groups_pkgs={},
upgrade_groups=[],
single_pkgs=[],
adjust_pkgs=[],
):
#可升级的组列表
self.upgrade_groups = upgrade_groups
#组列表中包含的包
self.groups_pkgs = groups_pkgs
#推送的可升级的单包
self.single_pkgs = single_pkgs
#调整版本列表 源过滤
self.adjust_pkgs = adjust_pkgs
#加版本号的升级包
self.versoin_pkgs = {'single_upgrade':{}, 'groups_upgrade':{}}
class UpdateList():
OUTPUT_CONFIG_PATH = '/var/lib/kylin-system-updater/json/'
IMPORTANT_LIST_PATH = '/var/lib/kylin-software-properties/template/important.list'
def __init__(self,parent):
self.parent = parent
#所有的组升级安装列表
self.upgrade_meta = LocalUpgradeDataList({},[],[],[])
if 'XDG_CURRENT_DESKTOP' in os.environ:
self.current_desktop = os.environ.get('XDG_CURRENT_DESKTOP')
else:
self.current_desktop = ''
if 'XDG_DATA_DIRS' in os.environ and os.environ['XDG_DATA_DIRS']:
data_dirs = os.environ['XDG_DATA_DIRS']
else:
data_dirs = '/usr/local/share/:/usr/share/'
self.application_dirs = [os.path.join(base, 'applications')
for base in data_dirs.split(':')]
self.config_path = get_config_patch()
if self.parent.install_mode.check_filter() == True:
#开启原过滤
self.fu = UpdateListFilterCache(self.parent)
else:
self.fu = None
logging.info("Close to Allowed origin fiter...")
#清空上次输出的分组JSON文件
def _empty_output_dir(self):
#清空 升级列表
if not os.path.exists(self.OUTPUT_CONFIG_PATH):
os.makedirs(self.OUTPUT_CONFIG_PATH)
logging.info('making the ConfigPath(%s) is complete...',self.OUTPUT_CONFIG_PATH)
else:
shutil.rmtree(self.OUTPUT_CONFIG_PATH)
os.makedirs(self.OUTPUT_CONFIG_PATH)
logging.info('Emptying the ConfigPath(%s) is complete...',self.OUTPUT_CONFIG_PATH)
#读取推送列表,判断分组和单包推送,再进行源过滤
def _make_important_list(self,cache,pkgs_upgrade,important_list = []):
upgradeable_pkgs = []
tmp = []
upgradeable_groups = []
logging.info("The Server Push List: %a",important_list)
for pkg_name in important_list:
#检查是否在cache 没有在cache中属于组
if pkg_name in cache:
pkg_obj = cache[pkg_name]
#在可升级的列表当中 此步骤为了排除已安装不需要升级的
if pkg_obj.is_installed:
if pkg_name in pkgs_upgrade:
pkgs_upgrade.remove(pkg_name)
tmp.append(pkg_obj)
else:
tmp.append(pkg_obj)
else:
upgradeable_groups.append(pkg_name)
if tmp != []:
install_list,upgrade_list,adjust_pkgs = self._make_fiter_origin(tmp,True)
self.upgrade_meta.adjust_pkgs.extend(adjust_pkgs)
upgradeable_pkgs = install_list + upgrade_list
logging.info("Push Single Packages: %a, Push Groups:%a",upgradeable_pkgs,upgradeable_groups)
return upgradeable_groups,upgradeable_pkgs
def _make_pkg_info_json(self,cache,pkgs_list):
total_download_size = 0
total_installed_size = 0
pkgs_info_json = {}
for pkg_name in pkgs_list:
pkg = cache[pkg_name]
#当前版本
cur_version = getattr(pkg.installed, "version", '')
new_version = getattr(pkg.candidate, "version", '')
#获取下载大小
download_size = getattr(pkg.candidate, "size", 0)
installed_size = getattr(pkg.candidate, "installed_size", 0)
total_download_size = total_download_size + download_size
total_installed_size = total_installed_size + installed_size
pkgs_info_json.update({pkg_name:{"cur_version":cur_version,"new_version":new_version,\
"download_size":str(download_size),"install_size":str(installed_size)}})
pkgs_info_json.update({"total_download_size":str(total_download_size)})
pkgs_info_json.update({"total_install_size":str(total_installed_size)})
return pkgs_info_json
#检查包是否在cache中 返回新得列表没 有安装的话才添加到列表
def _check_pkg_in_cache(self,cache,pkgs_list):
new_pkgs_list = []
for pkg_name in pkgs_list:
#检查是否在cache 以及 是否安装检查
if pkg_name in cache and not cache[pkg_name].is_installed:
new_pkgs_list.append(pkg_name)
else:
pass
return new_pkgs_list
def _make_group_output_json(self,data,data_yaml,upgrade_pkgs_json,install_pkgs_json):
groups_base_info = {}
output_json = {}
#FIXME: 确定输出文件的文件名 以及放置位置
output_config_name = self.OUTPUT_CONFIG_PATH + data['package'] + '.json'
#4、添加一些基础信息
groups_base_info.update({"package":data['package']})
groups_base_info.update({"new_version":data['version']})
groups_base_info.update({"name":data['name']})
groups_base_info.update({"description":data['description']})
groups_base_info.update({"icon":data['icon']})
#添加读yaml文件
groups_base_info.update({"changelog":data_yaml['changelog']})
#5、添加升级的内容
output_json.update(groups_base_info)
output_json.update({"upgrade_list":upgrade_pkgs_json})
output_json.update({"install_list":install_pkgs_json})
# output_json.update({"hold_list":hold_pkgs_list})
# output_json.update({"remove_list":remove_pkgs_list})
#6 产生JSON文件
with open(output_config_name, 'w', encoding='utf-8') as f:
json.dump(output_json, f, ensure_ascii=False, indent=4)
logging.info("Generate Jsonfile(%s) to complete... ",output_config_name)
#进行源过滤is_adjust 是否调整cache中的候选版本单包推送会调整保持控制面板显示正确的版本
def _make_fiter_origin(self,pkgs_list,adjust_versions):
install_pkgs = []
upgrade_pkgs = []
adjust_pkgs = []
#是否进行源过滤的选项
if self.fu != None:
try:
after_pkgs_list,adjust_pkgs = self.fu.check_in_allowed_origin(pkgs_list,adjust_versions)
except Exception as e:
after_pkgs_list = pkgs_list
logging.error("Check Allowed origin is occur error:" + str(e))
else:
after_pkgs_list = pkgs_list
adjust_pkgs = []
for pkg_obj in after_pkgs_list:
if pkg_obj.is_installed:
upgrade_pkgs.append(pkg_obj.name)
else:
install_pkgs.append(pkg_obj.name)
return install_pkgs,upgrade_pkgs,adjust_pkgs
#从本地中获取本次升级需要升级的包 部分升级和全部升级使用 全盘升级不适用
def _make_pkgs_list(self,cache,groups_pkgs,groups_list,pkg_list):
pkgs_install = []
pkgs_upgrade = []
#单包的升级方式
for pkg in pkg_list:
if cache[pkg].is_installed:
pkgs_upgrade.append(pkg)
else:
pkgs_install.append(pkg)
#遍历升级组列表
for group_name in groups_list:
pkgs_install += groups_pkgs.get(group_name,[]).get('pkgs_install',[])
pkgs_upgrade += groups_pkgs.get(group_name,[]).get('pkgs_upgrade',[])
return pkgs_install,pkgs_upgrade
#输出白名单的配置
def _make_autoupgrade_config(self,cache,upgrade_data,_adjust_pkgs):
pkgs_install,pkgs_upgrade = self._make_pkgs_list(cache,upgrade_data.groups_pkgs,upgrade_data.upgrade_groups,upgrade_data.single_pkgs)
split_adjust_pkgs = [i.split("=")[0] for i in _adjust_pkgs]
output_config_name = self.OUTPUT_CONFIG_PATH + 'auto-upgrade-list.json'
output_json = {}
install_info = {}
for pkg in pkgs_install:
pkg_cache = cache[pkg]
pkgs_json = {}
pkgs_json.update({"cur_version":getattr(pkg_cache.installed, "version", '')})
if pkg in split_adjust_pkgs:
version_adjust = _adjust_pkgs[split_adjust_pkgs.index(pkg)].split("=")[1]
pkgs_json.update({"new_version":version_adjust})
else:
pkgs_json.update({"new_version":getattr(pkg_cache.candidate, "version", '')})
install_info.update({pkg:pkgs_json})
upgrade_json = {}
for pkg in pkgs_upgrade:
pkg_cache = cache[pkg]
pkgs_json = {}
pkgs_json.update({"cur_version":getattr(pkg_cache.installed, "version", '')})
if pkg in split_adjust_pkgs:
version_adjust = _adjust_pkgs[split_adjust_pkgs.index(pkg)].split("=")[1]
pkgs_json.update({"new_version":version_adjust})
else:
pkgs_json.update({"new_version":getattr(pkg_cache.candidate, "version", '')})
upgrade_json.update({pkg:pkgs_json})
group_json = {}
for ug in self.upgrade_meta.groups_pkgs:
pkgs_json = {}
with open(self.config_path + str(ug) + ".yaml", "r") as stream:
try:
data_yaml = yaml.safe_load(stream)
pkgs_json.update({"cur_version":""})
pkgs_json.update({"new_version":data_yaml["version"]})
pkgs_json.update({"changelog":data_yaml["changelog"]})
except yaml.YAMLError as exc:
logging.error(exc)
group_json.update({ug:pkgs_json})
single_json = {}
for us in self.upgrade_meta.single_pkgs:
pkg_cache = cache[us]
pkgs_json = {}
pkgs_json.update({"cur_version":getattr(pkg_cache.installed, "version", '')})
if pkg in split_adjust_pkgs:
version_adjust = _adjust_pkgs[split_adjust_pkgs.index(pkg)].split("=")[1]
pkgs_json.update({"new_version":version_adjust})
else:
pkgs_json.update({"new_version":getattr(pkg_cache.candidate, "version", '')})
pkgs_json.update({"changelog":""})
single_json.update({us:pkgs_json})
output_json.update({"upgrade_list":upgrade_json})
output_json.update({"install_list":install_info})
output_json.update({"group_json":group_json})
output_json.update({"single_json":single_json})
#产生JSON文件
with open(output_config_name, 'w', encoding='utf-8') as f:
json.dump(output_json, f, ensure_ascii=False, indent=4)
logging.info("Generate AutoUpgrade Configfile to Complete and Jsonfile(%s) to complete... ",output_config_name)
def _split_package_id(self,package):
"""Return the name, the version number and the release of the
specified package."""
if "=" in package:
name, version = package.split("=", 1)
release = None
elif "/" in package:
name, release = package.split("/", 1)
version = None
else:
name = package
version = release = None
return name, version, release
def _make_downgrade(self,cache,downgrade_pkgs):
output_downgrade = []
adjust_pkgs = []
for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg)
for pkg in downgrade_pkgs]:
try:
pkg = cache[pkg_name]
except KeyError:
logging.warning("Package %s isn't available",pkg_name)
continue
if not pkg.is_installed:
logging.warning("Package %s isn't installed",pkg_name)
if pkg_ver:
if pkg.installed and pkg.installed.version < pkg_ver:
logging.warning("The former version %s of %s is already installed",pkg.installed.version, pkg.name)
continue
elif pkg.installed and pkg.installed.version == pkg_ver:
logging.warning("The version %s of %s is already installed",pkg.installed.version, pkg.name)
continue
try:
pkg.candidate = pkg.versions[pkg_ver]
except KeyError:
logging.warning("The version %s of %s isn't available",pkg_ver, pkg_name)
continue
output_downgrade.append(pkg_name)
adjust_pkgs.append(pkg_name+'='+pkg_ver)
return output_downgrade,adjust_pkgs
def _get_downgrade_list(self,cache,data):
downgrade_pkgs = []
try:
downgrade_raw = data['force_install_list']
except Exception as e:
downgrade_raw = []
for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg)
for pkg in downgrade_raw]:
if pkg_name in cache:
downgrade_pkgs.append(pkg_name)
else:
logging.warning("Package %s isn't available",pkg_name)
continue
return downgrade_raw,downgrade_pkgs
def _make_groups_pkgs(self,cache,data,pkgs_upgrade = []):
upgrade_pkgs_list = data['upgrade_list']
#检查包是否在cache中 以及是否已经安装 没有安装的话才添加到列表
new_install_list = self._check_pkg_in_cache(cache,data['install_list'])
downgrade_raw,downgrade_pkgs = self._get_downgrade_list(cache,data)
#被降级的软件包优先级最高
for pkg in downgrade_pkgs:
if pkg in upgrade_pkgs_list:
upgrade_pkgs_list.remove(pkg)
if pkg in new_install_list:
new_install_list.remove(pkg)
if pkg in self.upgrade_meta.single_pkgs:
self.upgrade_meta.single_pkgs.remove(pkg)
#进行交集 升级列表
new_upgrade_list = list(set(pkgs_upgrade) & set(upgrade_pkgs_list))
#进行源过滤
new_install_list,new_upgrade_list,adjust_pkgs = self._make_fiter_origin([cache[pkg] for pkg in new_install_list + new_upgrade_list],False)
self.upgrade_meta.adjust_pkgs.extend(adjust_pkgs)
#在总升级列表中移除这些包
for pkg in new_upgrade_list:
pkgs_upgrade.remove(pkg)
downgrade_pkg,adjust_pkgs = self._make_downgrade(cache,downgrade_raw)
self.upgrade_meta.adjust_pkgs.extend(adjust_pkgs)
new_upgrade_list.extend(downgrade_pkg)
#单包的优先级最高 从组中剔除此包
for pkg in self.upgrade_meta.single_pkgs:
if pkg in new_install_list:
new_install_list.remove(pkg)
return new_install_list,new_upgrade_list
def _make_groups_upgrade(self,cache,group_list,is_openkylin,pkgs_install,pkgs_upgrade):
upgrade_list = []
install_list = []
if os.path.isdir(self.config_path) == False:
logging.warning("configPath(%s) is not exists...",self.config_path)
return
files = os.listdir(self.config_path) #获得文件夹中所有文件的名称列表
for ifile in files:
#判是否是目录以及是否以JSON结尾
if ifile.endswith('.json'):
#读取组JSON文件
with open(self.config_path+ifile,'r') as f:
try:
data = json.load(f)
except Exception as exc:
logging.error(exc)
raise UpdateBaseError(ERROR_LOAD_CONFIG_FAILED)
group_name = data['package']
#读取组的yaml 文件的changelog的信息
with open(self.config_path + group_name + ".yaml", "r") as stream:
try:
data_yaml = yaml.safe_load(stream)
except Exception as exc:
logging.error(exc)
raise UpdateBaseError(ERROR_LOAD_CONFIG_FAILED)
#过滤没有推送的配置文件
if not group_name in group_list:
continue
if is_openkylin == True:
install_list,upgrade_list = pkgs_install,pkgs_upgrade
else:
install_list,upgrade_list = self._make_groups_pkgs(cache,data,pkgs_upgrade)
#判断当前是否可升级或者新装的包
if len(install_list) == 0 and len(upgrade_list) == 0:
continue
#3、生成升级的包列表JSON
upgrade_pkgs_json = self._make_pkg_info_json(cache,upgrade_list)
#2、生成安装的软件列表
install_pkgs_json = self._make_pkg_info_json(cache,install_list)
#输出JSON配置文件
self._make_group_output_json(data,data_yaml,upgrade_pkgs_json,install_pkgs_json)
#保存分组版本号,好像没有
self.upgrade_meta.versoin_pkgs['groups_upgrade'].update({group_name:''})
#添加到字典维护的升级列表
self.upgrade_meta.upgrade_groups.append(group_name)
self.upgrade_meta.groups_pkgs.update({group_name:{"pkgs_upgrade":upgrade_list,"pkgs_install":install_list}})
logging.info("Group(%s) upgrade:%d install:%d",group_name,len(upgrade_list),len(install_list))
else:
pass
def _make_openkylin_output_json(self,upgrade_pkgs_json,install_pkgs_json):
groups_base_info = {}
output_json = {}
#FIXME: 确定输出文件的文件名 以及放置位置
output_config_name = self.OUTPUT_CONFIG_PATH + "kylin-update-desktop-system.json"
#4、添加一些基础信息
groups_base_info.update({"package":"kylin-update-desktop-system"})
groups_base_info.update({"new_version":"33797.0001"})
groups_base_info.update({"name":{"zh_CN": "系统更新","en_US": "Kylin OS"}})
groups_base_info.update({"description":{"zh_CN": "Openkylin-系统更新包","en_US": "Openkylin-System Update Package"}})
groups_base_info.update({"icon":" "})
#添加读yaml文件
groups_base_info.update({"changelog":"Openkylin-系统更新包\n"})
#5、添加升级的内容
output_json.update(groups_base_info)
output_json.update({"upgrade_list":upgrade_pkgs_json})
output_json.update({"install_list":install_pkgs_json})
#6 产生JSON文件
with open(output_config_name, 'w', encoding='utf-8') as f:
json.dump(output_json, f, ensure_ascii=False, indent=4)
logging.info("Generate Jsonfile(%s) to complete... ",output_config_name)
def _rate_application_for_package(self, application, pkg):
score = 0
desktop_file = os.path.basename(application.get_filename())
application_id = os.path.splitext(desktop_file)[0]
if application.should_show():
score += 1
if application_id == pkg.name:
score += 5
return score
def _file_is_application(self, file_path):
# WARNING: This is called often if there's a lot of updates. A poor
# performing call here has a huge impact on the overall performance!
if not file_path.endswith(".desktop"):
# First the obvious case: If the path doesn't end in a .desktop
# extension, this isn't a desktop file.
return False
file_path = os.path.abspath(file_path)
for app_dir in self.application_dirs:
if file_path.startswith(app_dir):
return True
return False
def get_application_for_package(self, pkg):
desktop_files = []
rated_applications = []
for installed_file in pkg.installed_files:
if self._file_is_application(installed_file):
desktop_files.append(installed_file)
for desktop_file in desktop_files:
try:
application = Gio.DesktopAppInfo.new_from_filename(
desktop_file)
application.set_desktop_env(self.current_desktop)
except Exception as e:
logging.warning("Error loading .desktop file %s: %s" %
(desktop_file, e))
continue
score = self._rate_application_for_package(application, pkg)
if score > 0:
rated_applications.append((score, application))
rated_applications.sort(key=lambda app: app[0], reverse=True)
if len(rated_applications) > 0:
return rated_applications[0][1]
else:
return None
def _make_single_upgrade(self,cache,pkg_list):
for pkg in pkg_list:
zh_name = ''
base_info = {}
output_json = {}
output_config_name = self.OUTPUT_CONFIG_PATH + pkg + '.json'
pkg_cache = cache[pkg]
#获取包的软件名称,从主题中读取,只有可升级,是软件的包才可以读取
if pkg_cache.is_installed:
app = self.get_application_for_package(pkg_cache)
if app is not None:
zh_name = app.get_display_name()
pkgs_json = self._make_pkg_info_json(cache,[pkg])
en_name = getattr(pkg_cache.candidate, "summary", '')
description_str = getattr(pkg_cache.candidate, "description", '')
#4、添加一些基础信息
base_info.update({"package":pkg})
base_info.update({"cur_version":getattr(pkg_cache.installed, "version", '')})
base_info.update({"new_version":getattr(pkg_cache.candidate, "version", '')})
base_info.update({"name":{"zh_CN":zh_name,"en_US":en_name}})
base_info.update({"description":{"zh_CN":description_str,"en_US":description_str}})
base_info.update({"icon":''})
#5、添加升级的内容
output_json.update(base_info)
if pkg_cache.is_installed:
output_json.update({"upgrade_list":pkgs_json})
output_json.update({"install_list":{}})
else:
output_json.update({"upgrade_list":{}})
output_json.update({"install_list":pkgs_json})
#产生JSON文件
with open(output_config_name, 'w', encoding='utf-8') as f:
json.dump(output_json, f, ensure_ascii=False, indent=4)
logging.info("Generate Jsonfile(%s) to complete... ",output_config_name)
#6、保存单包版本号
self.upgrade_meta.versoin_pkgs['single_upgrade'].update({pkg_cache.name:getattr(pkg_cache.installed, "version", '')})
def _make_distupgrade(self,cache):
pkgs_upgrade = []
pkgs_install = []
if cache.get_changes():
cache.clear()
cache._depcache.upgrade(True)
#查找所有可升级的包
for pkg in cache:
try:
if pkg.marked_install:
pkgs_install.append(pkg.name)
elif pkg.marked_upgrade:
pkgs_upgrade.append(pkg.name)
except KeyError:
pass
return pkgs_install,pkgs_upgrade
def update_kylin(self,cache,important_data,is_openkylin = False):
pkgs_install = []
pkgs_upgrade = []
#查找所有可升级的包
if is_openkylin == True:
pkgs_install,pkgs_upgrade = self._make_distupgrade(cache)
else:
for pkg in cache:
if pkg.is_upgradable and pkg.is_installed:
pkgs_upgrade.append(pkg.name)
logging.info("System all upgradeable packages:upgrade:%d install:%d ",len(pkgs_upgrade),len(pkgs_install))
group_important_list,self.upgrade_meta.single_pkgs = self._make_important_list(cache,pkgs_upgrade,important_data)
#清空输出的目录
self._empty_output_dir()
#important_list 为空时此次不需要升级
if not group_important_list and not self.upgrade_meta.single_pkgs:
self.parent.dbusController.UpdateDetectFinished(True,[],'','')
return
#产生单包的JSON
self._make_single_upgrade(cache,self.upgrade_meta.single_pkgs)
#分组的包的JSON
self._make_groups_upgrade(cache,group_important_list,is_openkylin,pkgs_install,pkgs_upgrade)
self._make_autoupgrade_config(cache,self.upgrade_meta,self.upgrade_meta.adjust_pkgs)
self.parent.dbusController.UpdateDetectFinished(True,self.upgrade_meta.upgrade_groups + self.upgrade_meta.single_pkgs,'','')
return

View File

@ -0,0 +1,105 @@
#!/usr/bin/python3
# DistUpgradeConfigParser.py
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
from configparser import NoOptionError
from configparser import ConfigParser as SafeConfigParser
import os.path
import logging
class UpgradeConfig(SafeConfigParser):
def __init__(self, datadir="/var/lib/kylin-system-updater/", name="system-updater.conf",defaults_dir=None):
SafeConfigParser.__init__(self)
self.datadir = datadir
maincfg = os.path.join(datadir, name)
# defaults are read first
self.config_files = []
if defaults_dir:
self.config_files.append(os.path.join(datadir, defaults_dir))
# our config file
self.config_files += [maincfg]
self.read(self.config_files)
logging.info("Initialize Upgrade ConfigFile(%s) to success",str(self.config_files))
def optionxform(self, optionstr):
return optionstr
def reReadConfigFiles(self):
self.read(self.config_files)
def setValue(self, section, option, value=None,is_write = True):
if option != 'upgradelist':
logging.info("SetValue Section:%s Option:%s Value:%s",section, option, value)
try:
self.reReadConfigFiles()
self.set(section, option,value)
except Exception as e:
logging.error("Error: setValue section:%s option:%s value:%s",section, option, value)
logging.error(str(e))
return False
if is_write == True:
with open(self.config_files[-1], 'w+') as configfile:
self.write(configfile)
return True
def getWithDefault(self, section, option, default,re_read=False):
try:
if re_read == True:
self.reReadConfigFiles()
if type(default) == bool:
return self.getboolean(section, option)
elif type(default) == float:
return self.getfloat(section, option)
elif type(default) == int:
return self.getint(section, option)
return self.get(section, option)
except Exception as e:
logging.error(str(e))
return default
def getlist(self, section, option):
try:
tmp = self.get(section, option)
except Exception as e:
logging.error(str(e))
return []
items = [x.strip() for x in tmp.split(" ")]
if '' in items and len(items):
return []
return items
def setListValue(self, section, option, value=None,is_write = True):
tmp = str(value).replace('[', '').replace(']', '')
tmp = tmp.replace("'", '').replace(',', '')
try:
self.set(section, option,tmp)
except Exception as e:
logging.error("setListValue section:%s option:%s",section, option)
logging.error(str(e))
return
if is_write == True:
with open(self.config_files[-1], 'w+') as configfile:
self.write(configfile)
def getListFromFile(self, section, option):
try:
filename = self.get(section, option)
except NoOptionError:
return []
p = os.path.join(self.datadir, filename)
if not os.path.exists(p):
logging.error("getListFromFile: no '%s' found" % p)
with open(p) as f:
items = [x.strip() for x in f]
return [s for s in items if not s.startswith("#") and not s == ""]
if __name__ == "__main__":
# c = UpgradeConfig("/home/x/share/kylin-system-updater/backend/data/")
# print(c.setValue("SystemStatus", "abnormal_reboot", str(False)),True)
# print(c.getWithDefault("SystemStatus", "abnormal_reboot", False))
pass

View File

View File

@ -0,0 +1,169 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""enums - Enumerates for apt daemon dbus messages"""
__all__ = (
"ERROR_UPDATE_DEFAULT_FAILED",
"ERROR_UPDATE_SOURCE_FAILED","ERROR_NETWORK_FAILED","ERROR_NOT_GROUPS_CONFIG","ERROR_SOFTWARE_INDEX_RROKEN",
"ERROR_NOT_INIT_PACKAGESINFIO","ERROR_READ_IMPORTANTLIST_FAILED","ERROR_RESOLVER_FAILED","ERROR_NOT_UPGRADE_PACKAGES",
"ERROR_REMOVE_ESSENTIAL_PACKAGES","ERROR_NOT_DISK_SPACE","ERROR_NOT_CONFIGPKG_DEPENDENCIES","ERROR_NOT_SELFPKG_DEPENDENCIES",
"ERROR_NOT_FIX_SYSTEM","ERROR_READ_LOCAL_DEB","ERROR_LOCAL_DEB_FORMAT","ERROR_INSTALL_DEB_BASE","ERROR_LOAD_CONFIG_FAILED",
"ERROR_UPDATE_KEY_SIGNATURES","ERROR_UPDATE_NET_AUTHENTICATION","ERROR_UPDATE_NOTREAD_SOURCES","PRIORITY_UPGRADE_SUCCCESSED",
"ERROR_UPDATE_INVALID_TIME",
"get_error_description_from_enum", "get_error_string_from_enum", "get_source_name_from_enum", "get_caller_from_enum")
import gettext
gettext.bindtextdomain('kylin-system-updater', '/usr/share/locale')
gettext.textdomain('kylin-system-updater')
_ = gettext.gettext
PRIORITY_UPGRADE_SUCCCESSED = "priority-upgrade-successed"
#apt update阶段出现的错误解析
ERROR_UPDATE_DEFAULT_FAILED = "error-update-default-failed"
ERROR_UPDATE_KEY_SIGNATURES = "The following signatures"
ERROR_UPDATE_NET_AUTHENTICATION ="does the network require authentication?"
ERROR_UPDATE_NOTREAD_SOURCES = "The list of sources could not be read"
ERROR_UPDATE_INVALID_TIME = "(invalid for another"
ERROR_UPDATE_SOURCE_FAILED = "error-update-source-failed"
ERROR_NETWORK_FAILED = "error-network-failed"
ERROR_NOT_GROUPS_CONFIG = "error-not-groups-config"
ERROR_NOT_CONFIGPKG_DEPENDENCIES = "error-not-configpkg-dependencies"
ERROR_NOT_SELFPKG_DEPENDENCIES = "error-not-selfpkg-dependencies"
ERROR_NOT_FIX_SYSTEM = "error-not-fix-system"
ERROR_LOAD_CONFIG_FAILED = "error-load-config-failed"
#自己的
ERROR_SOFTWARE_INDEX_RROKEN = "error-software-index-broken"
ERROR_NOT_INIT_PACKAGESINFIO = "error-not-init-packagesinfo"
ERROR_READ_IMPORTANTLIST_FAILED = "error-read-importantlist-failed"
ERROR_RESOLVER_FAILED = "error-resolver-failed"
ERROR_NOT_UPGRADE_PACKAGES = "error-not-upgrade-packages"
ERROR_REMOVE_ESSENTIAL_PACKAGES = "error-remove-essential-packages"
ERROR_NOT_DISK_SPACE = "error-not-disk-space"
ERROR_READ_LOCAL_DEB = "error-read-local-deb"
ERROR_LOCAL_DEB_FORMAT = "error-local-deb-format"
ERROR_INSTALL_DEB_BASE = "error-install-deb-base"
_STRINGS_ERROR = {
PRIORITY_UPGRADE_SUCCCESSED: _("Update Manager upgrade is complete, please restart the setting panel before performing the system update."),
#update
ERROR_UPDATE_DEFAULT_FAILED: _("Check for update exceptions!"),
ERROR_UPDATE_SOURCE_FAILED: _("Check for update exceptions!"),
ERROR_NETWORK_FAILED: _("Network anomaly, can't check for updates!"),
ERROR_UPDATE_KEY_SIGNATURES: _("Check for update exceptions!"),
ERROR_READ_IMPORTANTLIST_FAILED: _("Check for update exceptions!"),
ERROR_SOFTWARE_INDEX_RROKEN: _("Check for update exceptions!"),
ERROR_NOT_INIT_PACKAGESINFIO: _("Check for update exceptions!"),
ERROR_NOT_FIX_SYSTEM: _("Check for update exceptions!"),
ERROR_LOAD_CONFIG_FAILED: _("Check for update exceptions!"),
#优先升级
ERROR_NOT_GROUPS_CONFIG: _("Upgrade configuration acquisition exception."),
ERROR_NOT_CONFIGPKG_DEPENDENCIES: _("Upgrade configuration acquisition exception."),
ERROR_NOT_SELFPKG_DEPENDENCIES: _("Priority upgrade status exception."),
#install
ERROR_RESOLVER_FAILED: _("Could not calculate the upgrade"),
ERROR_NOT_UPGRADE_PACKAGES: _("There is an exception in the update package."),
ERROR_REMOVE_ESSENTIAL_PACKAGES: _("There is an exception in the update package."),
ERROR_NOT_DISK_SPACE: _("Disk space is insufficient, please clean the disk and then upgrade"),
ERROR_READ_LOCAL_DEB:_(" "),
ERROR_LOCAL_DEB_FORMAT:_(" "),
ERROR_INSTALL_DEB_BASE:_(" ")}
_DESCS_ERROR = {
#update
ERROR_UPDATE_SOURCE_FAILED: _("Unable to access the source management server"),
ERROR_NETWORK_FAILED: _("Please check your network connection and retry."),
ERROR_UPDATE_KEY_SIGNATURES: _("Check your source public key signature"),
ERROR_UPDATE_NOTREAD_SOURCES: _("Please check your source list and retry."),
ERROR_UPDATE_INVALID_TIME: _("Please check the system time and synchronize the system time before updating."),
ERROR_UPDATE_NET_AUTHENTICATION: _("Check if your network requires authentication?"),
ERROR_NOT_GROUPS_CONFIG: _("Unable to get group configuration package, Please check if the configuration package exists in the software source repository."),
ERROR_NOT_INIT_PACKAGESINFIO: _("An unresolvable problem occurred while initializing the package."),
ERROR_SOFTWARE_INDEX_RROKEN: _("Software index is broken") + _("It is impossible to install or remove any software. "
"Please use the package manager \"Synaptic\" or run "
"\"sudo apt-get install -f\" in a terminal to fix "
"this issue at first."),
ERROR_READ_IMPORTANTLIST_FAILED: _("read important list failed"),
ERROR_NOT_CONFIGPKG_DEPENDENCIES: _("Unable to install group configuration package, Please check the configuration package related dependencies."),
ERROR_NOT_SELFPKG_DEPENDENCIES: _("Unable to perform priority upgrade, please check the dependency related to the priority upgrade package."),
ERROR_LOAD_CONFIG_FAILED: _("The system update configuration file is read abnormally, please check if the system update configuration file format is correct."),
ERROR_NOT_FIX_SYSTEM: _("The system APT environment is abnormal, please check the system APT environment."),
#install
ERROR_RESOLVER_FAILED: _("nothing"),
ERROR_NOT_UPGRADE_PACKAGES: _("This update cannot detect the upgradeable package."),
ERROR_REMOVE_ESSENTIAL_PACKAGES: _("You request the removal of a system-essential package."),
ERROR_NOT_DISK_SPACE: _("test"),
ERROR_READ_LOCAL_DEB:_("Deb format exception, read local deb file error."),
ERROR_LOCAL_DEB_FORMAT:_("Deb format exception, failed to parse package file."),
ERROR_INSTALL_DEB_BASE:_("Install deb error.")
}
#UPGRADE MONITOR STATUS
MONIT_DETECT = "step-updatedetect"
MONIT_DEPRESOLUT = "step-depresolution"
MONIT_DOWNLOAD = "step-downloading"
MONIT_INSTALL = "step-installing"
MONIT_FINISH = "step-finish"
MONIT_INSTALLDEB = "step-installdeb"
SOURCE_NAME = {
'kylin-installer':_("Kylin Installer"),
'kylin-uninstaller':_("Kylin Uninstaller"),
'kylin-background-upgrade':_("Kylin Background Upgrade"),
'kylin-software-center':_("Kylin Software Center"),
}
CALLER = {
'kylin-installer':"Kylin Installer",
'kylin-uninstaller':"Kylin Uninstaller",
'kylin-background-upgrade':"Kylin Background Upgrade",
'kylin-software-center':"Kylin Software Center",
}
def get_error_description_from_enum(enum):
"""Get a long description of an error.
:param enum: The transaction error enum, e.g. :data:`ERROR_NO_LOCK`.
:returns: The description string.
"""
try:
return _DESCS_ERROR[enum]
except KeyError:
return None
def get_error_string_from_enum(enum):
"""Get a short description of an error.
:param enum: The transaction error enum, e.g. :data:`ERROR_NO_LOCK`.
:returns: The description string.
"""
try:
return _STRINGS_ERROR[enum]
except KeyError:
return None
def get_source_name_from_enum(enum):
try:
return SOURCE_NAME[enum]
except KeyError:
return _("Kylin System Updater")
def get_caller_from_enum(enum):
try:
return CALLER[enum]
except KeyError:
return _("Kylin System Updater")
# vim:ts=4:sw=4:et

View File

@ -0,0 +1,65 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Exception classes"""
# __all__ = ("UpdateBaseError")
import logging
from selectors import EpollSelector
import sys
from .enums import *
PY3K = sys.version_info.major > 2
class UpdateBaseError(Exception):
"""Internal error if a transaction could not be processed successfully."""
_dbus_error_name = "org.debian.apt.TransactionFailed"
def __init__(self, code,header=None,desc=None,details="",*args):
if not args:
# Avoid string replacements if not used
details = details.replace("%", "%%")
args = tuple([_convert_unicode(arg) for arg in args])
details = _convert_unicode(details)
self.code = code
self.details = details
self.details_args = args
if header == None:
self.header = get_error_string_from_enum(self.code)
else:
self.header = header
if desc == None:
self.desc = get_error_description_from_enum(self.code)
else:
self.desc = desc
Exception.__init__(self, *args)
# AptDaemonError.__init__(self, "%s: %s" % (code, details % args))
def __unicode__(self):
return "%s" % \
(get_error_string_from_enum(self.code))
def __str__(self):
if PY3K:
return self.__unicode__()
else:
return self.__unicode__().encode("utf-8")
class UpdateProgressExit(Exception):
def __init__(self,*args):
Exception.__init__(self, *args)
logging.info("Update Progress wiil be Exit...")
def _convert_unicode(text, encoding="UTF-8"):
"""Always return an unicode."""
if PY3K and not isinstance(text, str):
text = str(text, encoding, errors="ignore")
elif not PY3K and not isinstance(text, unicode):
text = unicode(text, encoding, errors="ignore")
return text
# vim:ts=4:sw=4:et

View File

@ -0,0 +1,13 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""Main loop for aptdaemon."""
__all__ = ("mainloop", "get_main_loop")
from gi.repository import GLib
mainloop = GLib.MainLoop()
def get_main_loop():
"""Return the glib main loop as a singleton."""
return mainloop

View File

@ -0,0 +1,809 @@
# utils.py
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
#
# Copyright (c) 2004-2013 Canonical
#
# Authors: Michael Vogt <mvo@debian.org>
# Michael Terry <michael.terry@canonical.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
from __future__ import print_function
from gettext import gettext as _
from gettext import ngettext
from stat import (S_IMODE, ST_MODE, S_IXUSR)
from math import ceil
import apt
import dbus
import apt_pkg
apt_pkg.init_config()
import shutil
import locale
import logging
import re
import os
import subprocess
import sys
import time
import fcntl
from urllib.request import (
ProxyHandler,
Request,
build_opener,
install_opener,
urlopen,
)
import dbus
from urllib.parse import urlsplit
from copy import copy
import psutil
import ctypes
from ctypes import *
import struct
# 禁止关机锁文件路径
VERIFY_SO = "libkylin_signtool.so"
class ExecutionTime(object):
"""
Helper that can be used in with statements to have a simple
measure of the timing of a particular block of code, e.g.
with ExecutionTime("db flush"):
db.flush()
"""
def __init__(self, info=""):
self.info = info
def __enter__(self):
self.now = time.time()
def __exit__(self, type, value, stack):
print("%s: %s" % (self.info, time.time() - self.now))
def get_string_with_no_auth_from_source_entry(entry):
tmp = copy(entry)
url_parts = urlsplit(tmp.uri)
if url_parts.username:
tmp.uri = tmp.uri.replace(url_parts.username, "hidden-u")
if url_parts.password:
tmp.uri = tmp.uri.replace(url_parts.password, "hidden-p")
return str(tmp)
def is_unity_running():
""" return True if Unity is currently running """
unity_running = False
try:
import dbus
bus = dbus.SessionBus()
unity_running = bus.name_has_owner("com.canonical.Unity")
except Exception:
logging.exception("could not check for Unity dbus service")
return unity_running
def is_child_of_process_name(processname, pid=None):
if not pid:
pid = os.getpid()
while pid > 0:
stat_file = "/proc/%s/stat" % pid
with open(stat_file) as stat_f:
stat = stat_f.read()
# extract command (inside ())
command = stat.partition("(")[2].rpartition(")")[0]
if command == processname:
return True
# get parent (second to the right of command) and check that next
pid = int(stat.rpartition(")")[2].split()[1])
return False
def inside_chroot():
""" returns True if we are inside a chroot
"""
# if there is no proc or no pid 1 we are very likely inside a chroot
if not os.path.exists("/proc") or not os.path.exists("/proc/1"):
return True
# if the inode is differnt for pid 1 "/" and our "/"
return os.stat("/") != os.stat("/proc/1/root")
def wrap(t, width=70, subsequent_indent=""):
""" helpers inspired after textwrap - unfortunately
we can not use textwrap directly because it break
packagenames with "-" in them into new lines
"""
out = ""
for s in t.split():
if (len(out) - out.rfind("\n")) + len(s) > width:
out += "\n" + subsequent_indent
out += s + " "
return out
def twrap(s, **kwargs):
msg = ""
paras = s.split("\n")
for par in paras:
s = wrap(par, **kwargs)
msg += s + "\n"
return msg
def lsmod():
" return list of loaded modules (or [] if lsmod is not found) "
modules = []
# FIXME raise?
if not os.path.exists("/sbin/lsmod"):
return []
p = subprocess.Popen(["/sbin/lsmod"], stdout=subprocess.PIPE,
universal_newlines=True)
lines = p.communicate()[0].split("\n")
# remove heading line: "Modules Size Used by"
del lines[0]
# add lines to list, skip empty lines
for line in lines:
if line:
modules.append(line.split()[0])
return modules
def check_and_fix_xbit(path):
" check if a given binary has the executable bit and if not, add it"
if not os.path.exists(path):
return
mode = S_IMODE(os.stat(path)[ST_MODE])
if not ((mode & S_IXUSR) == S_IXUSR):
os.chmod(path, mode | S_IXUSR)
def country_mirror():
" helper to get the country mirror from the current locale "
# special cases go here
lang_mirror = {'c': ''}
# no lang, no mirror
if 'LANG' not in os.environ:
return ''
lang = os.environ['LANG'].lower()
# check if it is a special case
if lang[:5] in lang_mirror:
return lang_mirror[lang[:5]]
# now check for the most comon form (en_US.UTF-8)
if "_" in lang:
country = lang.split(".")[0].split("_")[1]
if "@" in country:
country = country.split("@")[0]
return country + "."
else:
return lang[:2] + "."
return ''
def get_dist():
" return the codename of the current runing distro "
# then check the real one
from subprocess import Popen, PIPE
p = Popen(["lsb_release", "-i", "-s"], stdout=PIPE,
universal_newlines=True)
res = p.wait()
if res != 0:
sys.stderr.write("lsb_release returned exitcode: %i\n" % res)
return "unknown distribution"
dist = p.stdout.readline().strip()
p.stdout.close()
return dist
def get_dist_version():
" return the version of the current running distro "
# then check the real one
from subprocess import Popen, PIPE
p = Popen(["lsb_release", "-r", "-s"], stdout=PIPE,
universal_newlines=True)
res = p.wait()
if res != 0:
sys.stderr.write("lsb_release returned exitcode: %i\n" % res)
return "unknown distribution"
desc = p.stdout.readline().strip()
p.stdout.close()
return desc
class HeadRequest(Request):
def get_method(self):
return "HEAD"
def url_downloadable(uri, debug_func=None):
"""
helper that checks if the given uri exists and is downloadable
(supports optional debug_func function handler to support
e.g. logging)
Supports http (via HEAD) and ftp (via size request)
"""
if not debug_func:
lambda x: True
debug_func("url_downloadable: %s" % uri)
(scheme, netloc, path, querry, fragment) = urlsplit(uri)
debug_func("s='%s' n='%s' p='%s' q='%s' f='%s'" % (scheme, netloc, path,
querry, fragment))
if scheme in ("http", "https"):
try:
http_file = urlopen(HeadRequest(uri))
http_file.close()
if http_file.code == 200:
return True
return False
except Exception as e:
debug_func("error from httplib: '%s'" % e)
return False
elif scheme == "ftp":
import ftplib
try:
f = ftplib.FTP(netloc)
f.login()
f.cwd(os.path.dirname(path))
size = f.size(os.path.basename(path))
f.quit()
if debug_func:
debug_func("ftplib.size() returned: %s" % size)
if size != 0:
return True
except Exception as e:
if debug_func:
debug_func("error from ftplib: '%s'" % e)
return False
return False
def is_chinese(string):
"""
检查整个字符串是否包含中文
:param string: 需要检查的字符串
:return: bool
"""
for ch in string:
if u'\u4e00' <= ch <= u'\u9fff':
return True
return False
def init_proxy(gsettings=None):
""" init proxy settings
* use apt.conf http proxy if present,
* otherwise look into synaptics config file,
* otherwise the default behavior will use http_proxy environment
if present
"""
SYNAPTIC_CONF_FILE = "/root/.synaptic/synaptic.conf"
proxies = {}
# generic apt config wins
if apt_pkg.config.find("Acquire::http::Proxy") != '':
proxies["http"] = apt_pkg.config.find("Acquire::http::Proxy")
# then synaptic
elif os.path.exists(SYNAPTIC_CONF_FILE):
cnf = apt_pkg.Configuration()
apt_pkg.read_config_file(cnf, SYNAPTIC_CONF_FILE)
use_proxy = cnf.find_b("Synaptic::useProxy", False)
if use_proxy:
proxy_host = cnf.find("Synaptic::httpProxy")
proxy_port = str(cnf.find_i("Synaptic::httpProxyPort"))
if proxy_host and proxy_port:
proxies["http"] = "http://%s:%s/" % (proxy_host, proxy_port)
if apt_pkg.config.find("Acquire::https::Proxy") != '':
proxies["https"] = apt_pkg.config.find("Acquire::https::Proxy")
elif "http" in proxies:
proxies["https"] = proxies["http"]
# if we have a proxy, set it
if proxies:
# basic verification
for proxy in proxies.values():
if not re.match("https?://\\w+", proxy):
print("proxy '%s' looks invalid" % proxy, file=sys.stderr)
return
proxy_support = ProxyHandler(proxies)
opener = build_opener(proxy_support)
install_opener(opener)
if "http" in proxies:
os.putenv("http_proxy", proxies["http"])
if "https" in proxies:
os.putenv("https_proxy", proxies["https"])
return proxies
def on_battery():
"""
Check via dbus if the system is running on battery.
This function is using UPower per default, if UPower is not
available it falls-back to DeviceKit.Power.
"""
try:
import dbus
bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM)
try:
devobj = bus.get_object('org.freedesktop.UPower',
'/org/freedesktop/UPower')
dev = dbus.Interface(devobj, 'org.freedesktop.DBus.Properties')
return dev.Get('org.freedesktop.UPower', 'OnBattery')
except dbus.exceptions.DBusException as e:
error_unknown = 'org.freedesktop.DBus.Error.ServiceUnknown'
if e._dbus_error_name != error_unknown:
raise
devobj = bus.get_object('org.freedesktop.DeviceKit.Power',
'/org/freedesktop/DeviceKit/Power')
dev = dbus.Interface(devobj, "org.freedesktop.DBus.Properties")
return dev.Get("org.freedesktop.DeviceKit.Power", "on_battery")
except Exception:
#import sys
#print("on_battery returned error: ", e, file=sys.stderr)
return False
def str_to_bool(str):
if str == "0" or str.upper() == "FALSE":
return False
return True
def get_lang():
import logging
try:
(locale_s, encoding) = locale.getdefaultlocale()
return locale_s
except Exception:
logging.exception("gedefaultlocale() failed")
return None
def get_ubuntu_flavor(cache=None):
""" try to guess the flavor based on the running desktop """
# this will (of course) not work in a server environment,
# but the main use case for this is to show the right
# release notes.
pkg = get_ubuntu_flavor_package(cache=cache)
return pkg.split('-', 1)[0]
# def _load_meta_pkg_list():
# # This could potentially introduce a circular dependency, but the config
# # parser logic is simple, and doesn't rely on any UpdateManager code.
# from DistUpgrade.DistUpgradeConfigParser import DistUpgradeConfig
# parser = DistUpgradeConfig('/usr/share/ubuntu-release-upgrader')
# return parser.getlist('Distro', 'MetaPkgs')
def get_ubuntu_flavor_package(cache=None):
""" try to guess the flavor metapackage based on the running desktop """
# From spec, first if ubuntu-desktop is installed, use that.
# Second, grab first installed one from DistUpgrade.cfg.
# Lastly, fallback to ubuntu-desktop again.
meta_pkgs = ['ubuntu-desktop']
# try:
# meta_pkgs.extend(sorted(_load_meta_pkg_list()))
# except Exception as e:
# print('Could not load list of meta packages:', e)
if cache is None:
cache = apt.Cache()
for meta_pkg in meta_pkgs:
cache_pkg = cache[meta_pkg] if meta_pkg in cache else None
if cache_pkg and cache_pkg.is_installed:
return meta_pkg
return 'ubuntu-desktop'
def get_ubuntu_flavor_name(cache=None):
""" try to guess the flavor name based on the running desktop """
pkg = get_ubuntu_flavor_package(cache=cache)
lookup = {'ubuntustudio-desktop': 'Ubuntu Studio'}
if pkg in lookup:
return lookup[pkg]
elif pkg.endswith('-desktop'):
return capitalize_first_word(pkg.rsplit('-desktop', 1)[0])
elif pkg.endswith('-netbook'):
return capitalize_first_word(pkg.rsplit('-netbook', 1)[0])
else:
return 'Ubuntu'
# Unused by update-manager, but still used by ubuntu-release-upgrader
def error(parent, summary, message):
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk
d = Gtk.MessageDialog(parent=parent,
flags=Gtk.DialogFlags.MODAL,
type=Gtk.MessageType.ERROR,
buttons=Gtk.ButtonsType.CLOSE)
d.set_markup("<big><b>%s</b></big>\n\n%s" % (summary, message))
d.realize()
d.get_window().set_functions(Gdk.WMFunction.MOVE)
d.set_title("")
d.run()
d.destroy()
return False
def _split_package_id(package):
"""Return the name, the version number and the release of the
specified package."""
if ":" in package:
name, arch = package.split(":", 1)
# release = None
# elif "/" in package:
# name, release = package.split("/", 1)
# version = None
else:
name = package
arch = None
return name, arch
def get_config_patch():
#检查组配置文件当前的目录
NOW_UPDATE_CONFIG = '/usr/share/kylin-update-desktop-config/config/'
OLD_UPDATE_CONFIG = '/usr/share/kylin-update-desktop-config/data/'
if os.path.exists(NOW_UPDATE_CONFIG):
return NOW_UPDATE_CONFIG
elif os.path.exists(OLD_UPDATE_CONFIG):
return NOW_UPDATE_CONFIG
else:
return NOW_UPDATE_CONFIG
def get_broken_details(cache,now=True):
"""Return a message which provides debugging information about
broken packages.
This method is basically a Python implementation of apt-get.cc's
ShowBroken.
Keyword arguments:
trans -- the corresponding transaction
#表示当前系统apt已经破损的话是True 如果是安装软件包讲导致破损的话是False
now -- if we check currently broken dependecies or the installation
candidate
"""
msg = _("The following packages have unmet dependencies:")
msg += "\n\n"
for pkg in cache:
if not ((now and pkg.is_now_broken) or
(not now and pkg.is_inst_broken)):
continue
msg += "%s: " % pkg.name
#获取出现问题的包的版本
if now:
version = pkg.installed
else:
version = pkg.candidate
indent = " " * (len(pkg.name) + 2)
dep_msg = ""
#拿取依赖关系
for dep in version.dependencies:
or_msg = ""
for base_dep in dep.or_dependencies:
if or_msg:
or_msg += "or\n"
or_msg += indent
# Check if it's an important dependency
# See apt-pkg/depcache.cc IsImportantDep
# See apt-pkg/pkgcache.cc IsCritical()
if not (base_dep.rawtype in ["Depends","PreDepends",
"Obsoletes", "DpkgBreaks",
"Conflicts"] or
(apt_pkg.config.find_b("APT::Install-Recommends",
False) and
base_dep.rawtype == "Recommends") or
(apt_pkg.config.find_b("APT::Install-Suggests",
False) and
base_dep.rawtype == "Suggests")):
continue
# Get the version of the target package
try:
pkg_name,pkg_arch = _split_package_id(base_dep.name)
pkg_dep = cache[pkg_name]
except KeyError:
dep_version = None
else:
if now:
dep_version = pkg_dep.installed
else:
dep_version = pkg_dep.candidate
# We only want to display dependencies which cannot
# be satisfied
if dep_version and not apt_pkg.check_dep(base_dep.version,
base_dep.relation,
dep_version.version):
break
or_msg = "%s: %s " % (base_dep.rawtype, base_dep.name)
if base_dep.version:
or_msg += "(%s %s) " % (base_dep.relation,
base_dep.version)
if cache.is_virtual_package(base_dep.name):
or_msg += _("but it is a virtual package")
#表示这个依赖包没有安装 源里面没有
elif not dep_version:
if now:
or_msg += _("but it is not installed")
else:
#要依赖包 不存在时走此
or_msg += _("but it is not going to "
"be installed")
#表示安装的版本与需要的版本不一致 在这个地方来再进行递归安装判断 具体那些包造成的不能安装
elif now:
# TRANSLATORS: %s is a version number
or_msg += (_("but %s is installed") %
dep_version.version)
else:
#安装之后出现破损的话走这里
# TRANSLATORS: %s is a version number
or_msg += (_("but %s is to be installed") %
dep_version.version)
else:
# Only append an or-group if at least one of the
# dependencies cannot be satisfied
if dep_msg:
dep_msg += indent
dep_msg += or_msg
dep_msg += "\n"
msg += dep_msg
return msg
def humanize_size(bytes):
"""
Convert a given size in bytes to a nicer better readable unit
"""
if bytes < 1000 * 1000:
# to have 0 for 0 bytes, 1 for 0-1000 bytes and for 1 and above
# round up
size_in_kb = int(ceil(bytes / float(1000)))
# TRANSLATORS: download size of small updates, e.g. "250 kB"
return ngettext("%(size).0f kB", "%(size).0f kB", size_in_kb) % {
"size": size_in_kb}
else:
# TRANSLATORS: download size of updates, e.g. "2.3 MB"
return locale.format_string(_("%.1f MB"), bytes / 1000.0 / 1000.0)
def get_arch():
return apt_pkg.config.find("APT::Architecture")
def is_port_already_listening(port):
""" check if the current system is listening on the given tcp port """
# index in the line
INDEX_LOCAL_ADDR = 1
#INDEX_REMOTE_ADDR = 2
INDEX_STATE = 3
# state (st) that we care about
STATE_LISTENING = '0A'
# read the data
with open("/proc/net/tcp") as net_tcp:
for line in net_tcp.readlines():
line = line.strip()
if not line:
continue
# split, values are:
# sl local_address rem_address st tx_queue rx_queue tr
# tm->when retrnsmt uid timeout inode
values = line.split()
state = values[INDEX_STATE]
if state != STATE_LISTENING:
continue
local_port_str = values[INDEX_LOCAL_ADDR].split(":")[1]
local_port = int(local_port_str, 16)
if local_port == port:
return True
return False
def iptables_active():
""" Return True if iptables is active """
# FIXME: is there a better way?
iptables_empty = """Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
"""
if os.getuid() != 0:
raise OSError("Need root to check the iptables state")
if not os.path.exists("/sbin/iptables"):
return False
out = subprocess.Popen(["iptables", "-nL"],
stdout=subprocess.PIPE,
universal_newlines=True).communicate()[0]
if out == iptables_empty:
return False
return True
def capitalize_first_word(string):
""" this uppercases the first word's first letter
"""
if len(string) > 1 and string[0].isalpha() and not string[0].isupper():
return string[0].capitalize() + string[1:]
return string
def get_package_label(pkg):
""" this takes a package synopsis and uppercases the first word's
first letter
"""
name = getattr(pkg.candidate, "summary", "")
return capitalize_first_word(name)
# 查看uu进程是否需要kill
def kill_process(path):
try:
# 判断文件是否存在
if (os.path.exists(path)):
with open(path, "r") as f:
pid = f.read()
if len(pid) == 0:
return False
logging.info("Unattended Upgrades run path: %d. ", int(pid))
os.kill(int(pid), 9)
logging.info('Unattended Upgrades is running, kill pid: %d. ', int(pid))
else:
logging.warning('%s is not exist.', path)
except Exception as e:
logging.error(e)
return False
return True
def whether_to_quit_uu():
osreleasedict={}
try:
with open('/etc/os-release') as f:
lines = f.readlines()
for line in lines:
ls = line.strip().split('=',1)
osreleasedict.update({ls[0]:ls[1].strip('"')})
except Exception as e:
pass
if 'SUB_PROJECT_CODENAME' not in osreleasedict.keys():
osreleasedict.update({'SUB_PROJECT_CODENAME':''})
if 'PROJECT_CODENAME' in osreleasedict:
if osreleasedict['PROJECT_CODENAME']=='V10SP1-edu':
if 'SUB_PROJECT_CODENAME' in osreleasedict:
if osreleasedict['SUB_PROJECT_CODENAME']=='mavis':
return False
else:
logging.info("SUB_PROJECT_CODENAME != mavis")
else:
logging.info("no SUB_PROJECT_CODENAME")
else:
logging.info("PROJECT_CODENAME != V10SP1-edu")
else:
logging.info("no PROJECT_CODENAME")
return True
def get_proc_from_dbus_name(dbus_name, bus=None):
"""Return a deferred that gets the id of process owning the given
system D-Bus name.
"""
if not bus:
bus = dbus.SystemBus()
bus_obj = bus.get_object("org.freedesktop.DBus",
"/org/freedesktop/DBus/Bus")
pid = bus_obj.GetConnectionUnixProcessID(dbus_name,
dbus_interface="org.freedesktop.DBus")
proc = psutil.Process(int(pid))
# with open("/proc/%s/status" % pid) as process:
# values = [v for v in process.readlines() if v.startswith("Uid:")]
# uid = int(values[0].split()[1])
# #检查是否root用户执行
# if uid == 0:
# return "root"
return proc.name()
def deb_verify(deb_path, _isinstall = False):
logging.info("Verify pkg:%s.",deb_path)
_deb_path = str(deb_path)
try:
# # 加载验证签名库 , 验签接口暂时无法调用
# args = ["dpkg-architecture", "-qDEB_TARGET_MULTIARCH"]
# ret = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
# verifyso_path = os.path.join("/usr/lib/",str(ret.stdout).strip(),VERIFY_SO)
# logging.info("Load verify interface:%s.",verifyso_path)
# verifyso = ctypes.CDLL(verifyso_path)
# #环境初始化
# ret = verifyso.SOF_Initialize(ctx_obj)
# if (ret) :
# logging.info("SOF_InitializeEx error!")
# return 2
# if os.path.isfile(_deb_path):
# ret = verifyso.BJCA_dodebverify(None, bytes(_deb_path, encoding='utf8'), _isinstall)
if not os.path.isfile("/usr/bin/kylinsigntool"):
logging.error("SOF_InitializeEx error!")
return 1
args = ["/usr/bin/kylinsigntool", "-v", _deb_path]
ret = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
if "Signature Verified failed" in str(ret.stdout).strip() or "签名验证失败" in str(ret.stdout).strip():
logging.info("Signature Verified failed!")
return 2
elif "Signature Verified Ok" in str(ret.stdout).strip() or "签名验证成功" in str(ret.stdout).strip():
logging.info("Signature Verified Ok!")
return 0
except Exception as e:
logging.error(e)
return 3
def PolicyKit_Authority(details = '', sender = None):
_allow_kylinsign = False
_verify_kylinsign = False
try:
#获取未知来源应用安装策略Unknown sources apply installation policies
inst_policies_path = "/etc/dpkg/dpkg.cfg"
if os.path.isfile(inst_policies_path):
with open(inst_policies_path, "r") as f:
lines = f.readlines()
for line in lines:
if "allow-kylinsign" in line:
_allow_kylinsign = True
if "verify-kylinsign" in line:
_verify_kylinsign = True
if _allow_kylinsign == True and _verify_kylinsign == False: #策略: 阻止
logging.debug("unknown sources apply installation policies: deter")
return False,_("The package is unsigned, refuses to install.")
elif _allow_kylinsign == True and _verify_kylinsign == True: #策略: 警告
logging.debug("unknown sources apply installation policies: warning")
elif _allow_kylinsign == False and _verify_kylinsign == False: #策略: 关闭
logging.debug("unknown sources apply installation policies: close")
else:
logging.warning("Unknown sources apply installation policies get failed.")
#用户鉴权
details = {'polkit.message':details}
cancel_id = ''
action = "cn.kylinos.KylinSystemUpdater.action"
kit = dbus.SystemBus().get_object('org.freedesktop.PolicyKit1', '/org/freedesktop/PolicyKit1/Authority')
kit = dbus.Interface(kit, 'org.freedesktop.PolicyKit1.Authority')
(granted, notused , details) = kit.CheckAuthorization(
('system-bus-name', {'name': sender}),
action, details, dbus.UInt32(1),cancel_id, timeout=60*60*24*7)
if granted:
logging.info("Authentication success ...")
return True,_("Authentication success.")
else:
logging.info("Authentication failure ...")
return False,_("Authentication failure.")
except Exception as e:
logging.error(e)
return False,str(e)
if __name__ == "__main__":
#print(mirror_from_sources_list())
#print(on_battery())
#print(inside_chroot())
#print(iptables_active())
error(None, "bar", "baz")

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,101 @@
# UpdateManager.py
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
import os
import sys
import time
import dbus
import logging
import dbus.service
import traceback
from gettext import gettext as _
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
DBusGMainLoop(set_as_default=True)
from .UpgradeStrategiesDbus import UpgradeStrategiesDbusController,UPDATER_DBUS_INTERFACE,UPDATER_DBUS_PATH,UPDATER_DBUS_SERVICE
from .Core.Database import Sqlite3Server
from .Core.loop import mainloop
from SystemUpdater.Core.UpdaterConfigParser import UpgradeConfig
STRATEGY_IDLE_INTERVAL = 2*60
STRATEGY_IDLE_TIMEOUT = 6*60
class UpgradeStrategies():
def __init__(self,options):
try:
self.options = options
#dbus
self.dbusController = self._setup_dbus()
#config
self.uuconfigs = UpgradeConfig(datadir = "/var/lib/unattended-upgrades/", name = "unattended-upgrades-policy.conf")
self.sqlite3_server = Sqlite3Server(self)
#策略配置接口的超时退出机制
self.strategy_timestamp = 0
GLib.timeout_add_seconds(STRATEGY_IDLE_INTERVAL,
self._check_strategy_inactivity)
except Exception as e:
logging.error(e)
traceback.print_exc()
def run(self):
"""Start the daemon and listen for calls."""
logging.info("Waiting for calls...")
try:
mainloop.run()
except KeyboardInterrupt:
self.dbusController.Quit(None)
def _setup_dbus(self):
# check if there is another g-a-i already and if not setup one
# listening on dbus
bus = dbus.SystemBus()
try:
bus_name = dbus.service.BusName(UPDATER_DBUS_SERVICE,
bus,
do_not_queue=True)
logging.info("Initiate dbus success ...")
return UpgradeStrategiesDbusController(self, bus_name)
except dbus.exceptions.NameExistsException:
if self.options.replace is False:
logging.critical("Another daemon is already running")
sys.exit(1)
logging.warning("Replacing already running daemon")
retry_reboot_times = 0
the_other_guy = bus.get_object(UPDATER_DBUS_SERVICE,
UPDATER_DBUS_PATH)
the_other_guy.Quit(dbus_interface=UPDATER_DBUS_INTERFACE,
timeout=300)
time.sleep(1)
while True:
retry_reboot_times = retry_reboot_times + 1
#当重试次数超过5次时退出程序
if retry_reboot_times > 5:
logging.critical("Reboot backend is Failed...")
sys.exit(1)
try:
bus_name = dbus.service.BusName(UPDATER_DBUS_SERVICE,
bus,
do_not_queue=True)
logging.warning("Replacing already running daemon to Success...")
return UpgradeStrategiesDbusController(self, bus_name)
except dbus.exceptions.NameExistsException:
the_other_guy = bus.get_object(UPDATER_DBUS_SERVICE,
UPDATER_DBUS_PATH)
the_other_guy.Quit(dbus_interface=UPDATER_DBUS_INTERFACE,
timeout=300)
logging.error("Dbus has not withdrawn and retry reboot times:%d...",retry_reboot_times)
time.sleep(1)
def _check_strategy_inactivity(self):
logging.info("Checking for inactivity in Strategies daemon ...")
timestamp = self.strategy_timestamp
if timestamp == 0:
self.strategy_timestamp = time.time()
return True
#超时退出
if self.strategy_timestamp != 0 and time.time() - self.strategy_timestamp > STRATEGY_IDLE_TIMEOUT:
logging.warning("Quitting due to inactivity")
self.dbusController.Quit(None)
return False
return True

View File

@ -0,0 +1,604 @@
#!/usr/bin/python3
import os
import dbus
import dbus.service
import logging
import subprocess
from gettext import gettext as _
from .Core.loop import mainloop
from SystemUpdater.Core.utils import get_proc_from_dbus_name
UPDATER_DBUS_INTERFACE = 'com.kylin.UpgradeStrategies.interface'
UPDATER_DBUS_PATH = '/com/kylin/UpgradeStrategies'
UPDATER_DBUS_SERVICE = 'com.kylin.UpgradeStrategies'
RUN_UNATTENDED_UPGRADE = '/var/run/unattended-upgrades.pid'
SYSTEM_VERSION = '/etc/kylin-version/kylin-system-version.conf'
#颜色设置
COLORLOG_SUFFIX = "\033[0m"
# Define some foreground colors
BLACK = 30
RED = 31
GREEN = 32
YELLOW = 33
BLUE = 34
MAGENTA = 35
CYAN = 36
WHITE = 37
#字体颜色
FRONT_COLOR_SEQ = "\033[1;%dm"
#背景颜色
BACK_COLOR_SEQ = "\033[%d;1m"
COLORLOG_PREFIX = FRONT_COLOR_SEQ % GREEN
COLORMETHOR_PREFIX = FRONT_COLOR_SEQ % CYAN
UU_UPGRADE_MODE_AUTOMATIC_DOWNLOAD = 0
UU_UPGRADE_MODE_MANUAL = 1
UU_UPGRADE_MODE_AUTOMATIC_INSTALL = 2
UU_UPGRADE_MODE_BEFORE_SHUTDOWN = 3
#dbus 建立
class UpgradeStrategiesDbusController(dbus.service.Object):
""" this is a helper to provide the UpdateManagerIFace """
P2P_DEDAULT_PATH = "/etc/default/apt-p2p"
RETURN_SUCCESS_CODE = 0
RETURN_SUCCESS_DESC = ""
RETURN_UNKNOWN_CODE = -1
RETURN_UNKNOWN_DESC = ""
def __init__(self, parent, bus_name,
object_path=UPDATER_DBUS_PATH):
dbus.service.Object.__init__(self, bus_name, object_path)
self.parent = parent
self.bus = dbus.SystemBus()
self.transaction = None
def __check_change__(self, _config = None, _section = "", _option = "", _value = ""):
if _config == None:
return False
if _value == _config.getWithDefault(_section,_option,_value," "):
return True
return False
@dbus.service.method(UPDATER_DBUS_INTERFACE,
in_signature="", out_signature="",
sender_keyword="caller_name")
def Quit(self, caller_name):
"""Request a shutdown of the daemon."""
#如果在下载就请求 取消
logging.info("Quitting was requested")
logging.debug("Quitting main loop...")
mainloop.quit()
logging.debug("Exit")
## dbus接口: 开启或关闭预下载功能
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='s', out_signature='is',sender_keyword='sender')
def ChangingP2PStatus(self,_status,sender = None):
status = str(_status)
sender_name = get_proc_from_dbus_name(sender)
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' ChangingP2PStatus, _status = %s , sender name: %s',status,sender_name)
if os.path.exists(self.P2P_DEDAULT_PATH):
if status == "enable":
with open(self.P2P_DEDAULT_PATH, 'w+') as configfile:
configfile.write("#enable=true\n")
#第一次进行检查是否已经开启
args = ["systemctl","is-enabled","apt-p2p.service"]
p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
if p.returncode != 0:
logging.info("Apt-p2p service is not runing and will be enable...")
#第二次进行重启
args = ["systemctl","enable","apt-p2p.service"]
p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
if p.returncode == 0:
logging.info("Service Enable Execute successfully")
#第三次进行重启
args = ["systemctl","restart","apt-p2p.service"]
p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
if p.returncode == 0:
logging.info("Restart Execute successfully")
return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC
else:
logging.error(str(p.stdout))
logging.error("Failed to execute reboot")
return self.RETURN_UNKNOWN_CODE,str(p.stdout)
else:
logging.error(str(p.stdout))
logging.error("Failed to execute enable")
return self.RETURN_UNKNOWN_CODE,str(p.stdout)
else:
logging.info("Apt-p2p service has been enabled and not need to reabled...")
return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC
elif status == "disable":
with open(self.P2P_DEDAULT_PATH, 'w+') as configfile:
configfile.write("enable=false\n")
args = ["systemctl","is-enabled","apt-p2p.service"]
p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
if p.returncode == 0:
logging.info("Apt-p2p service is runing and will be disable...")
args = ["systemctl","disable","apt-p2p.service"]
p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
if p.returncode == 0:
logging.info("Service disable Execute successfully")
args = ["systemctl","stop","apt-p2p.service"]
p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
if p.returncode == 0:
logging.info("Stop Execute successfully")
return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC
else:
logging.error(str(p.stdout))
logging.error("Failed to execute Stop")
return self.RETURN_UNKNOWN_CODE,str(p.stdout)
else:
logging.error(str(p.stdout))
logging.error("Failed to execute disable")
return self.RETURN_UNKNOWN_CODE,str(p.stdout)
else:
logging.info("Apt-p2p service has been disabled and not need to redisabled...")
return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC
else:
logging.waring("error: input value _status=%s",status)
else:
logging.waring("apt-p2p function is not install...")
## dbus接口: 开启或关闭预下载功能
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='bs', out_signature='b',sender_keyword='sender')
def SetPreDownloadState(self, _state, _time, sender = None):
state = bool(_state)
time = str(_time)
sender_name = get_proc_from_dbus_name(sender)
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetPreDownloadState, state is %r, time: %s, sender name: %s .',state,time,sender_name)
try:
if state:
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "preDownload", "on"):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "preDownload", "on", True)
self.PropertyChanged("preDownload","on")
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "preDownloadTime", time):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "preDownloadTime", time, True)
self.PropertyChanged("preDownloadTime",time)
else:
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "preDownload", "off"):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "preDownload", "off", True)
self.PropertyChanged("preDownload","off")
except Exception as e:
logging.error(str(e))
return False
return True
## 设置更新周期
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='i', out_signature='b',sender_keyword='sender')
def SetUpdateDays(self, days, sender = None):
_days = int(days)
sender_name = get_proc_from_dbus_name(sender)
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetUpdateDays, days: %d , sender:%s .'\
,_days,sender_name)
try:
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "updateDays", _days):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "updateDays", str(_days), True)
self.PropertyChanged("updateDays",str(_days))
except Exception as e:
logging.error(str(e))
return False
return True
# 设置自动更新时间
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='s', out_signature='bs',sender_keyword='sender')
def SetAutoUpgradeRandomRange(self,randomRange,sender=None):
_randomRange = str(randomRange)
sender_name = get_proc_from_dbus_name(sender)
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetAutoUpgradeRandomRange will be set value %s, sender: %s .',\
_randomRange,sender_name)
try:
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "randomRange", _randomRange):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "randomRange", _randomRange, True)
self.PropertyChanged("randomRange",_randomRange)
except Exception as e:
logging.error(str(e))
return True,"success"
## 设置是否开启自动重启,以及设置自动重启的时间
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='bs', out_signature='b',sender_keyword='sender')
def SetAutomaticReboot(self, status, reboot_time, sender = None):
_state = bool(status)
_reboot_time = str(reboot_time)
sender_name = get_proc_from_dbus_name(sender)
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetAutomaticReboot, status is %r, reboot_time: %s, sender name: %s .'\
,_state,_reboot_time,sender_name)
try:
if _state:
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "automaticReboot", "on"):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "automaticReboot", "on", True)
self.PropertyChanged("automaticReboot","on")
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "automaticRebootTime", _reboot_time):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "automaticRebootTime", _reboot_time, True)
self.PropertyChanged("automaticRebootTime",_reboot_time)
else:
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "automaticReboot", "off"):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "automaticReboot", "off", True)
self.PropertyChanged("automaticReboot","off")
except Exception as e:
logging.error(str(e))
return False
return True
## dbus接口: 开启关闭自动更新功能
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='b', out_signature='b')
def SetAutoUpgradeState(self, _state):
state = bool(_state)
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetAutoUpgradeState, state is %r ...',state)
try:
if state:
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "autoUpgradeState", "on"):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "autoUpgradeState", "on", True)
self.parent.sqlite3_server.insert_into_display("autoupdate_allow", "true")
self.PropertyChanged("autoUpgradeState","on")
self.ButtonStatusChange("autoUpgradeStatus", "true")
else :
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "autoUpgradeState", "off"):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "autoUpgradeState", "off", True)
self.parent.sqlite3_server.insert_into_display("autoupdate_allow", "false")
self.PropertyChanged("autoUpgradeState","off")
self.ButtonStatusChange("autoUpgradeStatus", "false")
except Exception as e:
logging.error(str(e))
return False
return True
## dbus接口: 设置自动更新策略
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='is', out_signature='b')
def SetAutoUpgradeMode(self, mode, time):
_time = str(time)
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetAutoUpgradeMode, mode is %s, time is %s ...',mode,_time)
try:
if mode == UU_UPGRADE_MODE_AUTOMATIC_DOWNLOAD:
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "downloadMode", "timing"):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "downloadMode", "timing", True)
self.PropertyChanged("downloadMode","timing")
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "downloadTime", str(_time)):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "downloadTime", str(_time), True)
self.PropertyChanged("downloadTime",str(_time))
self.ButtonStatusChange("autoUpgradeTime", str(_time))
elif mode == UU_UPGRADE_MODE_AUTOMATIC_INSTALL:
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "installMode", "timing"):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "installMode", "timing", True)
self.PropertyChanged("installMode","timing")
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "installTime", str(_time)):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "installTime", str(_time), True)
self.PropertyChanged("installTime",str(_time))
elif mode == UU_UPGRADE_MODE_BEFORE_SHUTDOWN:
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "installTime", "bshutdown"):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "installMode", "bshutdown", True)
self.PropertyChanged("installMode","bshutdown")
elif mode == UU_UPGRADE_MODE_MANUAL:
if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "downloadMode", "manual"):
self.parent.uuconfigs.setValue("autoUpgradePolicy", "downloadMode", "manual", True)
self.PropertyChanged("downloadMode","manual")
except Exception as e:
logging.error(str(e))
return False
return True
# # dbus接口改变apt下载速度
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='sb', out_signature='b',sender_keyword='sender')
def SetDownloadspeedMax(self, speed, set,sender = None):
sender_name = get_proc_from_dbus_name(sender)
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetDownloadspeedMax, speed:%s, set:%r, sender name: %s .'%(speed, set, sender_name))
#来重启Aptdeamon
self.parent.init_config_aptdeamon = True
if set:
with open("/etc/apt/apt.conf.d/80apt-download", "w+") as f:
try:
f.write("Acquire::http::Dl-Limit" + " \"" + "%s" % str(speed) + "\";\n")
f.write("Acquire::https::Dl-Limit" + " \"" + "%s" % str(speed) + "\";\n")
#更改数据库值
self.parent.sqlite3_server.insert_into_display("download_limit","true")
self.parent.sqlite3_server.insert_into_display("download_limit_value",str(speed))
#发送信号
self.ButtonStatusChange("speed" , str(speed))
return True
except Exception as e:
logging.error(e)
return False
else:
if os.path.exists("/etc/apt/apt.conf.d/80apt-download"):
os.remove("/etc/apt/apt.conf.d/80apt-download")
self.parent.sqlite3_server.insert_into_display("download_limit","false")
self.ButtonStatusChange("speed", "0")
return True
else:
self.parent.sqlite3_server.insert_into_display("download_limit","false")
self.ButtonStatusChange("speed", "0")
return True
# # dbus接口获取apt下载速度
@dbus.service.method(UPDATER_DBUS_INTERFACE, out_signature='bs',sender_keyword='sender')
def GetDownloadspeedLimitValue(self,sender = None):
sender_name = get_proc_from_dbus_name(sender)
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' GetDownloadspeedLimitValue sender: %s .', sender_name)
try:
download_limit = self.parent.sqlite3_server.select_from_display("download_limit")
if download_limit == "true":
download_limit_value = self.parent.sqlite3_server.select_from_display("download_limit_value")
return True,str(download_limit_value)
else:
return False,str("0")
except:
return False, "0"
# 是否允许关机前更新
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='ss', out_signature='bs', sender_keyword='sender')
def UnattendedUpgradeValue(self, operation, value="false", sender=None):
sender_name = get_proc_from_dbus_name(sender)
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' UnattendedUpgradeValue sender:%s ', sender_name)
if operation.lower() != "get" and operation.lower() != "set":
return False, 'Please input [\"set\", \"value\"] to set. \nor [\"get\"] to get whether updates are allowed before shutdown.'
if operation == "set":
try:
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' UnattendedUpgradeValue is going to %s [allow_unattended_upgrades_shutdown] value to %s.'%(operation,value))
self.parent.sqlite3_server.insert_into_display("allow_unattended_upgrades_shutdown", value.lower())
except Exception as e:
logging.error(str(e))
return False,str(e)
else:
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' UnattendedUpgradeValue is going to %s [allow_unattended_upgrades_shutdown] value.'%(operation))
try:
value = self.parent.sqlite3_server.select_from_display("allow_unattended_upgrades_shutdown")
logging.info("[allow_unattended_upgrades_shutdown] value is %s."%(value))
except Exception as e:
logging.error(str(e))
return False,str(e)
return True,"success"
# 设置自动更新时间
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='s', out_signature='bs',sender_keyword='sender')
def SetAutoUpgradePeriod(self, period, sender = None):
sender_name = get_proc_from_dbus_name(sender)
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetAutoUpgradePeriod will be set value %s, SetAutoUpgradePeriod sender: %s.'%(period, sender_name))
try:
self.parent.sqlite3_server.insert_into_display("update_period", period.lower())
except Exception as e:
logging.error(str(e))
return True,"success"
# 获取数据库值
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='bss', out_signature='s')
def GetSetDatabaseInfo(self, gs, table, field):
Text = 'NULL'
try:
if gs: #get
if table == 'display':
Text = self.parent.sqlite3_server.select_from_display(str(field))
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' GetDatabaseInfo Table:%s Field:%s Text:%s',table,field,Text)
else: #set
if table == 'display' and "=" in field:
field, value = str(field).split("=")
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetDatabaseInfo Table:%s Field:%s', table, field)
self.parent.sqlite3_server.insert_into_display(field, value)
return "success"
except Exception as e:
logging.error(str(e))
return Text
return Text
## dbus接口: 发送立即更新的信号
@dbus.service.method(UPDATER_DBUS_INTERFACE, out_signature='b')
def AutoUpgradeAllNow(self):
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' AutoUpgradeAllNow ...')
try:
self.UpgradeAllNow()
except Exception as e:
logging.error(str(e))
return False
return True
# kill 进程
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='i', out_signature='b')
def KillProcessSignal(self, pid):
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' KillProcessSignal is %d', pid)
try:
# 判断文件是否存在
if (os.path.exists(RUN_UNATTENDED_UPGRADE)):
os.kill(int(pid), 9)
logging.info('%s has been killed', pid)
else:
logging.warning('%s is not exist.', RUN_UNATTENDED_UPGRADE)
except Exception as e:
logging.error(str(e))
return False
return True
#设置数据库配置信息
@dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='ss',out_signature='b',sender_keyword='sender')
def DatabaseInfoSet(self,field_name,field_value,sender=None):
Status = False
sender_name = get_proc_from_dbus_name(sender)
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetDatabaseInfo,field_name:%s,field_value:%s,caller:%s .',\
field_name,field_value,sender_name)
Status = self.parent.sqlite3_server.insert_into_display(field_name,field_value)
return bool(Status)
#数据库获取配置信息
@dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='s',out_signature='s',sender_keyword='sender')
def DatabaseInfoGet(self,field_name,sender=None):
field_value = ''
sender_name = get_proc_from_dbus_name(sender)
logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' GetDatabaseInfo field_name:%s caller:%s',field_name,sender_name)
field_value = self.parent.sqlite3_server.select_from_display(str(field_name))
logging.info("Get field_value:%s",field_value)
return field_value
#限速修改信号
@dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='ss')
def ButtonStatusChange(self, signal_types = '', value=''):
logging.info(COLORLOG_PREFIX + "Emitting"+ COLORLOG_SUFFIX + " ButtonStatusChange signal_types = %s, value = %s.",signal_types, value)
# dbus 信号:用于发送立即更新信号
@dbus.service.signal(UPDATER_DBUS_INTERFACE)
def UpgradeAllNow(self):
logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" UpgradeAllNow")
# dbus 信号:用于发送自动更新配置更改信号
@dbus.service.signal(UPDATER_DBUS_INTERFACE)
def ChangeUpgradePolicy(self):
logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" ChangeUpgradePolicy")
#限速修改信号
@dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='ss')
def ButtonStatusChange(self, signal_types = '', value=''):
logging.info(COLORLOG_PREFIX + "Emitting"+ COLORLOG_SUFFIX + " ButtonStatusChange signal_types = %s, value = %s.",signal_types, value)
# signal属性发生改变
@dbus.service.signal(dbus_interface=UPDATER_DBUS_INTERFACE,
signature="ss")
def PropertyChanged(self, property, value):
logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" PropertyChanged: ( %s, %s )" % (property, value))
# WRITABLE_PROPERTIES = ()
# # pylint: disable-msg=C0103,C0322
# @dbus.service.signal(dbus_interface=dbus.PROPERTIES_IFACE,
# signature="sa{sv}as")
# def PropertiesChanged(self, interface, changed_properties,
# invalidated_properties):
# """The signal gets emitted if a property of the object's
# interfaces changed.
# :param property: The name of the interface.
# :param changed_properties: A dictrionary of changed
# property/value pairs
# :param invalidated_properties: An array of property names which
# changed but the value isn't conveyed.
# :type interface: s
# :type changed_properties: a{sv}
# :type invalidated_properties: as
# """
# logging.info("Emitting PropertiesChanged: %s, %s, %s" %
# (interface, changed_properties, invalidated_properties))
# # pylint: disable-msg=C0103,C0322
# @dbus.service.method(dbus.INTROSPECTABLE_IFACE,
# in_signature='', out_signature='s',
# path_keyword='object_path',
# connection_keyword='connection')
# def Introspect(self, object_path, connection):
# # Inject the properties into the introspection xml data
# data = dbus.service.Object.Introspect(self, object_path, connection)
# xml = ElementTree.fromstring(data)
# for iface in xml.findall("interface"):
# props = self._get_properties(iface.attrib["name"])
# for key, value in props.items():
# attrib = {"name": key}
# if key in self.WRITABLE_PROPERTIES:
# attrib["access"] = "readwrite"
# else:
# attrib["access"] = "read"
# if isinstance(value, dbus.String):
# attrib["type"] = "s"
# elif isinstance(value, dbus.UInt32):
# attrib["type"] = "u"
# elif isinstance(value, dbus.Int32):
# attrib["type"] = "i"
# elif isinstance(value, dbus.UInt64):
# attrib["type"] = "t"
# elif isinstance(value, dbus.Int64):
# attrib["type"] = "x"
# elif isinstance(value, dbus.Boolean):
# attrib["type"] = "b"
# elif isinstance(value, dbus.Struct):
# attrib["type"] = "(%s)" % value.signature
# elif isinstance(value, dbus.Dictionary):
# attrib["type"] = "a{%s}" % value.signature
# elif isinstance(value, dbus.Array):
# attrib["type"] = "a%s" % value.signature
# else:
# raise Exception("Type %s of property %s isn't "
# "convertable" % (type(value), key))
# iface.append(ElementTree.Element("property", attrib))
# new_data = ElementTree.tostring(xml, encoding="UTF-8")
# return new_data
# # pylint: disable-msg=C0103,C0322
# @dbus.service.method(dbus.PROPERTIES_IFACE,
# in_signature="ssv", out_signature="",
# sender_keyword="sender")
# def Set(self, iface, name, value, sender):
# """Set a property.
# Only the user who intiaited the transaction is
# allowed to modify it.
# :param iface: The interface which provides the property.
# :param name: The name of the property which should be modified.
# :param value: The new value of the property.
# :type iface: s
# :type name: s
# :type value: v
# """
# logging.info("Set() was called: %s, %s" % (name, value))
# return self._set_property(iface, name, value, sender)
# # pylint: disable-msg=C0103,C0322
# @dbus.service.method(dbus.PROPERTIES_IFACE,
# in_signature="s", out_signature="a{sv}")
# def GetAll(self, iface):
# """Get all available properties of the given interface."""
# logging.info("GetAll() was called: %s" % iface)
# return self._get_properties(iface)
# # pylint: disable-msg=C0103,C0322
# @dbus.service.method(dbus.PROPERTIES_IFACE,
# in_signature="ss", out_signature="v")
# def Get(self, iface, property):
# """Return the value of the given property provided by the given
# interface.
# """
# logging.info("Get() was called: %s, %s" % (iface, property))
# return self._get_properties(iface)[property]
# def _set_property(self, iface, name, value, sender):
# """Helper to set a property on the properties D-Bus interface."""
# if iface == UPDATER_DBUS_INTERFACE:
# if name == "ShutdownInstall":
# self.parent.configs_uncover.setValue("InstallMode","shutdown_install",str(bool(value)))
# elif name == "UploadUpgradeLog":
# self.parent.configs_uncover.setValue("SystemStatus","upload_upgrade_log",str(bool(value)))
# elif name == "UploadInstallerLog":
# self.parent.configs_uncover.setValue("SystemStatus","upload_installer_log",str(bool(value)))
# else:
# raise dbus.exceptions.DBusException("Unknown or read only "
# "property: %s" % name)
# else:
# raise dbus.exceptions.DBusException("Unknown interface: %s" %
# iface)
# def _get_properties(self, iface):
# """Helper get the properties of a D-Bus interface."""
# if iface == UPDATER_DBUS_INTERFACE:
# return {
# "ShutdownInstall": dbus.Boolean(
# self.parent.configs_uncover.getWithDefault("InstallMode", "shutdown_install", False)),
# "UploadUpgradeLog": dbus.Boolean(
# self.parent.configs_uncover.getWithDefault("SystemStatus", "upload_upgrade_log", True)),
# "UploadInstallerLog": dbus.Boolean(
# self.parent.configs_uncover.getWithDefault("SystemStatus", "upload_installer_log", False))
# }
# else:
# return {}

View File

View File

@ -0,0 +1,529 @@
#!/usr/bin/env python
import aptdaemon.client as client
import aptdaemon.errors as errors
import aptdaemon.enums as enums
from aptdaemon.enums import (
EXIT_SUCCESS,
EXIT_FAILED,
EXIT_CANCELLED,
STATUS_FINISHED,
get_error_description_from_enum,
get_error_string_from_enum,
get_status_string_from_enum
)
from defer import inline_callbacks
from SystemUpdater.backend import InstallBackend
import logging
from gettext import gettext as _
from SystemUpdater.Core.utils import humanize_size
import dbus,time
from gi.repository import GLib
import traceback
from importlib import reload
# 超时检测 秒单位
UPDATER_IDLE_CHECK_INTERVAL = 5
#安装的超时检查20分钟 按照5秒检查一次
INSTALL_IDLE_TIMEOUT = 4 * 60
#更新超时检查 5分钟
UPDATE_IDLE_TIMEOUT = 5 * 60
class InstallBackendAptdaemon(InstallBackend):
"""Makes use of aptdaemon to refresh the cache and to install updates."""
def __init__(self, window_main, action,mode = InstallBackend.MODE_DEFAULT_STATUS):
InstallBackend.__init__(self, window_main, action,mode)
self.window_main = window_main
#切换aptdaemon的语言 重新导入模块就可以进行切换
if self.window_main.aptd_lang_switch == True:
self.window_main.aptd_lang_switch = False
reload(client)
reload(errors)
reload(enums)
#客户端连接aptdeamon的dbus接口
self.client = client.AptClient()
self.trans_failed_msg = None
#是否在安装状态 判断依据进度>50
self.on_install_stage = False
if self.action == self.ACTION_INSTALL_SHUTDOWN:
self.on_install_stage = True
if self.action == self.ACTION_UPDATE:
#更新的超时检查机制 超时时取消下载
self.update_timestamp = 0
GLib.timeout_add_seconds(UPDATER_IDLE_CHECK_INTERVAL,
self._check_update_inactivity)
#定时模拟发送进度 为了让进度更加线性
self.simulation_progress = 0
GLib.timeout_add_seconds(1,self._check_simulation_progress)
elif self.action == self.ACTION_INSTALL or self.action == self.ACTION_INSTALL_SHUTDOWN:
#安装的超时间检查 超时解除禁止关机
self.install_timestamp = INSTALL_IDLE_TIMEOUT
self.check_progress = 0
GLib.timeout_add_seconds(UPDATER_IDLE_CHECK_INTERVAL,
self._check_install_inactivity)
def _check_simulation_progress(self):
self.simulation_progress += 20
if self.aptd_base.progress >= 90 or self.simulation_progress > 80:
return False
else:
self._dist_status_changed(self.action,[],self.simulation_progress,self.aptd_base.status,self.aptd_base.details)
return True
def _check_install_inactivity(self):
"""Shutdown the daemon if it has been inactive for time specified
in INSTALL_IDLE_TIMEOUT.
"""
logging.info("Checking for inactivity in Installing Time:%d...",self.install_timestamp)
if self.window_main.now_working != self.ACTION_INSTALL and self.window_main.now_working != self.ACTION_INSTALL_SHUTDOWN:
logging.info("Installing to exit and timeout check quit...")
return False
# 进度不同时 更新时间戳
if self.aptd_base.progress != self.check_progress:
self.check_progress = self.aptd_base.progress
self.install_timestamp = INSTALL_IDLE_TIMEOUT
#只有安装的时候启用 下载时候不使用
if (self.install_timestamp <= 0 and self.on_install_stage == True):
logging.error("Quitting due to inactivity(%s)",self.aptd_base.details)
if self.action == self.ACTION_INSTALL_SHUTDOWN:
#关机安装模式 解除禁止关机锁
self.window_main.inhibit_lock.close()
logging.info("Installtion timeout to exit Due to inactivity and Releasing the shutdown lock...")
else:
#超时只单独进行解锁关机
self.inhibit_shutdown.unlock()
self._action_done(self.ACTION_INSTALL,
is_cancelled=False, success=False,
#FIXME: 安装超时退出
error_string=_("Could not install the upgrades"),
error_desc=_("Installtion timeout to exit Due to inactivity") + self.aptd_base.details)
# self.window_main.dbusController.Quit(None)
return False
else:
self.install_timestamp = self.install_timestamp - 1
return True
def _check_update_inactivity(self):
logging.info("Checking for inactivity in Updating...")
#退出定时器 当更新完毕的时候
if (self.aptd_base.cancelable == False and self.aptd_base.progress >= 90) or self.window_main.now_working != self.ACTION_UPDATE:
logging.info("Updating to exit and timeout check quit...")
return False
#当更新进入下载状态时 记录进去的时间
timestamp = self.update_timestamp
if self.aptd_base.cancelable == True and timestamp == 0:
self.update_timestamp = time.time()
return True
#超时设置
if self.update_timestamp != 0 and time.time() - self.update_timestamp > UPDATE_IDLE_TIMEOUT \
and self.aptd_base.cancelable == True:
logging.error("Quitting due to inactivity")
self.window_main.dbusController.transaction.cancel()
return False
return True
@inline_callbacks
def update(self):
"""刷新包cache"""
try:
trans = yield self.client.update_cache(defer=True)
self.window_main.dbusController.transaction = trans
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_UPDATE,
_("Checking for updates…"), False)
except errors.NotAuthorizedError:
self._action_done(self.ACTION_UPDATE,
authorized=False, success=False,
error_string='', error_desc='')
except Exception:
self._action_done(self.ACTION_UPDATE,
is_cancelled=False, success=False,
error_string='', error_desc='')
raise
@inline_callbacks
def commit(self,model,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_downgrade = []):
"""Commit a list of package adds and removes"""
try:
reinstall = purge = []
trans = yield self.client.commit_packages(
pkgs_install, reinstall, pkgs_remove, purge = purge, upgrade = pkgs_upgrade,
downgrade = pkgs_downgrade,defer=True)
self.window_main.dbusController.transaction = trans
yield self._show_transaction(trans, self.action,
_("Installing updates…"), True)
except errors.NotAuthorizedError:
self._action_done(self.action,
authorized=False, success=False,
error_string='', error_desc='')
except errors.TransactionFailed as e:
self.trans_failed_msg = str(e)
except dbus.DBusException as e:
if e.get_dbus_name() != "org.freedesktop.DBus.Error.NoReply":
raise
self._action_done(self.action,
authorized=False, success=False,
error_string='', error_desc='')
except Exception:
self._action_done(self.action,
is_cancelled=False, success=False,
error_string='', error_desc='')
raise
@inline_callbacks
def commit_only(self,model,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_downgrade = []):
"""Commit a list of package adds and removes"""
try:
reinstall = purge = []
trans = yield self.client.commit_only(
pkgs_install, reinstall, pkgs_remove, purge = purge, upgrade = pkgs_upgrade,
downgrade = pkgs_downgrade,download = model, defer=True)
self.window_main.dbusController.transaction = trans
yield self._show_transaction(trans, self.action,
_("Installing updates…"), True)
except errors.NotAuthorizedError:
self._action_done(self.action,
authorized=False, success=False,
error_string='', error_desc='')
except errors.TransactionFailed as e:
self.trans_failed_msg = str(e)
except dbus.DBusException as e:
if e.get_dbus_name() != "org.freedesktop.DBus.Error.NoReply":
raise
self._action_done(self.action,
authorized=False, success=False,
error_string='', error_desc='')
except Exception:
self._action_done(self.action,
is_cancelled=False, success=False,
error_string='', error_desc='')
raise
@inline_callbacks
def install_deb(self,install_path,install_force):
"""安装deb包 """
try:
trans = yield self.client.install_file(path = install_path,force = install_force,defer=True)
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_INSTALL_DEB,
_("Installing deb packages…"), False)
except errors.NotAuthorizedError:
self._action_done(self.ACTION_INSTALL_DEB,
authorized=False, success=False,
error_string='', error_desc='')
except Exception as e:
self._action_done(self.ACTION_INSTALL_DEB,
is_cancelled=False, success=False,
error_string=str(e), error_desc='')
# raise
@inline_callbacks
def fix_broken(self):
"""安装deb包 """
try:
trans = yield self.client.fix_broken_depends(defer=True)
self.window_main.dbusController.transaction = trans
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_FIX_BROKEN,
_("Installing deb packages…"), False)
except errors.NotAuthorizedError:
self._action_done(self.ACTION_FIX_BROKEN,
authorized=False, success=False,
error_string='', error_desc='')
except Exception:
self._action_done(self.ACTION_FIX_BROKEN,
is_cancelled=False, success=False,
error_string='', error_desc='')
raise
@inline_callbacks
def fix_incomplete(self):
"""修复未完成的安装 """
try:
trans = yield self.client.fix_incomplete_install(defer=True)
self.window_main.dbusController.transaction = trans
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_FIX_INCOMPLETE,
_("fix incomplete install"), False)
except errors.NotAuthorizedError:
self._action_done(self.ACTION_FIX_INCOMPLETE,
authorized=False, success=False,
error_string='', error_desc='')
except Exception:
self._action_done(self.ACTION_FIX_INCOMPLETE,
is_cancelled=False, success=False,
error_string='', error_desc='')
raise
@inline_callbacks
def clean(self):
"""清空所有下载的文件 """
try:
trans = yield self.client.clean(defer=True)
self.window_main.dbusController.transaction = trans
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_CLEAN,
_("Remove all downloaded files."), False)
except errors.NotAuthorizedError:
self._action_done(self.ACTION_CLEAN,
authorized=False, success=False,
error_string='', error_desc='')
except Exception:
self._action_done(self.ACTION_CLEAN,
is_cancelled=False, success=False,
error_string='', error_desc='')
raise
@inline_callbacks
def purge_packages(self,pkgs_purge):
"""卸载deb包 """
try:
# trans = yield self.client.remove_packages(package_names = pkgs_purge,defer=True)
trans = yield self.client.commit_packages([],[],[],pkgs_purge,[],[],defer=True)
self.window_main.dbusController.transaction = trans
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_REMOVE_PACKAGES,
_("Installing deb packages…"), False)
except errors.NotAuthorizedError:
self._action_done(self.ACTION_REMOVE_PACKAGES,
authorized=False, success=False,
error_string='', error_desc='')
except Exception as e:
logging.error(str(e))
# self._action_done(self.ACTION_REMOVE_PACKAGES,
# is_cancelled=False, success=False,
# error_string=str(e), error_desc='')
#进度回调
def _on_progress_changed(self, trans,progress,action):
#不要101这种未知状态
if progress == 101:
return
#过滤掉不是线性的进度
if progress > self.aptd_base.progress:
self.aptd_base.progress = progress
else:
return
self.aptd_base.progress = progress
self._dist_status_changed(action,self.now_upgrade.upgrade_content,self.aptd_base.progress,self.aptd_base.status,self.aptd_base.details)
#同步状态回调
def _on_status_changed(self, trans, status,action):
if action == self.ACTION_UPDATE and status == STATUS_FINISHED:
return
#转化词条
self.aptd_base.status = get_status_string_from_enum(status)
if self.aptd_base.status == None:
return
self._dist_status_changed(action,self.now_upgrade.upgrade_content,\
self.aptd_base.progress,self.aptd_base.status,self.aptd_base.details)
#分发进度状态和细节信息
def _dist_status_changed(self,action,upgrade_content = [],progress = 0,status = '',details = ''):
if action == self.ACTION_UPDATE: # 更新进度100后推迟发出100%的信号 -- 等待源过滤完成
if progress == 11:
progress = 15
if progress != 100:
self.window_main.dbusController.UpdateDetectStatusChanged(progress,status)
elif action == self.ACTION_INSTALL:
#50%时候 属于下载状态切换到安装状态的过程 下面的代码只执行一次
if progress >= 50 and progress < 90 and self.on_install_stage == False:
logging.info("The process is now in the installtion phase")
self.on_install_stage = True
self.safe_manager.shutdown_safe()
self._start_install_lock(_("Kylin System Updater"))
#只处理从下载切换到安装时出现的网络问题
#当网络波动时下载某些软件包失败时属于异常状态进行重试时 不发送后续进度 等待重试正常是 进行下载安装
if self.now_upgrade.version_upgrade == True and progress >= 48 and self.on_install_stage != True and 'Failed to fetch' in self.aptd_base.error_details:
logging.warning("Arise Failed to fetch and Need retry Upgrade...")
self.now_upgrade.need_retry = True
return
#在下载阶段发送取消信号
if self.on_install_stage == False:
self.window_main.dbusController.Cancelable(self.aptd_base.cancelable)
self.window_main.dbusController.UpdateDloadAndInstStaChanged(upgrade_content,progress,status,details)
elif action == self.ACTION_INSTALL_SHUTDOWN:
# 写入进度 到plymouth
self._progress_to_plymouth(progress)
self.window_main.dbusController.UpdateDloadAndInstStaChanged(upgrade_content,progress,status,details)
elif action == self.ACTION_DOWNLOADONLY:
#只处理从下载切换到安装时出现的网络问题
#当网络波动时下载某些软件包失败时属于异常状态进行重试时 不发送后续进度 等待重试正常是 进行下载安装
if self.now_upgrade.version_upgrade == True and progress >= 48 and 'Failed to fetch' in self.aptd_base.error_details:
logging.warning("Arise Failed to fetch and Need retry Upgrade...")
self.now_upgrade.need_retry = True
return
self.window_main.dbusController.Cancelable(self.aptd_base.cancelable)
self.window_main.dbusController.UpdateDloadAndInstStaChanged(upgrade_content,progress,status,details)
elif action == self.ACTION_FIX_BROKEN:
self.window_main.dbusController.FixBrokenStatusChanged(False,True,progress,status,'','')
elif action == self.ACTION_REMOVE_PACKAGES:
self.window_main.dbusController.PurgePkgStatusChanged(progress,status,details)
elif action == self.ACTION_INSTALL_DEB or action == self.ACTION_BACKGROUND_UPGRADE:
self.window_main.dbusController.InstalldebStatusChanged(progress,status,details)
else:
logging.info("Other Action:progress = %d , status = %s ,details = %s",progress,status,details)
def _on_details_changed(self, trans, details,action):
self.aptd_base.details = details
self._dist_status_changed(action,self.now_upgrade.upgrade_groups+self.now_upgrade.single_pkgs,\
self.aptd_base.progress,self.aptd_base.status,self.aptd_base.details)
def _on_download_changed(self, trans, details):
logging.info(details)
# eta 剩余时间不正确,取消掉
def _on_progress_download_changed(self,trans,current_items, total_items, currenty_bytes, total_bytes, current_cps, eta):
if self.action == self.ACTION_INSTALL or self.action == self.ACTION_DOWNLOADONLY or self.action == self.ACTION_BACKGROUND_UPGRADE:
self.window_main.dbusController.UpdateDownloadInfo(\
self.now_upgrade.upgrade_groups+self.now_upgrade.single_pkgs,\
current_items, total_items, \
currenty_bytes, total_bytes, \
current_cps)
else:
if self.action == self.ACTION_UPDATE or self.action == self.ACTION_REMOVE_PACKAGES:
return
logging.info("Other Action:current_items = %d, total_items = %d, currenty_bytes = %s, total_bytes = %s, current_cps = %s/s",\
current_items, total_items, \
humanize_size(currenty_bytes), humanize_size(total_bytes),\
humanize_size(current_cps))
def _on_cancellable_changed(self, trans, Cancelable):
#下面的这些 不发送取消信号
if self.action == self.ACTION_REMOVE_PACKAGES:
return
if self.action != self.ACTION_UPDATE:
logging.info("\033[1;32m" + "Emitting" + "\033[0m" +" Cancelable: %r",Cancelable)
self.window_main.dbusController.Cancelable(Cancelable)
#增加取消信号的频发机制
self.aptd_base.cancelable = Cancelable
def _on_config_file_conflict(self, transaction, old, new):
logging.info("Config file conflict oldconf = %s , newconf = %s...",str(old),str(new))
logging.info("Default To Replace Old Configfile...")
#默认替换旧的配置文件
transaction.resolve_config_file_conflict(old, "keep")
# transaction.resolve_config_file_conflict(old, "keep")
#增加记录当产生错误的时候 详细信息
def _on_error_changed(self, trans,error_code, error_details):
# error_string = get_error_string_from_enum(error_code)
self.aptd_base.error_details = str(error_details)
logging.error(str(error_details))
@inline_callbacks
def _show_transaction(self, trans, action, header, show_details):
#更新和升级最后完成和失败都会走此在此进行完成之后的处理
trans.connect("finished", self._on_finished, action)
#升级和更新的状态信息和进度
trans.connect("status-changed", self._on_status_changed,action)
trans.connect("progress-changed", self._on_progress_changed,action)
#取消升级
trans.connect("cancellable-changed", self._on_cancellable_changed)
#下载的进度信息
trans.connect("progress-details-changed", self._on_progress_download_changed)
trans.connect("status-details-changed", self._on_details_changed,action)
trans.connect("error", self._on_error_changed)
trans.connect("config-file-conflict", self._on_config_file_conflict)
# yield trans.set_debconf_frontend("ukui")
# yield trans.set_locale(os.environ["LANGUAGE"] + ".UTF-8")
yield trans.run()
def _on_finished(self, trans, status, action):
try:
error_string = ''
error_desc = ''
#退出
self.on_install_stage = False
if status == EXIT_FAILED:
# self.log_audit(str(trans.error.code))
error_string = get_error_string_from_enum(trans.error.code)
error_desc = get_error_description_from_enum(trans.error.code)
if self.trans_failed_msg:
error_desc = error_desc + "\n" + self.trans_failed_msg
#取消下载
elif status == EXIT_CANCELLED:
error_string = _("Failed to fetch")
error_desc = _("_Cancel Upgrade")
elif status == EXIT_SUCCESS and action == self.ACTION_INSTALL:
error_string = _("System upgrade is complete.")
elif status == EXIT_SUCCESS and action == self.ACTION_REMOVE_PACKAGES:
error_string = _("Uninstallation completed")
is_success = (status == EXIT_SUCCESS)
self._action_done(action,
is_cancelled=(status == EXIT_CANCELLED), success=is_success,
error_string=error_string, error_desc=error_desc)
except Exception as e:
logging.error(e)
traceback.print_exc()
# def log_audit(self,error_code):
# if error_code == "error-package-manager-failed":
# error_msg = self.check_install_error()
# with open("/var/log/kylin-system-updater/error_details.log", 'w+') as configfile:
# configfile.write(str(error_msg))
# def check_install_error(self):
# locate_error = ''
# with open("/var/log/apt/term.log", "r+") as f:
# log_start = None
# log_end = None
# aptterm_log = f.readlines()
# reverse_log = aptterm_log[::-1]
# for logstr in reverse_log:
# if log_end == None and "Log ended:" in logstr:
# log_end = aptterm_log.index(logstr)
# if log_start == None and "Log started:" in logstr:
# log_start = aptterm_log.index(logstr)
# if log_end != None and log_start != None:
# break
# latest_log = aptterm_log[log_start:log_end+1]
# error_deb = latest_log[-2].strip()
# error_msg_line = None
# for log_msg in latest_log:
# if error_deb in log_msg:
# error_msg_line = latest_log.index(log_msg)
# locate_error = latest_log[error_msg_line-5:error_msg_line+5]
# break
# return locate_error

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
Dir::Bin::Methods::ftp "ftp";

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<policyconfig>
<vendor>Kylin System Updater</vendor>
<vendor_url>www.kylinos.cn</vendor_url>
<icon_name>kylin-system-updater</icon_name>
<action id="cn.kylinos.KylinSystemUpdater.action">
<_description>
system level settings
</_description>
<_message>
To Change the settings, you need to authenticate.
</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
</policyconfig>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<policyconfig>
<vendor>Kylin System Updater Config Manager</vendor>
<vendor_url>www.kylinos.cn</vendor_url>
<icon_name>kylin-upgrade-strategies</icon_name>
<action id="com.kylin.UpgradeStrategies.action">
<_description>
system level settings
</_description>
<_message>
To Change the settings, you need to authenticate.
</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
</policyconfig>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- Only root can own the service -->
<policy user="root">
<allow own="com.kylin.UpgradeStrategies"/>
<allow send_interface="com.kylin.UpgradeStrategies.interface"/>
</policy>
<!-- Allow anyone to invoke methods on the interfaces -->
<policy context="default">
<allow send_destination="com.kylin.UpgradeStrategies"
send_interface="com.kylin.UpgradeStrategies.interface"/>
<allow send_destination="com.kylin.UpgradeStrategies"
send_interface="org.freedesktop.DBus.Introspectable"/>
<allow send_destination="com.kylin.UpgradeStrategies"
send_interface="org.freedesktop.DBus.Properties"/>
</policy>
</busconfig>

View File

@ -0,0 +1,4 @@
[D-BUS Service]
Name=com.kylin.UpgradeStrategies
Exec=/bin/python3 /usr/share/kylin-system-updater/kylin-upgrade-strategies -r -d
User=root

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- Only root can own the service -->
<policy user="root">
<allow own="com.kylin.systemupgrade"/>
<allow send_interface="com.kylin.systemupgrade.interface"/>
</policy>
<!-- Allow anyone to invoke methods on the interfaces -->
<policy context="default">
<allow send_destination="com.kylin.systemupgrade"
send_interface="com.kylin.systemupgrade.interface"/>
<allow send_destination="com.kylin.systemupgrade"
send_interface="org.freedesktop.DBus.Introspectable"/>
<allow send_destination="com.kylin.systemupgrade"
send_interface="org.freedesktop.DBus.Properties"/>
</policy>
</busconfig>

View File

@ -0,0 +1,14 @@
[whitelist]
key1 = /usr/bin/kylin-background-upgrade
key2 = /usr/bin/ukui-control-center
key3 = /usr/bin/kylin-installer
key4 = /usr/bin/kylin-uninstaller
key5 = /usr/bin/kylin-software-properties-service
key6 = /usr/bin/kylin-source-update
key7 = /usr/bin/kylin-source-manager
key8 = /usr/bin/kylin-unattended-upgrade
key9 = /usr/bin/kylin-software-center
key10 = /usr/bin/kylin-printer
key11 = /usr/bin/kylin-printer-applet
key12 = /usr/bin/hedron-client
key13 = /usr/bin/kylin-software-center-plugin-synchrodata

View File

@ -0,0 +1,26 @@
#!/bin/sh
# a) it breaks if its not available
# b) the string we have here does not need it (because it has no vars)
eval_gettext() {
if [ -x /usr/bin/gettext ]; then
echo $(gettext "$1")
else
echo "$1"
fi
}
export TEXTDOMAIN=update-notifier
export TEXTDOMAINDIR=/usr/share/locale
case "$DPKG_MAINTSCRIPT_PACKAGE::$DPKG_MAINTSCRIPT_NAME" in
linux-image-extra*::postrm)
exit 0;;
esac
if [ "$0" = "/etc/kernel/postinst.d/update-notifier" ]; then
DPKG_MAINTSCRIPT_PACKAGE=linux-base
fi
# Wake the applet up
echo "*** $(eval_gettext "System logout required") ***" > /var/run/logout-required
echo "$DPKG_MAINTSCRIPT_PACKAGE" >> /var/run/logout-required.pkgs

View File

@ -0,0 +1,26 @@
#!/bin/sh
# a) it breaks if its not available
# b) the string we have here does not need it (because it has no vars)
eval_gettext() {
if [ -x /usr/bin/gettext ]; then
echo $(gettext "$1")
else
echo "$1"
fi
}
export TEXTDOMAIN=update-notifier
export TEXTDOMAINDIR=/usr/share/locale
case "$DPKG_MAINTSCRIPT_PACKAGE::$DPKG_MAINTSCRIPT_NAME" in
linux-image-extra*::postrm)
exit 0;;
esac
if [ "$0" = "/etc/kernel/postinst.d/update-notifier" ]; then
DPKG_MAINTSCRIPT_PACKAGE=linux-base
fi
# Wake the applet up
echo "*** $(eval_gettext "System restart required") ***" > /var/run/reboot-required
echo "$DPKG_MAINTSCRIPT_PACKAGE" >> /var/run/reboot-required.pkgs

View File

@ -0,0 +1,10 @@
/var/log/kylin-system-updater/kylin-system-updater.log.1
{
weekly
missingok
rotate 3
compress
notifempty
minsize 10M
copytruncate
}

Binary file not shown.

View File

@ -0,0 +1,13 @@
[Unit]
Description=kylin-system-updater dbus daemon
StartLimitIntervalSec=0
[Service]
Type=dbus
Restart=always
RestartSec=3
BusName=com.kylin.systemupgrade
ExecStart=/usr/share/kylin-system-updater/kylin-system-updater
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,3 @@
[SYSTEM]
os_version =
update_version =

View File

@ -0,0 +1,12 @@
#此配置文件内的所有配置项,在新装时都会被替换掉
[SystemStatusCover]
close_source_filter = False
priority_upgrade_restart = True
[ConfigPkgStatus]
check_resover_remove = False
check_frontend_pkg = True
[AutoUpgradeConfig]
upgradeInterval = 7
downloadRandom = 180

View File

@ -0,0 +1,9 @@
[SystemStatus]
abnormal_reboot = False
upload_upgrade_log = True
upload_installer_log = False
[InstallMode]
shutdown_install = False
manual_install = False
auto_install = False

View File

@ -0,0 +1,30 @@
[autoUpgradePolicy]
#自动更新的开关
autoUpgradeState = off
#预下载开关
preDownload = off
# 预下载的时间为时间段 例如10:00-11:00
preDownloadTime = 10:00
#添加检查更新的周期 以天为单位
updateDays = 1
# timing 为定时下载 manaual手动下载
downloadMode = timing
# 下载的时间为时间段 例如10:00-11:00
downloadTime = 10:00
#安装存在定时timing 手动:manual 关机安装bshutdown
installMode = timing
#安装也为时间段 例如00:00
installTime = 10:00
#是否开启自动重启 以及自动重启时间可以调节
automaticReboot = off
#自动重启时间的调节 now为立即重启 重启时间调节 例如00:00
automaticRebootTime = now

View File

@ -0,0 +1 @@
0

657
backend/interface.md Normal file
View File

@ -0,0 +1,657 @@
## DBUS接口
[TOC]
### 对应版本信息
| 软件包 | 目前版本 | 备注 |
| :------------------: | :-----------------------------: | :--: |
| kylin-system-updater | kylin-system-updater 1.4.16kord | |
| aptdaemon | 1.1.1+bzr982-0kylin32.3 | |
| | | |
### 描述
实现系统升级以python apt库和aptdeamon的形式
### Dbus接口信息
| 名称 | 含义 |
| -------------- | --------------------------------- |
| BUS类型 | SYSTEM BUS |
| DBUS名称 | com.kylin.systemupgrade |
| OBJECT路径 | /com/kylin/systemupgrade |
| INTERFACES名称 | com.kylin.systemupgrade.interface |
| 属性名称 | org.freedesktop.DBus.Properties |
### Apt-p2p配置项设置
### Dbus接口信息
| 名称 | 含义 |
| -------------- | --------------------------------- |
| BUS类型 | SYSTEM BUS |
| DBUS名称 | com.kylin.systemupgrade |
| OBJECT路径 | /com/kylin/systemupgrade |
| INTERFACES名称 | com.kylin.systemupgrade.interface |
| 属性名称 | org.freedesktop.DBus.Properties |
#### Get
- `简介:`获取属性的值
- `入参:` `s`iface要设置的属性的接口 `s`property要设置的属性名称
- `出参:` `Variant`变量
- `示例:`
```
#获取p2p的配置
Get(com.kylin.systemupgrade.interface,P2pBootstrap)
```
#### Set
- `简介:`设置属性的值
- `入参:` `s`iiface要设置的属性的接口 `s`iproperty要设置的属性名称 `Variant`value要设置的值
- `出参:`
- `示例:`
```
#设置p2p的配置
set("com.kylin.systemupgrade.interface","P2pBootstrap"GLib.Variant('s', "test"))
```
### 方法列表
| Method Name | Input Args | Output Args | means | 异步任务 |
| ------------------ | ---------- | ----------- | --------------------------------- | ------------------ |
| UpdateDetect | 无 | b | 更新cache产生组升级列表JSON文件 | |
| DistUpgradeAll | b | b | 全部升级 | |
| DistUpgradePartial | b,as | b | 部分升级 | |
| DistUpgradeSystem | b | b | 全盘升级 | |
| CancelDownload | 无 | b | 取消升级 | |
| InsertInstallState | ss | b | 向display表插入数据 | |
| GtDownloadspeedLimitValue | 无 | b | 获取当前限速 | |
| SetDownloadspeedMax | sb | b | 设置限速 | |
| GetBackendStatus | 无 | i | 控制获取后端状态 | |
| UnattendedUpgradeValue | ss | bs | 获取是否允许关机前更新 | |
| PurgePackages | as | b | 卸载软件包 | |
| InstalldebFile | ssbb | b | 安装本地deb包 | |
| DataBackendCollect | ss | b | | |
| CheckRebootRequired | s | b | 检查是否需要重启的方法,以及弹窗提示 | |
### Method分析
#### UpdateDetect
- `简介:`更新cache对象完成从之后拿到系统中所有可升级的包再经过源过滤、白名单等等的过滤最后输出当前`可升级的包以及分组JSON配置 输出目录: /var/lib/kylin-system-updater
- `入参:`
- `出参:`True or False 注意:不通过返回值来判断有没有执行成功 通过下面的信号
- `对应信号:`
- `UpdateDetectStatusChanged:` 更新的进度信息和状态信息
- `UpdateDetectFinished:`更新的完成的信号
#### DistUpgradePartial
- `简介:` 升级部分软件包或者分组
- `入参:` `b:` False模式只进行获取升级列表以及计算修复依赖关系以及计算是否存在删除的包`True模式:`直接进行安装的操作 注意必须选使用False模式获取升级列表以及计算依赖关系再进行True模式
`as:` 输入需要升级或者安装的分组 例如 升级系统组:["kylin-update-desktop-system"]
- `出参:`True or False 注意:不通过返回值来判断有没有执行成功 通过下面的信号
- `对应信号:`
- `UpdateDependResloveStatus:` 升级计算依赖修复反馈信号
- `UpdateDloadAndInstStaChanged:`升级安装过程的进度信号以及状态
- `UpdateInstallFinished:` 升级安装完成的信号
#### DistUpgradeAll
- `简介:`升级全部可升级的分组
- `入参:` `b:` False模式只进行获取升级列表以及计算修复依赖关系以及计算是否存在删除的包`True模式:`直接进行安装的操作 注意必须选使用False模式获取升级列表以及计算依赖关系再进行True模式
- `出参:`True or False 注意:不通过返回值来判断有没有执行成功 通过下面的信号
- `对应信号:`
- `UpdateDependResloveStatus:` 升级计算依赖修复反馈信号
- `UpdateDloadAndInstStaChanged:`升级安装过程的进度信号以及状态
- `UpdateInstallFinished:` 升级安装完成的信号
#### UpdateDownloadInfo
- `介绍:` 发送下载包信息信号
- `出参`: `i:`当前正在下载的项,`i:`所有下载的项,`i:`当前下载的字节,`i:`总的需要下载的字节,`i:`下载速度
- `示例:`
```sh
current_items = 1, total_items = 1, currenty_bytes = 45 kB, total_bytes = 45 kB, current_cps = 0 kB/s
```
#### GetBackendStatus
- `介绍:` 获取后端的状态,现在正在处理那些任务
- `入参:` `s:`当前用户的语言变量 例如传入语言环境变量`LANG` 的值`zh_CN.UTF-8` 就会将升级的语言切换为中文 同理其他也能相应设置
- `出参`: `i:`当前任务ID整型数字
- `状态示例列表:`
```python
ACTION_DEFUALT_STATUS = -1 #默认状态空闲状态
ACTION_UPDATE = 0 #处于更新cache状态
ACTION_INSTALL = 1 #包括部分升级、全部升级、q
ACTION_INSTALL_DEB = 2 #处于安装deb的状态
ACTION_CHECK_RESOLVER = 3 #处于计算依赖过程
ACTION_DOWNLOADONLY = 4 #单独下载软件包过程
ACTION_FIX_BROKEN = 5 #修复依赖的过程
ACTION_REMOVE_PACKAGES = 6 #卸载包的状态中
```
#### UnattendedUpgradeValue
- `介绍:` 设置或获取是否允许关机前更新
- `入参`: `s:`operation("get"/"set")`s:`value将要设置的值
- `示例:`
```sh
operation = "set", value = "false"
```
#### InstalldebFile
- `简介:`安装本地deb包
- `入参:` `source:(string)` 安装来源,`path:(string)`本地deb包绝对路径`_check_local_dep:(bool)`出现依赖问题时是否查询本路径下是否存在满足的包,`_auto_satisfy:(bool)`出现依赖问题时是否通过网络下载并安装依赖包
- `出参:`True or False
- `对应信号:`
- `InstalldebStatusChanged`:安装过程的进度信号以及状态
- `InstalldebFinished`:安装完成的信号
- `示例:`
```sh
source = 'kylin-installer', path = '/home/kylin/kylin-video_3.1.0-94.5_amd64.deb', _check_local_dep = 0, _auto_satisfy = 1
```
#### PurgePackages
- `简介:`卸载系统中的软件包
- `入参:` `as:` 需要卸载的包列表 `s:`当前用户的用户名 例如:kylin用户就传入`kylin`字符串
- `出参:`True or False 出参值不做任何参考意义 `注意:`其中False的时候表示后端正在处理其他任务会报错其中完成信号也会反馈结果故不采用方法的返回值来判断错误类型
- `对应信号:`
- `PurgePkgStatusChanged:`卸载过程的进度信号以及状态
- `PurgePackagesFinished:` 卸载完成的信号
- `示例:`
```sh
_purge_list = ['kylin-video','tree'] cur_user = 'kylin'
```
#### DataBackendCollect
- `介绍:` 后端数据采集
- `入参`: `messageType: ` 消息埋点(string) `uploadMessage: ` 上传数据(json格式字符串),必须包含的字段: "packageName"
- `示例:`
```sh
messageType = "UpdateInfos", uploadMessage = "{\"packageName\":\"kylin-system-updater\",\"source\":\"kylin-system-updater\",\"status\":\"True\",\"errorCode\":\"\",\"versionOld\":\"1.2.13.2kord\",\"versionNew\":\"1.2.17.1kord\"}"
messageType: 消息埋点(string) "UpdateInfos"、"InstallInfos"、"RemoveInfos"...
source: 安装来源 "kylin-installer"、"unattented-upgrade"、"kylin-software-center"、"kylin-system-updater"...
status: 安装或卸载状态 "True"/"False"
errorCode: 错误信息 ""/"..."
versionOld: 旧版本号 "1.2.13.2kord"
versionNew: 新版本号 "1.2.17.1kord"
```
#### CheckRebootRequired
- `介绍:` 检查是否需要重启的方法,以及弹窗提示
- `入参`: `s:`标识那个应用调的此接口如自动更新可填入字符串“autoyupgrade”
- `出参:`True or False 执行的结果
#### SetConfigValue
- `简介:`设置配置文件的值 配置文件的目录`/var/lib/kylin-system-updater/system-updater.conf`
- `入参:` `section`, `option`,` value` 不管布尔、列表的数据类型都转化成字符串类型来写入
- 例如传入"InstallModel","shutdown_install","False"
```
[InstallMode]
shutdown_install = True
manual_install = False
auto_install = False
pkgs_install =
pkgs_upgrade =
pkgs_remove =
```
- `出参:`True :设置值成功 False: 设置失败
#### GetConfigValue
- `简介:`获取配置文件的值 配置文件的目录`/var/lib/kylin-system-updater/system-updater.conf`
- `入参:` `section`,` option` 例如传入"InstallModel","shutdown_install"
- `出参:` `bool:`True :获取值成功 False: 获取失败 `Value:`值都以字符串类型来返回
```
[InstallMode]
shutdown_install = True
manual_install = False
auto_install = False
pkgs_install =
pkgs_upgrade =
pkgs_remove =
```
#### CheckInstallRequired
- `简介:`检查当前系统是否需要关机安装或者重启安装
- `入参:`
- `出参:` `int:` 类型返回值 表示当前系统是否需要安装 返回值数值含义如下。简要为0时不需要安装不为零时需要进行提示安装
- `1` 手动更新请求当前系统在关机时进行安装软件包
- `2` 自动更新请求当前系统在关机时进行安装软件包
- `0` 当前系统不需要进行安装
#### FixBrokenDepends
- `简介:` 修复当前的系统Apt环境收到`UpdateFixBrokenStatus`后进行调用类似于调用apt install -f 来进行修复
- `入参:`
- `出参:` True or False 执行的结果 无实际意义
- `对应信号:`
- `FixBrokenStatusChanged:` 修复依赖的状态信号 可不使用
#### MountSquashfsSource
- `简介:` 挂载离线源squashfs
- `入参:` `s:` 挂载文件的位置
- `出参:` `b:` True or False 执行的结果,`s:` 字符类型错误信息描述
### Signal列表
| Signal Name | Output Args | means |
| ---------------------------- | ----------- | ------------------------ |
| UpdateDetectStatusChanged | i,s | 更新进度信息以及状态信息 |
| UpdateDetectFinished | b,as,s,s | 更新完成信号 |
| UpdateDloadAndInstStaChanged | as,i,s,s | 升级的进度信号以及状态 |
| UpdateInstallFinished | b,as,s,s | 升级完成的信号 |
| UpdateDownloadInfo | i,i,u,u,i | 发送下载包信息信号 |
| UpdateDependResloveStatus | b,b,s | 更新依赖修复信息 |
| DistupgradeDependResloveStatus | b,s | 更新全盘修复信息 |
| Cancelable | b | 是否可取消 |
| UpdateSqlitSingle | | |
| FixBrokenStatusChanged | iiisss | 修复依赖的状态信号 |
| PurgePackagesFinished | iss | 卸载完成信号 |
| PurgePkgStatusChanged | bss | 卸载进度信息以及状态信息 |
| RebootLogoutRequired | s | 请求重启或者注销的信号 |
| UpdateInstallFinished | b,as,s,s | 下载完成的信号 |
### Signal分析
#### UpdateDetectStatusChanged
- `介绍:`更新的进度信息和状态信息
- `出参`:`i:`更新的进度信息从0-100%`s:`更新的状态信息,
- `示例:`
```sh
progress = 9 , status = 正在解决依赖关系
progress = 92 , status = 正在载入软件列表
progress = 92 , status = 完成
```
#### UpdateDetectFinished
- `介绍:`更新的完成的信号
- `出参`: `b:`更新是否成功,`as:`可升级的组列表,`s:`产生错误的结果,`s:`产生错误的原因
- `示例:`
```sh
success = True , upgrade_group = ['kylin-update-desktop-system', 'tree', 'texinfo', 'kylin-update-manager', 'dnsmasq-base', 'vino', 'dpkg-dev', 'ghostscript', 'atril', 'wpasupplicant', 'eom', 'eom-common', 'fcitx-bin', 'fcitx-data', 'fcitx-frontend-gtk2', 'wps-office'], error_string = , error_desc =
error_string = 获取更新软件推送失败,请稍后再进行尝试更新 , error_desc = 推送服务器连接异常
```
#### UpdateDependResloveStatus
- `介绍:`升级计算依赖修复反馈信号
- `出参`: `b:`修复依赖关系是否成功,`b:`是否存在升级需要卸载的包,`as:`卸载的包列表,`as:`卸载的包的描述信息,`as:`卸载此包的原因 升级安装那些包导致的,`s:`产生错误的结果,`s:`产生错误的原因
- `示例:`
```sh
UpdateDependResloveStatus:resolver_status = True , remove_status = True , remove_pkgs = ['kylin-burner-i18n'],pkg_raw_description = ['Sophisticated CD/DVD burning application - localizations files'] ,delete_desc = ['kylin-burner-i18n 将要被删除,由于升级 kylin-burner'],error_string = , error_desc =
```
#### UpdateFixBrokenStatus
- `介绍:`更新检查过程中是否需要修复系统Apt的环境提示是否存在卸载软件包的情况
- `出参`: `b:`是否能修复系统环境,`b:`是否存在修复需要卸载的包,`as:`卸载的包列表,`as:`卸载的包的描述信息,`as:`卸载此包的原因,`s:`产生错误的结果,`s:`产生错误的原因
- `示例:`
```sh
UpdateDependResloveStatus:resolver_status = True , remove_status = True , remove_pkgs = ['kylin-burner-i18n'],pkg_raw_description = ['Sophisticated CD/DVD burning application - localizations files'] ,delete_desc = ['kylin-burner-i18n 将要被删除,由于升级 kylin-burner'],error_string = , error_desc =
```
#### UpdateDloadAndInstStaChanged
- `介绍:` 升级安装过程的进度信号以及状态
- `出参`: `as:`当前那些组在升级安装 `i:`更新的进度信息从0-100%`s:`更新的状态信息 `s:`下载的细节信息
- ` 示例:`
```sh
groups_list = ['kylin-update-desktop-system'] progress = 15 , status = 下载中 current_details = 下载中 tree
```
#### UpdateInstallFinished
- `介绍:` 升级安装完成的信号
- `出参`: `b:`升级是否成功,`as:`可升级的组列表,`s:`产生错误的结果,`s:`产生错误的原因
- `示例:`
```sh
pdateInstallFinished success = True , upgrade_group = ['tree'], error_string = 系统升级完成。 , error_desc =
```
#### UpdateDownloadFinished
- `介绍:` 下载完成的信号
- `出参`: `b:`下载是否成功,`as:`可升级的组列表,`s:`产生错误的结果,`s:`产生错误的原因
- `示例:`
```sh
pdateInstallFinished success = True , upgrade_group = ['tree'], error_string = 系统升级完成。 , error_desc =
```
#### FixBrokenStatusChanged
- `介绍:` 修复依赖过程中的状态反馈信号
- `出参`: `i:`修复依赖是否完成 `i:`修复依赖过程是否成功`注意:只有修复完成时,修复依赖是否成功才有意义``i:`修复的进度信息 `s:`修复的状态信息 `s:`产生错误的结果,`s:`产生错误的原因
- ` 示例:`
```sh
emit FixBrokenStatusChanged finished = False , success = True,progress = 66 , status = 正在应用更改,error_string = , error_desc =
```
-
#### PurgePkgStatusChanged
- `介绍:`卸载的进度信息和状态信息以及状态的细节信息
- `出参`:`i:`卸载的进度信息从0-100%`s:`卸载的状态信息,`s:`卸载的细节信息
- `示例:`
```sh
INFO:emit PurgePkgStatusChanged progress = 63 , status = 正在应用更改 ,current_details = 正在准备删除 kylin-video
INFO:emit PurgePkgStatusChanged progress = 76 , status = 正在应用更改 ,current_details = 正在卸载 kylin-video
```
#### PurgePackagesFinished
- `介绍:`卸载的完成的信号
- `出参`: `b:`卸载是否成功,`s:`产生错误的结果,`s:`产生错误的原因
- `示例:`
```sh
#卸载完成
PurgePackagesFinished success = True , error_string = 卸载完成。 , error_desc =
#卸载失败
PurgePackagesFinished success = False , error_string = 软件包不存在 , error_desc = 检查包名的拼写是否正确,以及是否启用了相应的仓库。
PurgePackagesFinished success = False , error_string = 软件包没有安装 , error_desc = 不需要进行卸载。
#卸载失败 由于正在处理其他任务也同样会报错
PurgePackagesFinished success = False , error_string = 其他任务正在更新升级中,请稍后再卸载。 , error_desc =
```
#### InstalldebStatusChanged
- `介绍:`安装的进度信息和状态信息以及状态的细节信息
- `出参`:`i:`安装的进度信息从0-100%`s:`安装的状态信息,`s:`安装的细节信息
- `示例:`
```sh
InstalldebStatusChanged progress = 57 , status = 正在应用更改 ,current_details = 正在配置 python3-bandit
InstalldebStatusChanged progress = 57 , status = 正在应用更改 ,current_details = python3-bandit 已安装
```
#### InstalldebFinished
- `介绍:`安装的完成的信号
- `出参`: `b:`安装是否成功,`s:`产生错误的结果,`s:`产生错误的原因
- `示例:`
```sh
#安装完成
InstalldebFinished success = True , error_string = , error_desc =
#安装失败 缺少依赖的
InstalldebFinished success = False , error_string = bandit dependency is not satisfied , error_desc = python3-bandit
#安装失败 选择从网络拉依赖 网络断开 报网络错误
InstalldebFinished success = False , error_string = 下载软件包文件失败 , error_desc = 检查您的网络连接。
```
#### RebootLogoutRequired
- `介绍:`请求重启和注销的信号
- `出参`: `s:` "reboot" 表示重启 "logout"表示注销
- `示例:`
```sh
Emitting RebootLogoutRequired required_status = reboot
```
#### InstallDetectStatus
- `介绍:`下载安装前的状态检查
- `出参`: `b:`检查出错时为`False`,没有错误`success``s:`产生错误的码
- 错误码示例:
```python
ERROR_NOT_DISK_SPACE = "error-not-disk-space"
```
- `示例:`
```sh
#表示出现磁盘已满的错误z
InstallDetectStatus success = False , error_code = "error-not-disk-space"
```
后端日志:`/var/log/kylin-system-updater/kylin-system-updater.log.1`
### 更新过程报错信息总结
| 错误信息 | 错误原因 | 解决办法 |
| -------------------- | ------------------------------------------------------------ | ---------------------------------------- |
| 下载软件仓库信息失败 | 源存在问题使用apt update检查若存在报错则更新管理器无问题 | 检查源是否可以使用 |
| 无法访问源管理服务器 | 源管理服务器存在问题 | 源管理服务器是否可用或者检查源服务器配置 |
| 软件索引已经损坏 | 当前系统中cache被破坏apt无法使用 | 终端检查错误原因进行解决 |
| 无法初始化软件包信息 | apt存在某些问题 | 具体错误原因查看日志相应解决 |
| 无法获取组配置软件包 | 源中不存在kylin-update-desktop-config | 将此包放入源仓库或者写配置文件不强制安装 |
| 无法读取推送升级列表 | 读取推送列表出现问题 | 检查important.list是否存在 |
| 获取软件推送失败 | 老版本文案同 无法访问源管理服务器解决 | |
### 安装过程报错信息总结
| 错误信息 | 错误原因 | 解决办法 |
| ------------------ | ------------------------------ | ---------------------------------- |
| 软件包操作失败 | 被升级的软件包有问题 | 检查后端log日志查看那个包存在问题 |
| 下载软件包文件失败 | 网络原因的或者这个软件包的仓库 | 检查网络以及源仓库 |
| 磁盘空间不足 | 磁盘的空间不足 | 查看日志那些目录空间不足 |
| 不能计算升级 | 无法计算依赖关系 | 检查日志那个包出现的问题,相应解决 |
| | | |

103
backend/kylin-system-updater Executable file
View File

@ -0,0 +1,103 @@
#!/usr/bin/python3
from SystemUpdater.UpdateManager import UpdateManager
from gettext import gettext as _
import logging
from optparse import OptionParser
import dbus
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
import signal
import os
import sys
import gettext
from SystemUpdater.Core.LogManager import get_logfile as logfile
gettext.bindtextdomain('kylin-system-updater', '/usr/share/locale')
gettext.textdomain('kylin-system-updater')
_ = gettext.gettext
#定义日志的格式
FORMAT = "%(asctime)s [%(levelname)s]: %(message)s"
FORMAT_DEBUG = '%(asctime)-15s %(levelname)s(%(filename)s:%(lineno)d):%(message)s'
def signal_handler_term(signal, frame):
# type: (int, object) -> None
logging.warning("SIGTERM received, will stop")
app.dbusController.Quit(None)
if __name__ == "__main__":
# Begin parsing of options
parser = OptionParser()
parser.add_option ("-d", "--debug", action="store_true", default=False,
help=_("Show debug messages"))
parser.add_option("-r", "--replace",
default=False,
action="store_true", dest="replace",
help=_("Quit and replace an already running "
"daemon"))
parser.add_option ("-n","--no-update-source", action="store_true",
dest="no_update_source", default=False,
help=_("Do not check for updates source when updating"))
parser.add_option ("--no-update", action="store_true",
dest="no_update", default=False,
help="Do not check for updates when starting")
parser.add_option("-c", "--close-filter",
default=False,
action="store_true", dest="close_filter",
help=_("Quit and close allowed origin"))
parser.add_option("--no-check-network",
default=False,
action="store_true", dest="no_check_network",
help=_("Quit and close check network"))
(options, args) = parser.parse_args()
if os.getuid() != 0:
print(_("You need to be root to run this application"))
sys.exit(1)
# set debconf to NON_INTERACTIVE
os.environ["DEBIAN_FRONTEND"] = "noninteractive"
os.environ["TERM"] = "xterm"
os.environ["PATH"] = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
#当不存在语言变量时 默认显示中文
if not "LANGUAGE" in os.environ:
os.environ["LANGUAGE"] = "zh_CN.UTF-8"
#当不存在语言变量时 默认显示中文
if not "LANG" in os.environ:
os.environ["LANG"] = "zh_CN.UTF-8"
#做一些规范处理
if os.environ["LANGUAGE"] == "en":
os.environ["LANGUAGE"] = "en_US.UTF-8"
if os.environ["LANGUAGE"] == "zh_CN:en" or os.environ["LANGUAGE"] == "zh_CN:zh":
os.environ["LANGUAGE"] = "zh_CN.UTF-8"
# ensure that we are not killed when the terminal goes away e.g. on
# shutdown
signal.signal(signal.SIGHUP, signal.SIG_IGN)
signal.signal(signal.SIGINT,signal_handler_term)
if options.debug:
logging.basicConfig(format=FORMAT,level=logging.INFO,datefmt='%m-%d,%H:%M:%S')
else:
logging.basicConfig(format=FORMAT,level=logging.DEBUG,datefmt='%m-%d,%H:%M:%S',filename = logfile(),filemode = 'a')
logging.info('kylin-system-updater(LANGUAGE:%s LANG:%s) starting ...',os.environ["LANGUAGE"],os.environ["LANG"])
app = UpdateManager(options)
#当出现安装过程中异常的重启时 开机直接进行修复操作
# if app.configs_cover.getWithDefault("ConfigPkgStatus", "check_frontend_pkg", False) == True:
# app.configs_cover.setValue("ConfigPkgStatus","check_frontend_pkg",str(False),True)
# app.check_frontend_pkg()
#当出现安装过程中异常的重启时 开机直接进行修复操作
if app.configs_uncover.getWithDefault("SystemStatus", "abnormal_reboot", False) == True:
app.start_update()
app.run()

View File

@ -0,0 +1,81 @@
#!/usr/bin/python3
from SystemUpdater.UpgradeStrategies import UpgradeStrategies
from gettext import gettext as _
import logging
from optparse import OptionParser
import dbus
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
import signal
import os
import sys
import gettext
from SystemUpdater.Core.LogManager import upgrade_strategies_logfile as logfile
gettext.bindtextdomain('kylin-system-updater', '/usr/share/locale')
gettext.textdomain('kylin-system-updater')
_ = gettext.gettext
#定义日志的格式
FORMAT = "%(asctime)s [%(levelname)s]: %(message)s"
FORMAT_DEBUG = '%(asctime)-15s %(levelname)s(%(filename)s:%(lineno)d):%(message)s'
def signal_handler_term(signal, frame):
# type: (int, object) -> None
logging.warning("SIGTERM received, will stop")
app.dbusController.Quit(None)
if __name__ == "__main__":
# Begin parsing of options
parser = OptionParser()
parser.add_option ("-d", "--debug", action="store_true", default=False,
help=_("Show debug messages"))
parser.add_option("-r", "--replace",
default=False,
action="store_true", dest="replace",
help=_("Quit and replace an already running "
"daemon"))
(options, args) = parser.parse_args()
if os.getuid() != 0:
print(_("You need to be root to run this application"))
sys.exit(1)
# set debconf to NON_INTERACTIVE
os.environ["DEBIAN_FRONTEND"] = "noninteractive"
os.environ["TERM"] = "xterm"
os.environ["PATH"] = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
#当不存在语言变量时 默认显示中文
if not "LANGUAGE" in os.environ:
os.environ["LANGUAGE"] = "zh_CN.UTF-8"
#当不存在语言变量时 默认显示中文
if not "LANG" in os.environ:
os.environ["LANG"] = "zh_CN.UTF-8"
#做一些规范处理
if os.environ["LANGUAGE"] == "en":
os.environ["LANGUAGE"] = "en_US.UTF-8"
if os.environ["LANGUAGE"] == "zh_CN:en" or os.environ["LANGUAGE"] == "zh_CN:zh":
os.environ["LANGUAGE"] = "zh_CN.UTF-8"
# ensure that we are not killed when the terminal goes away e.g. on
# shutdown
signal.signal(signal.SIGHUP, signal.SIG_IGN)
signal.signal(signal.SIGINT,signal_handler_term)
if options.debug:
logging.basicConfig(format=FORMAT,level=logging.INFO,datefmt='%m-%d,%H:%M:%S')
else:
logging.basicConfig(format=FORMAT,level=logging.DEBUG,datefmt='%m-%d,%H:%M:%S',filename = logfile(),filemode = 'a')
logging.info('Updater Config Manager Daemon(LANGUAGE:%s LANG:%s) starting ...',os.environ["LANGUAGE"],os.environ["LANG"])
app = UpgradeStrategies(options)
app.run()

6
backend/po/ChangeLog Normal file
View File

@ -0,0 +1,6 @@
2021-09-16 XueYi Luo <luoxueyi@kylinos.cn>
* zh_CN.po: Updated Simplified Chinese translation.
* zh_HK.po: Updated translation for HongKong,china.
* zh_TW.po: Updated translation for Taiwan,China.

28
backend/po/Makefile Normal file
View File

@ -0,0 +1,28 @@
top_srcdir=`pwd`/..
DOMAIN=kylin-system-updater
PO_FILES := $(wildcard *.po)
CONTACT=sebastian.heinlein@web.de
XGETTEXT_ARGS = --msgid-bugs-address=$(CONTACT)
XGETTEXT_ARGS += --keyword=unicode_gettext:2 --keyword=unicode_ngettext:2,3
XGETTEXT_ARGS += --language=python
all: update-po
# update the pot
$(DOMAIN).pot:
XGETTEXT_ARGS="$(XGETTEXT_ARGS)" intltool-update -p -g $(DOMAIN)
# merge the new stuff into the po files
merge-po: $(PO_FILES)
XGETTEXT_ARGS="$(XGETTEXT_ARGS)" intltool-update -r -g $(DOMAIN);
# create mo from the pos
%.mo : %.po
mkdir -p mo/$(subst .po,,$<)/LC_MESSAGES/
msgfmt $< -o mo/$(subst .po,,$<)/LC_MESSAGES/$(DOMAIN).mo
# dummy target
update-po: $(DOMAIN).pot merge-po $(patsubst %.po,%.mo,$(wildcard *.po))

11
backend/po/POTFILES.in Normal file
View File

@ -0,0 +1,11 @@
[encoding: UTF-8]
SystemUpdater/backend/InstallBackendAptdaemon.py
SystemUpdater/backend/__init__.py
SystemUpdater/UpdateManager.py
SystemUpdater/Core/MyCache.py
SystemUpdater/Core/UpdateList.py
SystemUpdater/Core/OriginFilter.py
SystemUpdater/Core/Database.py
SystemUpdater/UpdateManagerDbus.py
SystemUpdater/Core/utils.py
SystemUpdater/Core/enums.py

0
backend/po/POTFILES.skip Normal file
View File

2763
backend/po/zh_CN.po Normal file

File diff suppressed because it is too large Load Diff

2696
backend/po/zh_HK.po Normal file

File diff suppressed because it is too large Load Diff

2728
backend/po/zh_TW.po Normal file

File diff suppressed because it is too large Load Diff

50
backend/report-updater-bug Executable file
View File

@ -0,0 +1,50 @@
#!/bin/sh
#系统升级收集bug日志使用
echo "系统升级收集BUG日志使用..."
#建立收集的log目录
mkdir updaterlog
#记录一些基本信息
date >> updaterlog/base-info
dpkg -l | grep kylin-system-updater >> updaterlog/base-info
dpkg -l | grep ukui-control-center >> updaterlog/base-info
dpkg -l | grep aptdaemon >> updaterlog/base-info
echo $1 >> updaterlog/base-info
echo "记录BUG产生时间系统当前时间以及升级相关的版本信息"
cat updaterlog/base-info
cp /etc/apt/sources.list updaterlog || true
cp -r /usr/share/kylin-update-desktop-config/config/ updaterlog || true
#复制后端的日志
cp -r /var/log/kylin-system-updater/ updaterlog || true
#收集apt的日志
cp -r /var/log/apt/term.log updaterlog || true
cp -r /var/log/apt/history.log updaterlog || true
#收集aptdamon的日志
cp -r /var/log/kylin-unattended-upgrades/ updaterlog || true
outputName="$(date +%m-%d,%H-%M-%S)-updaterLog.tar.gz"
#将所有的日志进行打包
tar -czvf updaterLog.tar.gz updaterlog >/dev/null
#删除收集的日志目录
rm -rf updaterlog
#将文件存储到桌面
if [ ! -d ~/桌面 ]; then
mv updaterLog.tar.gz ~/Desktop/$outputName
echo 输出位置:~/Desktop/$outputName
else
mv updaterLog.tar.gz ~/桌面/$outputName
echo 输出位置:~/桌面/$outputName
fi
echo "系统更新日志收集完毕..."
echo "\033[1;31m注意\033[0m 1、请确保Bug复现的时间与执行脚本收集日志时间相近以此能根据脚本执行时间快速定位到问题的相关日志..."
echo " 2、若Bug复现的时间与现在时间相差较远时请手动输入大概复现时间。例如 report-updater-bug 月-日,时-分"
echo "请将桌面下\033[5;32;49;1m $outputName \033[0m日志文件提交到禅道... "

15
backend/setup.cfg Normal file
View File

@ -0,0 +1,15 @@
[build_i18n]
domain=kylin-system-updater
# xml_files=[("share/metainfo/",
# ("data/update-manager.appdata.xml.in",)),
# ]
[sdist]
formats = bztar
[nosetests]
match=test
# [install]
# skip-build=0

21
backend/setup.py Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
from distutils.core import setup
from DistUtilsExtra.command import (
build_extra, build_i18n, build_help)
disabled = []
class CustomBuild(build_extra.build_extra):
def run(self):
build_extra.build_extra.run(self)
setup(
packages=[ 'SystemUpdater',
'SystemUpdater.backend',
'SystemUpdater.Core'
],
cmdclass={ "build": CustomBuild,
"build_i18n": build_i18n.build_i18n
# "build_help": build_help.build_help
}
)

8645
debian/changelog vendored Normal file

File diff suppressed because it is too large Load Diff

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
9

52
debian/control vendored Normal file
View File

@ -0,0 +1,52 @@
Source: kylin-system-updater
Section: misc
Priority: optional
Maintainer: Kylin Development Team <cp@kylinos.cn>
Build-Depends: debhelper (>= 9),
python3,
python3-setuptools,
dh-python,
python3-all (>= 3.3.0-2),
python3-distutils-extra (>= 2.38),
python3-dbus,
python3-distro-info,
python3-gi (>= 3.8),
python3-yaml,
lsb-release,
apt-clone (>= 0.2.3~ubuntu1)
Build-Depends-Indep: intltool,
python3-coverage,
python3-distro-info,
pycodestyle | pep8,
pyflakes3,
python3-apt (>= 1.9.6~),
python3-mock,
lsb-release,
python3-psutil
Standards-Version: 3.8.0
Homepage: https://www.kylinos.cn
Vcs-Browser: https://www.kylinos.cn
X-Python3-Version: >= 3.2
Package: kylin-system-updater
Architecture: all
Depends: ${python3:Depends},
${misc:Depends},
policykit-1,
python3-dbus,
python3-psutil,
python3-gi (>= 3.8),
python3-yaml,
aptdaemon (>=1.1.1+bzr982-0kylin32.3k5.2),
python3-distro-info,
python3-apscheduler,
python3-pyqt5,
python3-crypto,
sqlite3,
kylin-update-frontend
Breaks:
Recommends: python3-launchpadlib
Suggests: gir1.2-dbusmenu-glib-0.4,
gir1.2-unity-5.0,
Description: dbus daemon that manages apt updates.
dbus daemon that manages apt updates. Provides DBUS interfaces to UKCC.

22
debian/copyright vendored Normal file
View File

@ -0,0 +1,22 @@
This package was debianized by Michiel Sikkes <michiel@eyesopened.nl> on
Mon, 25 Oct 2004 21:49:07 +0200.
It was downloaded from http://code.launchpad.net/~ubuntu-core-dev/update-manager/main
Upstream Authors:
Michiel Sikkes <michiel@eyesopened.nl>
Michael Vogt <michael.vogt@ubuntu.com>
Sebastian Heinlein <glatzor@ubuntu.com>
Jonathan Riddell <jriddell@ubuntu.com>
Copyright:
2004-2008 Canonical Ltd.
2004-2005 Michiel Sikkes
All code released under the GPL, see /usr/share/common-licenses/GPL
With the exception of
UpdateManager/SimpleGladeApp.py
which is released under the LGPL, see /usr/share/common-licenses/LGPL

37
debian/kylin-system-updater.install vendored Normal file
View File

@ -0,0 +1,37 @@
#!/usr/bin/dh-exec
#backend
backend/data/kylin-system-updater.db /usr/share/kylin-system-updater/
backend/report-updater-bug /usr/bin
backend/data/30kylin-system-updater /etc/apt/apt.conf.d/
backend/data/com.kylin.systemupgrade.conf /etc/dbus-1/system.d/
#backend/data/com.kylin.systemupgrade.limit /etc/dbus-1/conf/
backend/data/kylin-system-updater.service /usr/lib/systemd/system/
backend/data/kylin-logout-required /usr/share/kylin-system-updater/
backend/data/kylin-reboot-required /usr/share/kylin-system-updater/
backend/kylin-system-updater /usr/share/kylin-system-updater/
backend/SystemUpdater/*.py /usr/share/kylin-system-updater/SystemUpdater/
backend/SystemUpdater/backend/*.py /usr/share/kylin-system-updater/SystemUpdater/backend/
backend/SystemUpdater/Core/*.py /usr/share/kylin-system-updater/SystemUpdater/Core/
backend/build/mo/* /usr/share/locale/
backend/data/system-updater-defaults.conf /var/lib/kylin-system-updater/
backend/data/system-updater-coverable.conf /var/lib/kylin-system-updater/
backend/data/unattended-upgrades-policy.conf /var/lib/unattended-upgrades/
backend/data/unattended-upgrades-timestamp /var/lib/unattended-upgrades/
backend/data/cn.kylinos.KylinSystemUpdater.policy /usr/share/polkit-1/actions/
backend/data/kylin-system-version.conf /etc/kylin-version/
#configDaemon
backend/kylin-upgrade-strategies /usr/share/kylin-system-updater/
backend/data/com.kylin.UpgradeStrategies.conf /etc/dbus-1/system.d/
backend/data/com.kylin.UpgradeStrategies.service /usr/share/dbus-1/system-services/
backend/data/cn.kylinos.UpgradeStrategies.policy /usr/share/polkit-1/actions/
backend/data/kylin-system-updater /etc/logrotate.d
#uu
unattended-upgrades/*.service /lib/systemd/system/
unattended-upgrades/notify /usr/bin/
unattended-upgrades/*.desktop /etc/xdg/autostart/
unattended-upgrades/kylin-unattended-upgrade /usr/bin
unattended-upgrades/kylin-unattended-upgrade-shutdown /usr/bin
unattended-upgrades/kylin-unattended-upgrades /etc/apt/apt.conf.d/
unattended-upgrades/logrotate.d/* /etc/logrotate.d/

24
debian/postinst vendored Normal file
View File

@ -0,0 +1,24 @@
#!/bin/bash
if [ ! -d /var/cache/kylin-system-updater ];then
mkdir -p /var/cache/kylin-system-updater
fi
if [ ! -f /var/cache/kylin-system-updater/kylin-system-updater.db ];then
echo "Copying database to the specified path ..."
cp -r /usr/share/kylin-system-updater/kylin-system-updater.db /var/cache/kylin-system-updater/
fi
systemctl enable kylin-system-updater.service
mkdir -p /var/lib/unattended-upgrades
chmod +x /usr/bin/kylin-unattended-upgrade
chmod +x /usr/bin/kylin-unattended-upgrade-shutdown
systemctl enable kylin-unattended-upgrades.service
if [ -f /usr/share/kylin-system-updater/SystemUpdater/Core/DataMigration.py ];then
# echo "Database record migration"
# /usr/share/kylin-system-updater/SystemUpdater/Core/DataMigration.py -m
/usr/share/kylin-system-updater/SystemUpdater/Core/DataMigration.py -u appname_cn=
/usr/share/kylin-system-updater/SystemUpdater/Core/DataMigration.py -t=tid_search
/usr/share/kylin-system-updater/SystemUpdater/Core/DataMigration.py -u status_cn=
/usr/share/kylin-system-updater/SystemUpdater/Core/DataMigration.py -u changelog=
/usr/share/kylin-system-updater/SystemUpdater/Core/DataMigration.py -f init_version="yes"
fi

7
debian/rules vendored Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/make -f
#export PYBUILD_INTERPRETERS=python3
%:
dh $@
#override_dh_makeshlibs:
#--with=python3 --buildsystem=pybuild

1
debian/source/format vendored Normal file
View File

@ -0,0 +1 @@
3.0 (quilt)

1
debian/update-manager.manpages vendored Normal file
View File

@ -0,0 +1 @@
debian/tmp/usr/share/man/man8/kylin-system-updater.8

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,153 @@
// Automatically upgrade packages from these (origin:archive) pairs
//
// Note that in Ubuntu security updates may pull in new dependencies
// from non-security sources (e.g. chromium). By allowing the release
// pocket these get automatically pulled in.
Unattended-Upgrade::Allowed-Origins {
"Kylin:10.1";
":default";
//"${distro_id}:${distro_codename}";
//"${distro_id}:${distro_codename}-security";
// Extended Security Maintenance; doesn't necessarily exist for
// every release and this system may not have it installed, but if
// available, the policy for updates is such that unattended-upgrades
// should also install from here by default.
//"${distro_id}ESMApps:${distro_codename}-apps-security";
//"${distro_id}ESM:${distro_codename}-infra-security";
// "${distro_id}:${distro_codename}-updates";
// "${distro_id}:${distro_codename}-proposed";
// "${distro_id}:${distro_codename}-backports";
};
// Python regular expressions, matching packages to exclude from upgrading
Unattended-Upgrade::Package-Blacklist {
// The following matches all packages starting with linux-
// "linux-";
// Use $ to explicitely define the end of a package name. Without
// the $, "libc6" would match all of them.
// "libc6$";
// "libc6-dev$";
// "libc6-i686$";
// Special characters need escaping
// "libstdc\+\+6$";
// The following matches packages like xen-system-amd64, xen-utils-4.1,
// xenstore-utils and libxenstore3.0
// "(lib)?xen(store)?";
// For more information about Python regular expressions, see
// https://docs.python.org/3/howto/regex.html
};
// This option controls whether the development release of Ubuntu will be
// upgraded automatically. Valid values are "true", "false", and "auto".
Unattended-Upgrade::DevRelease "false";
// This option allows you to control if on a unclean dpkg exit
// unattended-upgrades will automatically run
// dpkg --force-confold --configure -a
// The default is true, to ensure updates keep getting installed
//Unattended-Upgrade::AutoFixInterruptedDpkg "true";
//tell dpkg not to cause conffile prompts
DPkg:Options{
"--force-confnew";
};
// Split the upgrade into the smallest possible chunks so that
// they can be interrupted with SIGTERM. This makes the upgrade
// a bit slower but it has the benefit that shutdown while a upgrade
// is running is possible (with a small delay)
//Unattended-Upgrade::MinimalSteps "false";
// Install all updates when the machine is shutting down
// instead of doing it in the background while the machine is running.
// This will (obviously) make shutdown slower.
// Unattended-upgrades increases logind's InhibitDelayMaxSec to 30s.
// This allows more time for unattended-upgrades to shut down gracefully
// or even install a few packages in InstallOnShutdown mode, but is still a
// big step back from the 30 minutes allowed for InstallOnShutdown previously.
// Users enabling InstallOnShutdown mode are advised to increase
// InhibitDelayMaxSec even further, possibly to 30 minutes.
//Unattended-Upgrade::InstallOnShutdown "False";
// Send email to this address for problems or packages upgrades
// If empty or unset then no email is sent, make sure that you
// have a working mail setup on your system. A package that provides
// 'mailx' must be installed. E.g. "user@example.com"
//Unattended-Upgrade::Mail "";
// Set this value to one of:
// "always", "only-on-error" or "on-change"
// If this is not set, then any legacy MailOnlyOnError (boolean) value
// is used to chose between "only-on-error" and "on-change"
//Unattended-Upgrade::MailReport "on-change";
// Remove unused automatically installed kernel-related packages
// (kernel images, kernel headers and kernel version locked tools).
//Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
// Do automatic removal of newly unused dependencies after the upgrade
//Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
// Do automatic removal of unused packages after the upgrade
// (equivalent to apt-get autoremove)
//Unattended-Upgrade::Remove-Unused-Dependencies "false";
// Automatically reboot *WITHOUT CONFIRMATION* if
// the file /var/run/reboot-required is found after the upgrade
//Unattended-Upgrade::Automatic-Reboot "false";
// Automatically reboot even if there are users currently logged in
// when Unattended-Upgrade::Automatic-Reboot is set to true
//Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
// If automatic reboot is enabled and needed, reboot at the specific
// time instead of immediately
// Default: "now"
//Unattended-Upgrade::Automatic-Reboot-Time "02:00";
// Use apt bandwidth limit feature, this example limits the download
// speed to 70kb/sec
//Acquire::http::Dl-Limit "70";
//Retry times after each download failure
Unattended-Upgrade::RetryTimes 3;
// Enable logging to syslog. Default is False
//Unattended-Upgrade::SyslogEnable "True";
// Specify syslog facility. Default is daemon
// Unattended-Upgrade::SyslogFacility "daemon";
// Download and install upgrades only on AC power
// (i.e. skip or gracefully stop updates on battery)
Unattended-Upgrade::OnlyOnACPower "True";
// Download and install upgrades only on non-metered connection
// (i.e. skip or gracefully stop updates on a metered connection)
// Unattended-Upgrade::Skip-Updates-On-Metered-Connections "true";
// Verbose logging
//Unattended-Upgrade::Verbose "True";
// Print debugging information both in unattended-upgrades and
// in unattended-upgrade-shutdown
Unattended-Upgrade::Debug "True";
// Allow package downgrade if Pin-Priority exceeds 1000
// Unattended-Upgrade::Allow-downgrade "false";
// When APT fails to mark a package to be upgraded or installed try adjusting
// candidates of related packages to help APT's resolver in finding a solution
// where the package can be upgraded or installed.
// This is a workaround until APT's resolver is fixed to always find a
// solution if it exists. (See Debian bug #711128.)
// The fallback is enabled by default, except on Debian's sid release because
// uninstallable packages are frequent there.
// Disabling the fallback speeds up unattended-upgrades when there are
// uninstallable packages at the expense of rarely keeping back packages which
// could be upgraded or installed.
// Unattended-Upgrade::Allow-APT-Mark-Fallback "true";

View File

@ -0,0 +1,14 @@
[Unit]
Description=Unattended Upgrades Shutdown
After=network.target local-fs.target systemd-logind.service kylin-system-updater.service
RequiresMountsFor=/run /var/log /var/run /var/lib /boot
Documentation=man:unattended-upgrade(8)
[Service]
ExecStart=/usr/bin/kylin-unattended-upgrade-shutdown --wait-for-signal
Type=idle
#KillMode=process
#TimeoutStopSec=1800
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,10 @@
/var/log/unattended-upgrades/unattended-upgrades.log
/var/log/unattended-upgrades/unattended-upgrades-dpkg.log
/var/log/unattended-upgrades/unattended-upgrades-shutdown.log
{
rotate 6
monthly
compress
missingok
notifempty
}

72
unattended-upgrades/notify Executable file
View File

@ -0,0 +1,72 @@
#!/usr/bin/python3
import os
import sys
import subprocess
import dbus
import re
import atexit
import logging
import signal
NOTIFICATION_PIPE = '/tmp/notification.pipe'
PID_FILE = '/tmp/notify.pid'
def signal_handler_term():
logging.warning("SIGTERM received, will stop")
sys.exit(1)
def signal_handler_int():
logging.warning("SIGINT received, will stop")
sys.exit(1)
def translate(text):
env = os.environ['LANG']
if re.match('zh_CN',env):
if text == 'install start':
return '安装开始'
elif text == 'install finish':
return '安装结束'
else:
return text
def notify(iface,msg):
msg = msg.rstrip()
title = ' '
content = ' '
if msg =='install start':
title = translate('install start')
content = translate('install start')
elif msg == 'install finish':
title = translate('install finish')
content = translate('install start')
#print(title,content)
iface.Notify(' ',1,' ',title,content,[],{},3)
def main():
bus = dbus.SessionBus()
proxy_object = bus.get_object('org.freedesktop.Notifications','/org/freedesktop/Notifications')
iface = dbus.Interface(proxy_object,dbus_interface='org.freedesktop.Notifications')
f=open(NOTIFICATION_PIPE,'r')
while True:
msg = f.read()
if len(msg)>0:
bus = dbus.SessionBus()
proxy_object = bus.get_object('org.freedesktop.Notifications','/org/freedesktop/Notifications')
iface = dbus.Interface(proxy_object,dbus_interface='org.freedesktop.Notifications')
notify(iface,msg)
f.flush()
if __name__ == "__main__":
signal.signal(signal.SIGTERM, signal_handler_term)
signal.signal(signal.SIGINT,signal_handler_int)
if os.path.exists(PID_FILE):
logging.info("notify already exists, exiting...")
sys.exit(0)
else:
# clean up pid file on exit
with open(PID_FILE, "w+") as fp:
fp.write("%s" % os.getpid())
atexit.register(os.remove, PID_FILE)
main()

View File

@ -0,0 +1,7 @@
[Desktop Entry]
Name=update-notify
Exec=/usr/bin/notify
Type=Application
NoDisplay=true
Comment=update-notify