Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
#!/usr/bin/env lua50 -- -*- coding: raw-text-unix -*- -- Edrx, 2004sep08 -- Current version: 2004dec22 -- (find-angg "LUA/debs.lua") -- (find-es "debrepository" "var-www-vcarchives") -- -- 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 access the net as little as -- possible in the process. 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 format = string.format 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 installed[struct.name].arch = struct.arch installed[struct.name].epoch = struct.epoch installed[struct.name].colon = struct.colon end end end -- (find-fline "/tmp/obigdebiandebs") -- (find-luamanw3m "manual.html" "string.format") printcps = function (prefix) for name,s in installed do if s.pathname then print(format("%s %s %s_%s_%s.deb", prefix, installed[name].pathname, name, s.version, s.arch)) end end end printnotfound = function (prefix) for name,s in installed do if not s.pathname then print(format("%s %s %s", prefix, name, installed[name].version)) end end end -- (find-luamanw3m "manual.html") -- (find-luamanw3m "manual.html" "lua -la.lua b.lua t1 t2") -- (find-luamanw3m "contents.html") i = 1 installed = {} while i <= arg.n do local a, b = arg[i], arg[i+1] if a == "-i" then readinstalleddebs(b); i = i+2 elseif a == "-d" then readdeblist(b); i = i+2 elseif a == "-cp" then printcps(b); i = i+2 elseif a == "-nf" then printnotfound(b); i = i+2 elseif a == "-e" then assert(loadstring(b))(); i = i+2 else print("Unrecognized option: " .. a); os.exit(1) end end --[[ #* # «preparation» find /big/debian/pool/ -type f -and -name '*.deb' > /tmp/obigdebiandebs find /var/cache/apt/archives/ -type f -and -name '*.deb' > /tmp/ovcaadebs find $S/ -type f -and -name '*.deb' > /tmp/osnarfdebs grep-status -s Package,Version -F Status ' installed' > /tmp/oinstalleddebs # (find-fline "/tmp/obigdebiandebs") # (find-fline "/tmp/") #* # A small test: # (find-fline "/tmp/o") cd /tmp/ ~/LUA/debs2.lua \ -i /tmp/oinstalleddebs \ -d /tmp/ovcaadebs \ -cp 'cp -s' \ -nf '# Not found:' \ -e 'for name,s in installed do PP(name, s) end' \ |& tee /tmp/o #* # «ocp» # The real thing: # (find-fline "/tmp/ocp") cd /tmp/ ~/LUA/debs2.lua \ -i /tmp/oinstalleddebs \ -d /tmp/obigdebiandebs \ -d /tmp/ovcaadebs \ -d /tmp/osnarfdebs \ -cp 'cp -s' \ -nf '# Not found:' \ |& tee /tmp/ocp #* --]]