On Fri, Dec 28, 2007 at 08:20:01AM +0100, Frans Pop wrote: > I agree with Anthony that it is very much preferable to have a solution > that's just able to automatically determine the correct version. Okay, so here's a updated version that generates both debian_version and lsb-release as specced by dato, if it's given arguments of debian-version or dato-release, and has appropriate perms. In order for it to be useful, I guess it'd need to be in base, and hence written in perl or C (unless we decided to add python to base). ] $ ./debian_version.py debian-version ] /etc/debian_version should contain: ] lenny ] $ ./debian_version.py dato-release ] /etc/lsb-release should contain: ] DISTRIB_ID=Debian ] DISTRIB_RELEASE=lenny ] DISTRIB_CODENAME=lenny ] DISTRIB_DESCRIPTION="Debian x.y Testing distribution - Not Released" ] $ ./debian_version.py noisy ] Packages seem to be from Debian release lenny ] Debian x.y Testing distribution - Not Released ] ['mirror.internode.on.net_pub_debian_dists_lenny_Release', 'http.us.debian.org_debian_dists_lenny_Release'] ] 89.4% HIT RATE (1293 of 1447) ] 95.3% of installed packages available ] 4.4% of matching packages could be upgraded ] 1.8% of matching packages are more recent ] $ sudo rm /etc/debian_version /etc/lsb-release ] $ sudo ./debian_version.py debian-version dato-release ] $ cat /etc/debian_version; echo ----; cat /etc/lsb-release ] lenny ] ---- ] DISTRIB_ID=Debian ] DISTRIB_RELEASE=lenny ] DISTRIB_CODENAME=lenny ] DISTRIB_DESCRIPTION="Debian x.y Testing distribution - Not Released" Cheers, aj
#!/usr/bin/env python
# Copyright 2007 Anthony Towns
# GPL v2 or later.
import apt_pkg, sys, os
apt_pkg.init()
def try_write(file):
try:
f = open(file, "w")
except IOError:
f = sys.stdout
f.write("%s should contain:\n" % file)
return f
def uniq(l):
return dict( [(x,1) for x in l] ).keys()
def get_installed():
vs = {}
i = open("/var/lib/dpkg/status", "r")
p,v,x = None,None,None
for l in i.xreadlines():
l = l.rstrip()
if l.startswith("Package: "): p = l[l.find(" ")+1:]
if l.startswith("Version: "): v = l[l.find(" ")+1:]
if l.startswith("Status: "):
x = l.split(" ")[1:]
if l == "":
if x and x[0] != "hold" and x[1] == "ok" and x[2] == "installed":
vs[p] = v
p,v,x = None,None,None
i.close()
return vs
vlal = "/var/lib/apt/lists"
arch = "".join(os.popen("dpkg --print-architecture", "r").readlines()).rstrip()
def releases():
urs = {}
for path in os.listdir(vlal):
if not path.endswith("_Release.gpg"): continue
path = path[:-4]
release_info = []
o,l,s,v,c = [None] * 5
for l in open(os.path.join(vlal,path)).xreadlines():
l = l.rstrip()
if l[0] != " ":
release_info.append(
(l[:l.find(":")], l[l.find(":")+1:].lstrip()) )
else:
x = release_info[-1]
x = (x[0], x[1] + "\n" + l[1:])
release_info[-1] = x
release_info_l = release_info
release_info = dict(release_info)
vendor = filter(None, [
release_info.get("Label", None),
release_info.get("Origin", None),
"unknown"] ) [0]
version = filter(None, [
release_info.get("Version", None),
release_info.get("Codename", None),
release_info.get("Suite", None),
"unknown"] ) [0]
pkgs = [x for x in os.listdir(vlal)
if x.startswith(path[:-7])
and x.endswith("_binary-%s_Packages" % arch) ]
k = (vendor,version)
if k not in urs: urs[k] = ([],[],[])
urs[k][0].append( path )
urs[k][1].append( release_info )
urs[k][2].extend( pkgs )
res = []
for k,v in urs.iteritems():
(vendor, version) = k
(paths, rels, pkgs) = v
res.append( (vendor, version, paths, rels, readlist(pkgs)) )
return res
def readlist(files):
vs = {}
for file in files:
i = open(os.path.join(vlal, file), "r")
p,v = None,None
for l in i.xreadlines():
l = l.rstrip()
if l.startswith("Package: "): p = l[l.find(" ")+1:]
if l.startswith("Version: "): v = l[l.find(" ")+1:]
if l == "":
vs[p] = v
p,v = None,None
i.close()
return vs.items()
def compare(installed, list):
same, new, old = 0,0,0
tryagain = dict(installed)
for (p, tv) in list:
if p in installed:
if tv == installed[p]:
same += 1
del tryagain[p]
else:
x = apt_pkg.VersionCompare(installed[p], tv)
if x > 0:
old += 1
elif x < 0:
new += 1
else:
same += 1
del tryagain[p]
return same,new,old,tryagain
installed = get_installed()
release_pkgs = releases()
noisy = ("noisy" in sys.argv[1:])
iterate = ("iterate" in sys.argv[1:])
debian_version = ("debian-version" in sys.argv[1:])
dato_release = ("dato-release" in sys.argv[1:])
intro = "Packages"
while installed:
best = 0,len(installed),0,"-","-",[],"-",[]
for vendor, version, path, rels, packages in release_pkgs:
same,new,old,tryagain = compare(installed, packages)
if same > best[0]:
best = same,new,old,vendor,version,rels,path,tryagain
same,new,old,vendor,version,rels,path,tryagain = best
if same == 0: break
total = same+new+old
inst = len(installed)
if noisy:
print "%s seem to be from %s release %s" % (intro, vendor, version)
print "%s" % (rels[0].get("Description","(no description)"))
print "%s" % (path)
print " %5.1f%% HIT RATE (%d of %d)" % (100.0*same/inst, same, inst)
print " %5.1f%% of installed packages available" % (100.0*total/inst)
print " %5.1f%% of matching packages could be upgraded" % (100.0*new/total)
print " %5.1f%% of matching packages are more recent" % (100.0*old/total)
if debian_version:
debian_version = 0
f = try_write("/etc/debian_version")
f.write("%s\n" % (version))
del f
if dato_release:
dato_release = 0
f = try_write("/etc/lsb-release")
f.write("DISTRIB_ID=%s\n" % (vendor))
f.write("DISTRIB_RELEASE=%s\n" % (version))
for c in uniq([ x.get("Codename", None) for x in rels ]):
if c == None: continue
f.write("DISTRIB_CODENAME=%s\n" % (c))
break
for d in uniq([ x.get("Description", None) for x in rels ]):
if d == None: continue
f.write("DISTRIB_DESCRIPTION=\"%s\"\n" % (d))
break
if iterate and noisy:
installed = tryagain
intro = "\nRemaining packages"
else:
installed = []
if installed and iterate and noisy:
print "\nRemaining packages:"
for p,v in installed.iteritems():
print " %s: %s" % (p,v)
Attachment:
signature.asc
Description: Digital signature