allow-duplicated.lua 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. -- This script will handle Allow-Duplicated packages when more
  2. -- than one is available during an install operation, and will
  3. -- also upgrade these packages in a dist-upgrade operation (if
  4. -- they match a regex in RPM::Allow-Duplicated-Upgrade).
  5. --
  6. -- This script must be plugged in the following slots:
  7. --
  8. -- Scripts::AptGet::Install::SelectPackage
  9. -- Scripts::AptGet::DistUpgrade
  10. -- Scripts::Synaptic::DistUpgrade
  11. --
  12. -- Author: Gustavo Niemeyer <niemeyer@conectiva.com>
  13. rex = require("rex_posix")
  14. function realname(name)
  15. local s, e, name = string.find(name, "(.+)#")
  16. return name
  17. end
  18. function get_pkglist(name)
  19. local j = 1
  20. local packages = {}
  21. for i, p in ipairs(pkglist()) do
  22. if realname(pkgname(p)) == name then
  23. packages[j] = p
  24. j = j + 1
  25. end
  26. end
  27. return packages
  28. end
  29. -- select best choice of virtual provided packages
  30. function select_goodpackage(packages)
  31. local goodpkg = packages[1]
  32. local goodpkgname = realname(pkgname(goodpkg))
  33. if goodpkgname then
  34. -- Check if every package has the same real name, and
  35. -- leave only the one with the greatest version, if
  36. -- that's the case.
  37. for i = 2, table.getn(packages) do
  38. local nextpkg = packages[i]
  39. local nextpkgname = realname(pkgname(nextpkg))
  40. if nextpkgname ~= goodpkgname then
  41. --markkeep(goodpkg)
  42. goodpkg = nil
  43. break
  44. end
  45. if not pkgvercand(goodpkg)
  46. or pkgvercand(nextpkg) and
  47. verstrcmp(verstr(pkgvercand(goodpkg)),
  48. verstr(pkgvercand(nextpkg))) == -1 then
  49. --markkeep(goodpkg)
  50. goodpkg = nextpkg
  51. end
  52. end
  53. if goodpkg and pkgvercand(goodpkg) then
  54. selected = goodpkg
  55. markinstall(goodpkg)
  56. end
  57. end
  58. if not selected then
  59. -- Strip #... from package names if we can't find a good solution.
  60. for i, name in ipairs(packagenames) do
  61. local name = realname(name)
  62. if name and name ~= virtualname then
  63. packagenames[i] = name
  64. end
  65. end
  66. end
  67. end
  68. if script_slot == "Scripts::AptGet::Install::PreResolve" then
  69. for i, pkg in ipairs(pkglist()) do
  70. s, e, name = string.find(pkgname(pkg), "(.+)#")
  71. if statinstall(pkg) and s then
  72. -- unmark selected packages
  73. markkeep(pkg)
  74. local packages = {}
  75. packages = get_pkglist(name)
  76. select_goodpackage(packages)
  77. end
  78. end
  79. end
  80. if script_slot == "Scripts::AptGet::Install::SelectPackage" then
  81. local found = 0
  82. for i, pkg in ipairs(packages) do
  83. p = pkgfind(pkgname(pkg))
  84. if pkgvercur(p) then
  85. found = 1
  86. end
  87. end
  88. if found == 0 then
  89. select_goodpackage(packages)
  90. end
  91. end
  92. if script_slot == "Scripts::AptGet::DistUpgrade" or
  93. script_slot == "Scripts::AptGet::Upgrade" or
  94. script_slot == "Scripts::Synaptic::DistUpgrade" or
  95. script_slot == "Scripts::Synaptic::Upgrade" then
  96. -- Automatically install newer versions of all packages which
  97. -- are registered in the Allow-Duplicated scheme and are matched
  98. -- by the regular expressions in RPM::Allow-Duplicated-Upgrade.
  99. -- Compile expressions with package names which should
  100. -- be considered for upgrade.
  101. local updatelist = confgetlist("RPM::Allow-Duplicated-Upgrade")
  102. for i, expr in ipairs(updatelist) do
  103. updatelist[i] = rex.new(expr)
  104. end
  105. if table.getn(updatelist) ~= 0 then
  106. -- Gather information about Allow-Duplicated packges.
  107. local canddups = {}
  108. local curdups = {}
  109. for i, pkg in pairs(pkglist()) do
  110. local name = realname(pkgname(pkg))
  111. if name then
  112. if pkgvercur(pkg) then
  113. if not curdups[name] then
  114. curdups[name] = {}
  115. end
  116. table.insert(curdups[name],
  117. verstr(pkgvercur(pkg)))
  118. elseif pkgvercand(pkg) then
  119. if not canddups[name] then
  120. canddups[name] = {}
  121. end
  122. table.insert(canddups[name],
  123. verstr(pkgvercand(pkg)))
  124. end
  125. end
  126. end
  127. -- Compile expressions with package names which should be hold.
  128. local holdlist = confgetlist("RPM::Hold")
  129. for i, expr in ipairs(holdlist) do
  130. holdlist[i] = rex.new(expr)
  131. end
  132. -- Remove packages without any matches in updatelist, or with
  133. -- any matches in holdlist.
  134. for name, _ in pairs(curdups) do
  135. local found = false
  136. for i, expr in ipairs(updatelist) do
  137. if expr:match(name) then
  138. found = true
  139. break
  140. end
  141. end
  142. if found then
  143. for i, expr in ipairs(holdlist) do
  144. if expr:match(name) then
  145. found = false
  146. break
  147. end
  148. end
  149. end
  150. if not found then
  151. curdups[name] = nil
  152. end
  153. end
  154. -- Mark the newest packages for installation.
  155. for name, _ in pairs(curdups) do
  156. if canddups[name] then
  157. -- Check the best candidate version.
  158. local bestver = nil
  159. for i, ver in ipairs(canddups[name]) do
  160. if not bestver or
  161. verstrcmp(bestver, ver) == -1 then
  162. bestver = ver
  163. end
  164. end
  165. -- Now check if it's newer than all installed
  166. -- versions.
  167. for i, ver in ipairs(curdups[name]) do
  168. if verstrcmp(ver, bestver) == 1 then
  169. bestver = nil
  170. break
  171. end
  172. end
  173. -- Finally, mark it for installation.
  174. if bestver then
  175. markinstall(name.."#"..bestver)
  176. end
  177. end
  178. end
  179. end
  180. end
  181. -- vim:ts=4:sw=4:et