diff --git a/bin/apt-missing b/bin/apt-missing new file mode 100755 index 0000000..c80d8fe --- /dev/null +++ b/bin/apt-missing @@ -0,0 +1,148 @@ +#!/usr/bin/python +"""check missing dependencies""" + +import getopt,sys +import apt_pkg +import apt.progress.text +import os +progusage="apt-missing [options] [packages]" +shortoptions=["h","d","r","s","a","t:","p:"] +longoptions=["help", "depends", "recommends", "suggests", "any", "type=", "package=","help-nroff"] +argstype=['','','','','','string','string'] +explanation=['This help text', + 'Missing Depends or Pre-Depends', + 'Missing Recommends (default)', + 'Missing Suggests', + 'Missing positive dependency (as above)', + 'Arbitrary dependency type (e.g. Enhances)', + 'List of packages (all if none given)' + ] + +def fmt_dep(dep): + """Format a Dependency object [of apt_pkg] as a string.""" + ret = dep.target_pkg.name + if dep.target_ver: + ret += " (%s %s)" % (dep.comp_type, dep.target_ver) + return ret + +def usage(): + """Usage for this program.""" + print progusage + for k in range(len(longoptions)): + if longoptions[k]=='help-nroff': + continue + if k0: + x=x+"\\fI"+argstype[k]+"\\fR" + print ".TP" + print x + print explanation[k] + +def main(): + """The main function""" + apt_pkg.init_config() + try: + opts, args = getopt.getopt(sys.argv[1:], "".join(shortoptions), + longoptions) + except getopt.GetoptError: + usage() + sys.exit(1) + xtypes=[] + packages=[] + for o,a in opts: + if o in ("-h","--help"): + usage() + sys.exit() + elif o in ("--help-nroff"): + usagenroff() + sys.exit() + elif o in ("-d","--depends"): + xtypes.append('Depends') + xtypes.append('Pre-Depends') + elif o in ("-r","--recommends"): + xtypes.append('Recommends') + elif o in ("-s","--suggests"): + xtypes.append('Suggests') + elif o in ("-a","--any"): + xtypes.extend(['Depends','Pre-Depends','Recommends','Suggests']) + elif o in ("-t","--type"): + xtypes.extend(a.split(' ')) + elif o in ("-p","--package"): + packages.extend(a.split(' ')) + else: + assert False, "unhandled option" + for p in args: + packages.extend(p.split(' ')) + if len(xtypes)==0: + xtypes=['Depends','Pre-Depends','Recommends'] + apt_pkg.init_system() + f = open('/dev/null', 'w') + cache=apt_pkg.Cache(apt.progress.text.OpProgress(f)) + f.close() + defective={} + claimed={} + for xtype in xtypes: + defective[xtype]=0 + for pkg in sorted(cache.packages, key=lambda pkg: pkg.name): + if not(pkg.name in packages) and len(packages)>0: + continue; + version=pkg.current_ver + if version != None and pkg.current_state == apt_pkg.CURSTATE_INSTALLED: + for dtype,clauses in version.depends_list.iteritems(): + if dtype in xtypes: + missing=[] + for clause in clauses: + found=False + for dep in clause: + if dep.target_pkg.current_state == apt_pkg.CURSTATE_INSTALLED: + found=True + break + if not(found): + for dep in clause: + tpkg=dep.target_pkg + if tpkg.provides_list: + for name,x,tver in tpkg.provides_list: + if tver.parent_pkg.current_ver==None: + continue + if tver.parent_pkg.current_state != apt_pkg.CURSTATE_INSTALLED: + continue + if tver.ver_str==tver.parent_pkg.current_ver.ver_str: + found=True + break + + if not(found): + missing.append(clause) + if len(missing)>0: + bugfound=True + print "# Package %s has some %s missing:" % (pkg.name, + dtype) + for clause in missing: + string=" | ".join(fmt_dep(dep) for dep in clause) + if string in claimed: + claimed[string]=claimed[string]+1 + else: + claimed[string]=1 + print " | ".join(fmt_dep(dep) for dep in clause) + defective[dtype]=defective[dtype]+1 + for xtype in xtypes: + print "## \"%s\" broken in %d packages" % (xtype,defective[xtype]) + +if __name__ == '__main__': + main() diff --git a/bin/apt-origins b/bin/apt-origins new file mode 100755 index 0000000..dd534fd --- /dev/null +++ b/bin/apt-origins @@ -0,0 +1,236 @@ +#!/usr/bin/python +"""Check the origin of all packages""" + +import getopt,sys +import apt_pkg +import apt.progress.text +import os +import re +import types +progusage="apt-origins [options]" +shortoptions=["h","l","c","m","t","C:","L:","o:"] +longoptions=["help", "list","count","manual","tabular","columns=","lines=","order=","help-nroff"] +argstype=['','','','','','integer','integer','string'] +explanation=['This help text', + 'Just list available distributions', + 'Just display package count by origin', + 'Only display manually installed packages', + 'Use tabular output format for origin display', + 'Set the number of columns of the output', + 'Set the maximal number of packages that can be displayed', + 'Set the order in which packages are in the distributions.\n This is a space-jointed string of stanzas like\n alias1~site1/archive1/o=origin1/l=label1/a=arch1 where alias1 is the display name of\n a distribution of name archive1 at site1, label1 and origin1 being the\n values in the Release file. "none" will purge the preceding sources. Giving\n only the alias will reselect the defined alias if none was given.\n Regexp stanza for package names can be used instead of a mirror.\n Simply use REName:pkgname.*$ for any package named beginning by pkgname).' + ] + +def usage(): + """Usage for this program.""" + print progusage + for k in range(len(longoptions)): + if longoptions[k]=='help-nroff': + continue + if k0: + x=x+" \\fI"+argstype[k]+"\\fR" + print ".TP" + print x + print explanation[k] + +def main(): + """The main function""" + apt_pkg.init_config() + try: + opts, args = getopt.getopt(sys.argv[1:], "".join(shortoptions), + longoptions) + except getopt.GetoptError: + usage() + sys.exit(1) + justlist=False + justcount=False + onlymanual=False + optiontabular=False + defsources={} + xsources=[] + xlimit=100 + cols=80 + environfile=False + home=os.getenv('HOME',default='.') + try: + f=open(home+'/.apt-origins','r') + environfile=True + for line in f: + if len(line)>1 and line[0] != '#': + s=line.rstrip('\n') + x=s.find('~') + if x!=-1: + xsources.append(s) + defsources[s[0:x]]=s + f.close() + except IOError: + True + for o,a in opts: + if o in ("-h","--help"): + usage() + sys.exit() + elif o in ("--help-nroff"): + usagenroff() + sys.exit() + elif o in ("-l","--list"): + justlist=True + elif o in ("-c","--count"): + justcount=True + elif o in ("-t","--total"): + optiontabular=True + elif o in ("-m","--manual"): + onlymanual=True + elif o in ("-L","--lines"): + xlimit=int(a) + elif o in ("-C","--columns"): + cols=int(a) + elif o in ("-o","--order"): + if (a=='none'): + xsources=[] + else: + x=a.find('~') + if x==-1 and defsources[a]: + xsources.append(defsources[a]) + else: + xsources.append(a) + else: + assert False, "unhandled option" + apt_pkg.init_system() + f = open('/dev/null', 'w') + cache=apt_pkg.Cache(apt.progress.text.OpProgress(f)) + depcache=apt_pkg.DepCache(cache) + apt_pkg.init() + origin={} + best={} + xsources.append('installed~/now/o=/l=/a=') + xsources.append('other~REName:.*$') + out=len(xsources) + count=[] + packages=[] + sources=[] + naming={} + originalpattern={} + for i in range(out): + count.append(0) + packages.append([]) + sources.append(0) + for v in xsources: + k=xsources.index(v) + xx=v.find('~') + if xx!=-1: + a=v[0:xx] + c=v[xx+1:] + else: + c=v + a=v + xx=c.find('REName:') + if xx==0: + originalpatternstring=c + c=re.compile(c[xx+7:]) + originalpattern[c]=originalpatternstring + sources[k]=c + naming[c]=a + if justlist: + heuristic=re.compile(r"(.(org|net|com)$)|(^www.)|(^ftp.[a-z]{2,3}.)|(^ftp.)") + for pkg in cache.packages: + versions=pkg.version_list + for version in versions: + if version != None: + for pfile,_ in version.file_list: + cpt=pfile.site+'/'+pfile.archive+'/o='+pfile.origin+'/l='+pfile.label+'/a='+pfile.architecture + alias_heuristic=re.sub(heuristic,'',pfile.site)+'.'+pfile.archive; + if not(cpt in naming): + naming[cpt]=alias_heuristic+":"+pfile.site + print "#other and installed are always added by this program" + print "#Check that aliases are meaningful enough and UNIQUE" + if environfile: + print "#order of your .apt-origins was not preserved" + print "#other: downloadable packages from unnamed repositories" + print "#installed: packages installed but not downloadable" + for s in sorted(naming.keys(), key=lambda x: naming[x]): + if naming[s]!='installed' and naming[s]!='other': + if type(s)==types.StringType: + print naming[s]+'~'+s + else: + print naming[s]+'~'+originalpattern[s] + sys.exit() + for pkg in sorted(cache.packages, key=lambda pkg: pkg.name): + version=pkg.current_ver + if version != None and pkg.current_state == apt_pkg.CURSTATE_INSTALLED and (not(onlymanual) or not(depcache.is_auto_installed(pkg))): + for pfile,_ in version.file_list: + cpt=pfile.site+'/'+pfile.archive+'/o='+pfile.origin+'/l='+pfile.label+'/a='+pfile.architecture + if not(cpt in naming): + naming[cpt]=cpt + where=-1 + for cptmatch in sources: + where=where+1 + if type(cptmatch)==types.StringType: + if cptmatch==cpt: + break + else: + if cptmatch.match(pkg.name): + break + if pkg.name in best: + if best[pkg.name]>where: + best[pkg.name]=where + else: + best[pkg.name]=where + for s in best.keys(): + count[best[s]]=1+count[best[s]] + packages[best[s]].append(s) + if justcount: + for k in sources: + kk=sources.index(k) + if count[kk]>0: + print '%s:%d' % (naming[k],count[kk]) + sys.exit() + else: + if optiontabular: + for k in sources: + kk=sources.index(k) + for u in sorted(packages[kk]): + print k+':'+u + else: + for k in sources: + new='' + kk=sources.index(k) + if len(packages[kk])>0: + print ','+("-" * (cols-2))+'.' + print '|'+naming[k].center(cols-2)+'|' + print '`'+("-" * (cols-2))+'\'' + if len(packages[kk])<=xlimit: + for u in sorted(packages[kk]): + if len(new)+len(u)+1<=cols: + if new!='': + new=new+' '+u + else: + new=u + else: + print new + new=u + if len(new)>0: + print new + else: + print 'Too many packages (%d). Use --tabular or --lines=X (x>=%d).' % (len(packages[kk]),len(packages[kk])) + +if __name__ == '__main__': + main() + \ No newline at end of file diff --git a/debian/apt-moreutils.install b/debian/apt-moreutils.install new file mode 100644 index 0000000..e82dac3 --- /dev/null +++ b/debian/apt-moreutils.install @@ -0,0 +1 @@ +bin/* /usr/bin diff --git a/debian/apt-moreutils.manpages b/debian/apt-moreutils.manpages new file mode 100644 index 0000000..85c5e00 --- /dev/null +++ b/debian/apt-moreutils.manpages @@ -0,0 +1 @@ +man/* diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..91f2e63 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,79 @@ +apt-moreutils (1.8) unstable; urgency=low + + * Remove useless scripts and unfinished work + * Switch to git-buildpackage + + -- Jean-Christophe Dubacq Mon, 04 Feb 2013 16:10:38 +0100 + +apt-moreutils (1.7) unstable; urgency=low + + * The format changed, so change major version + * Fix small remaining bug with apt-origins -l + + -- Jean-Christophe Dubacq Wed, 14 Mar 2012 08:25:38 +0100 + +apt-moreutils (1.6.2) unstable; urgency=low + + * apt-origins: Re-enable correct listing with apt-origins -l + + -- Jean-Christophe Dubacq Tue, 13 Mar 2012 16:52:25 +0100 + +apt-moreutils (1.6.1) unstable; urgency=low + + * apt-origins: fix bug with apt-origins -l and REName lines + + -- Jean-Christophe Dubacq Tue, 01 Mar 2011 07:57:24 +0100 + +apt-moreutils (1.6) unstable; urgency=low + + * apt-origins: add REName: stanzas syntax. + * "other" is now less important than "installed" + + -- Jean-Christophe Dubacq Sat, 29 Jan 2011 23:53:13 +0100 + +apt-moreutils (1.5) unstable; urgency=low + + * apt-moreutils: fix manpages + * apt-origins: add --manual option to list only manual packages + * apt-moreutils: simplify the help system + + -- Jean-Christophe Dubacq Thu, 25 Mar 2010 07:51:02 +0800 + +apt-moreutils (1.4) unstable; urgency=low + + * apt-moreutils: use shell help system + * dpkg-speedup: move to sbin + * dpkg-checkconf: new binary, not functional yet + + -- Jean-Christophe Dubacq Tue, 09 Mar 2010 11:01:27 +0100 + +apt-moreutils (1.3) unstable; urgency=low + + * apt-origins: Use ~/.apt-origins as configuration file + * apt-origins: stanzas now use site/o=origin/l=label + * apt-origins: aliases can be used in -o even if none was used + + -- Jean-Christophe Dubacq Sun, 21 Feb 2010 23:24:09 +0100 + +apt-moreutils (1.2) unstable; urgency=low + + * Add apt-missing to the package + * Enhance help system + * Add python dependency + * Fix apt-origins manpage + + -- Jean-Christophe Dubacq Sat, 06 Feb 2010 01:52:24 +0100 + +apt-moreutils (1.1) unstable; urgency=low + + * Update Standards-Version to 3.8.4 (no change) + * Rename package_origins to apt-origins + * Remove licence from inside scripts + + -- Jean-Christophe Dubacq Wed, 03 Feb 2010 10:20:03 +0100 + +apt-moreutils (1.0) unstable; urgency=low + + * Initial release. + + -- Jean-Christophe Dubacq Fri, 29 Jan 2010 13:18:39 +0100 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +7 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..c46e144 --- /dev/null +++ b/debian/control @@ -0,0 +1,20 @@ +Source: apt-moreutils +Section: misc +Priority: optional +Maintainer: Jean-Christophe Dubacq +Build-depends: debhelper (>= 7.0.50~) +Standards-Version: 3.8.4 +Vcs-Browser: https://www-lipn.univ-paris13.fr/projects/jcdubacq/browser/debian/trunk/apt-moreutils +Vcs-Svn: https://www-lipn.univ-paris13.fr/svn/jcdubacq/debian/trunk/apt-moreutils +Homepage: https://www-lipn.univ-paris13.fr/projects/jcdubacq/wiki/AptMoreUtils + +Package: apt-moreutils +Architecture: all +Depends: python, python-apt (>= 0.7.93~), ${misc:Depends} +Description: Miscellaneous utilities for package management + apt-origins checks in the apt sources where a package is downloadable + from, and assigns each package to an origin. It can then display how many + packages come from each source and which ones. + . + apt-missing shows missing dependencies (or recommends, or else) of installed + packages diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..71c771a --- /dev/null +++ b/debian/copyright @@ -0,0 +1,35 @@ +LICENSE FOR apt-moreutils +================================ + +This copyright notice covers all files located under the following +directories: +bin debian man +and the Makefile in the toplevel directory + +This notice is not reproduced in the various files. +This notice is a simplified BSD license. + +Copyright 2010 Jean-Christophe Dubacq. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY JEAN-CHRISTOPHE DUBACQ ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JEAN-CHRISTOPHE DUBACQ OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..cbe925d --- /dev/null +++ b/debian/rules @@ -0,0 +1,3 @@ +#!/usr/bin/make -f +%: + dh $@ diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/man/apt-missing.1 b/man/apt-missing.1 new file mode 100644 index 0000000..28f4376 --- /dev/null +++ b/man/apt-missing.1 @@ -0,0 +1,42 @@ +.TH APT\-MISSING "1" "February 2010" "1\.5" "User Commands" +.SH NAME +apt\-missing \- check installed packages for missing dependencies +.SH SYNOPSIS +.B apt\-missing [options] [packages] +.SH DESCRIPTION +.\" Add any additional description here +.PP +apt\-missing checks given packages (or all if none given) to see if they +are missing some dependency. By default, Recommends is the type of +dependency that is checked, but any other can be selected. A list of +unfulfilled dependency clauses, ordered by package and type, is output. +.SH OPTIONS +.TP +\fB\-h\fR|\fB\-\-help\fR +This help text +.TP +\fB\-d\fR|\fB\-\-depends\fR +Missing Depends or Pre\-Depends +.TP +\fB\-r\fR|\fB\-\-recommends\fR +Missing Recommends (default) +.TP +\fB\-s\fR|\fB\-\-suggests\fR +Missing Suggests +.TP +\fB\-a\fR|\fB\-\-any\fR +Missing positive dependency (as above) +.TP +\fB\-t\fR|\fB\-\-type=\fR\fIstring\fR +Arbitrary dependency type (e.g. Enhances) +.TP +\fB\-p\fR|\fB\-\-package=\fR\fIstring\fR +List of packages (all if none given) +.SH AUTHOR +Written by Jean\-Christophe Dubacq. +.SH COPYRIGHT +Copyright \(co 2010 Jean\-Christophe Dubacq. +License BSD +.br +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. diff --git a/man/apt-origins.1 b/man/apt-origins.1 new file mode 100644 index 0000000..051ffb2 --- /dev/null +++ b/man/apt-origins.1 @@ -0,0 +1,60 @@ +.TH APT\-ORIGINS "1" "February 2010" "1\.7" "User Commands" +.SH NAME +apt\-origins \- display origin of installed packages +.SH SYNOPSIS +.B apt\-origins [options] +.SH DESCRIPTION +.PP +apt\-origins checks in the apt sources where a package is downloadable +from, and assigns each package to an origin (the ordered list of sources, +found either on the command line or in a configuration file)\. It can then +display how many packages come from each source and which ones\. It also +displays not downloadable packages and packages downloadable from known +sources not considered in the ordered list of sources\. +.SH OPTIONS +.TP +\fB\-h\fR|\fB\-\-help\fR +This help text +.TP +\fB\-l\fR|\fB\-\-list\fR +Just list available distributions +.TP +\fB\-c\fR|\fB\-\-count\fR +Just display package count by origin +.TP +\fB\-m\fR|\fB\-\-manual\fR +Only display manually installed packages +.TP +\fB\-t\fR|\fB\-\-tabular\fR +Use tabular output format for origin display +.TP +\fB\-C\fR|\fB\-\-columns=\fR \fIinteger\fR +Set the number of columns of the output +.TP +\fB\-L\fR|\fB\-\-lines=\fR \fIinteger\fR +Set the maximal number of packages that can be displayed +.TP +\fB\-o\fR|\fB\-\-order=\fR \fIstring\fR +Set the order in which packages are in the distributions\. +This is a space-jointed string of stanzas like +alias1~site1/archive1/o=origin1/l=label1/a=arch1 where alias1 is the display +name of a distribution of name archive1 at site1, label1 and origin1 being the +values in the Release file. "none" will purge the preceding sources. Giving +only the alias will reselect the defined alias if none was given. +Regexp stanza for package names can be used instead of a mirror. +Simply use REName:pkgname.*$ for any package named beginning by pkgname). +.SH NOTES +Stanza format changed in version 1.7. Just append /a= to the end of your +existing lines if you upgrade from 1.6. +.SH FILES +.TP +\fB~/.apt\-origins\fR + Ordered list of stanzas alias~site/archive/o=origin/l=label +.SH AUTHOR +Written by Jean\-Christophe Dubacq. +.SH COPYRIGHT +Copyright \(co 2010 Jean\-Christophe Dubacq. +License BSD +.br +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law.