|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- -*- coding: raw-text-unix -*-
-- Edrx, 2004sep08
-- Current version: 2004dec22
-- (find-angg "LUA/debs2.lua")
--
-- debs.lua: find the .debs corresponding to installed packages.
--
-- To create a new Debian system from an existing one (say, in another
-- partition) we usually need a repository of .debs; and we usually
-- want the new system to have a subset of the packages that are
-- installed in the current one, with exactly the same versions, and,
-- for dozens of reasons, we want to need to access the net as little
-- as possible. The best solution is then to create a local repository
-- with the right selection of .debs, but how do we do that?
--
-- This library provides some functions to help in that task. It is
-- easy to obtain the names of the packages currently installed, each
-- with its version string:
--
-- # (find-man "1 grep-status")
-- # (find-sh "grep-status -s Package,Version -F Status ' installed'")
-- grep-status --show-field=Package,Version --field=Status ' installed'
--
-- Usually _all_ the original .debs corresponding to those packages
-- are available somewhere in the system:
--
-- * the ones that were downloaded by apt are at
-- (find-fline "/var/cache/apt/archives/")
--
-- * the ones coming from CD installs are inside the CD images;
-- we can either mount the real CD or its .iso image
--
-- * the ones coming from local repositories, are, huh, well, just
-- files inside these local repositories
--
-- * the ones that have been installed with "dpkg -i" from
-- nonstandard .debs, like things that we have compiled locally or
-- that we have downloaded from very nonstandard places, are in
-- directories that we know; we are always very organized when we
-- put our root hats on :)
--
-- So we just need to list these .debs, typically with
--
-- find dir1 dir2 ... dirn -name '*.deb'
--
-- and then cross the output with the output of "grep-status" to
-- obtain the first listed .deb corresponding to each installed
-- package, plus a listing of the installed packages for which no
-- corresponding .deb was found.
--
-- After that we need a few other tricks to convert the output to a
-- series of "cp"s or "ln"s. Check the examples at the end of the
-- file. (But they're not well-documented, sorry).
strfind = string.find
splitdebversion = function (str)
local _, __, epoch, colon, version
_, __, epoch, colon, version = strfind(str, "^(.*)(%%3a)(.*)$")
if _ then return epoch, colon, version end
_, __, epoch, colon, version = strfind(str, "^(.*)(:)(.*)$")
if _ then return epoch, colon, version end
return nil, nil, str
end
splitdeb = function (str)
local _, __, dir, name, epoch, colon, version, arch
_, __, dir, rest = strfind(str, "^(.*/)([^/]*)$")
if _ then str = rest end
_, __, name, v, arch = strfind(str, "^([^_]*)_([^_]*)_([^_.]*).deb$")
if not _ then return end
epoch, colon, version = splitdebversion(v)
return {dir=dir, name=name, epoch=epoch, colon=colon,
version=version, arch=arch}
end
readinstalleddebs = function (fname)
for str in io.lines(fname) do
local _, __, field, contents = strfind(str, "^(.*): (.*)$")
if field == "Package" then name = contents end
if field == "Version" then
epoch, colon, version = splitdebversion(contents)
installed[name] = {name=name, epoch=epoch, colon=colon,
version=version}
end
end
end
readdeblist = function (fname)
for pathname in io.lines(fname) do
local struct = splitdeb(pathname)
if struct and
installed[struct.name] and
not installed[struct.name].pathname and
installed[struct.name].version == struct.version then
installed[struct.name].pathname = pathname
end
end
end
readall = function (fname_installeddebs, ...)
installed = {}
readinstalleddebs(fname_installeddebs)
for i=1,table.getn(arg) do readdeblist(arg[i]) end
end
printall = function ()
for name,struct in installed do
print(struct.pathname or "# no deb found for " .. name)
end
end
if arg and string.gsub(arg[0], ".*/", "") == "debs.lua" then
readall(unpack(arg))
printall()
end
--[[
# Examples and tests:
#*
lua50 -e '
dofile(os.getenv("HOME").."/LUA/debs.lua")
PP(splitdeb("libstartup-notification0_0.7-1_i386.deb"))
PP(splitdeb("libstdc++5-3.3-dev_1%3a3.3.4-6sarge1.2_i386.deb"))
PP(splitdeb("/foo/libstdc++5_1:3.3.4-6sarge1.2_i386.deb"))
'
#*
mkdir /tmp/cdd/
sudo umount /tmp/cdd/
sudo mount -o loop /big/hdb2/CDs/debian-br-cdd/sarge-i386-1.raw /tmp/cdd
find /tmp/cdd/ -name '*.deb' | sort | tee /tmp/cdddebs
ls /var/cache/apt/archives/*.deb | tee /tmp/vcdebs
ls /big/hdb2/CDs/cdd-extra/*.deb | tee /tmp/cddextradebs
grep-status --show-field=Package,Version --field=Status ' installed' \
| tee /tmp/installed-debs
#*
lua50 -e '
dofile("'$HOME/LUA/debs.lua'")
installed = {}
readinstalleddebs("/tmp/installed-debs")
readdeblist("/tmp/vcdebs")
readdeblist("/tmp/cddextradebs")
readdeblist("/tmp/cdddebs")
for name,struct in installed do
print("# " .. name, "->", struct.pathname or "")
end
' | sort | tee /tmp/o | l -S
#*
lua50 -e '
dofile("'$HOME/LUA/debs.lua'")
readall("/tmp/installed-debs",
"/tmp/vcdebs", "/tmp/cddextradebs", "/tmp/cdddebs")
for name,struct in installed do
print(struct.pathname or "# no deb found for " .. name)
end
' | sort | tee /tmp/o | l -S
#*
lua50 ~/LUA/debs.lua \
/tmp/installed-debs \
/tmp/vcdebs /tmp/cddextradebs /tmp/cdddebs
#*
--]]