Package: devscripts Version: 2.10.7 Severity: wishlist Hi,
I'd like to propose a new script for devscripts. It's a rewrite of what used to be known as 'MultiDistroTools' (or mdt). Its use is to create 'APT trees' for several distributions, making it easy to query the status of packages in Ubuntu without using chroots, for example. Example usage: ------------------------------------------------------ [EMAIL PROTECTED]:~$ chdist create sid Now edit /home/lucas/.chdist/sid/etc/apt/sources.list Then run chdist apt-get sid update And enjoy. [EMAIL PROTECTED]:~$ vi /home/lucas/.chdist/sid/etc/apt/sources.list [EMAIL PROTECTED]:~$ chdist create gutsy Now edit /home/lucas/.chdist/gutsy/etc/apt/sources.list Then run chdist apt-get gutsy update And enjoy. [EMAIL PROTECTED]:~$ vi /home/lucas/.chdist/gutsy/etc/apt/sources.list [EMAIL PROTECTED]:~$ chdist apt-get sid update Get:1 http://ftp.debian.org unstable Release.gpg [189B] Ign http://ftp.debian.org unstable/main Translation-en_US [...] [EMAIL PROTECTED]:~$ chdist apt-get gutsy update Get:1 http://archive.ubuntu.com gutsy Release.gpg [191B] [...] [EMAIL PROTECTED]:~$ chdist apt-cache gutsy show devscripts | head -10 Package: devscripts Priority: optional Section: devel Installed-Size: 1208 Maintainer: Ubuntu Core Developers <[EMAIL PROTECTED]> Original-Maintainer: Devscripts Devel Team <[EMAIL PROTECTED]> Architecture: i386 Version: 2.10.7ubuntu1 Depends: dpkg-dev, debianutils (>= 2.0), perl (>= 5.8), sed (>= 2.95), libc6 (>= 2.6-1) Recommends: fakeroot [EMAIL PROTECTED]:~$ chdist compare-packages sid gutsy |grep "^dev" devede UNAVAIL 2.13-0.0 devel-protocols UNAVAIL 1.5 develock-el 0.34-2 0.34-2 developers-reference 3.3.8 3.3.8 devhelp 0.15-1 0.15-0ubuntu1 device-tree-compiler UNAVAIL 0.1-1 device3dfx 2007.02.06-1 2007.02.06-1 devil 1.6.7-5 1.6.7-5 devilspie 0.20.2-1 0.20.2-1build1 devio 1.2-1 1.2-1 devmapper 2:1.02.20-2 2:1.02.20-1ubuntu3 devscripts 2.10.7 2.10.7ubuntu1 devtodo 0.1.19-3 0.1.19-3 [EMAIL PROTECTED]:~$ chdist compare-versions sid gutsy |grep "^dev" devede UNAVAIL 2.13-0.0 not_in_sid devel-protocols UNAVAIL 1.5 not_in_sid develock-el 0.34-2 0.34-2 same_version developers-reference 3.3.8 3.3.8 same_version devhelp 0.15-1 0.15-0ubuntu1 newer_in_sid device-tree-compiler UNAVAIL 0.1-1 not_in_sid device3dfx 2007.02.06-1 2007.02.06-1 same_version devil 1.6.7-5 1.6.7-5 same_version devilspie 0.20.2-1 0.20.2-1build1 newer_in_gutsy devio 1.2-1 1.2-1 same_version devmapper 2:1.02.20-2 2:1.02.20-1ubuntu3 newer_in_sid devscripts 2.10.7 2.10.7ubuntu1 newer_in_gutsy devtodo 0.1.19-3 0.1.19-3 same_version ------------------------------------------------------ The main problem with my script is that it's written in ruby, and I would really hate to rewrite it in perl just to include it in devscripts. I've seen that so far, you only have sh and perl scripts. Do you have a policy against adding scripts in other languages? I've attached the script in question. I'll work on a clean patch if you agree on its inclusion despite being in ruby. Thank you, -- | Lucas Nussbaum | [EMAIL PROTECTED] http://www.lucas-nussbaum.net/ | | jabber: [EMAIL PROTECTED] GPG: 1024D/023B3F4F |
#!/usr/bin/ruby -w require 'fileutils' require 'getoptlong' $datadir = ENV['HOME'] + '/.chdist' def usage return <<-EOF Usage: chdist [options] [command] [command parameters] Options: -h, --help Show this help -d, --data-dir DIR Choose data directory (default: $HOME/.chdist/ Commands: create DIST : prepare a new tree named DIST apt-get DIST (update|source|...) : run apt-get inside DIST apt-cache DIST (show|showsrc|...) : run apt-cache inside DIST apt-rdepends DIST [...] : run apt-rdepends inside DIST src2bin DIST PKG : get binary packages for a source package in DIST bin2src DIST PKG : get source package for a binary package in DIST compare-packages DIST1 DIST2 [DIST3, ...] : list versions of packages in several DISTributions compare-versions DIST1 DIST2 : same as compare-packages, but also run dpkg --compare-versions and display where the package is newer grep-dctrl-packages DIST [...] : run grep-dctrl on *_Packages inside DIST grep-dctrl-sources DIST [...] : run grep-dctrl on *_Sources inside DIST EOF end # specify the options we accept and initialize # the option parser opts = GetoptLong.new( [ "--help", "-h", GetoptLong::NO_ARGUMENT ], [ "--data-dir", "-d", GetoptLong::REQUIRED_ARGUMENT ] ) opts.ordering = GetoptLong::REQUIRE_ORDER # process the parsed options opts.each do |opt, arg| if opt == '--help' puts usage exit(0) elsif opt == '--data-dir' $datadir = arg end end if ARGV.length == 0 puts usage exit(1) end ######################################################## def dist_check(dist) dir = $datadir + '/' + dist return true if File::directory?(dir) puts "Could not find #{dist} in $datadir. Exiting." exit(1) end def aptopts(dist) return ['-o',"Dir=#{$datadir}/#{dist}/", '-o', "Dir::State::status=#{$datadir}/#{dist}/var/lib/dpkg/status"] end def compare_versions(va, vb) return IO::popen("dpkg --compare-versions #{va} lt #{vb}; echo $?").read.to_i == 1 end ### def aptcache(args) dist_check(dist = args.shift) args = aptopts(dist) + args exec('/usr/bin/apt-cache', *args) end def aptget(args) dist_check(dist = args.shift) args = aptopts(dist) + args exec('/usr/bin/apt-get', *args) end def aptrdepends(args) dist_check(dist = args.shift) args = aptopts(dist) + args exec('/usr/bin/apt-rdepends', *args) end def bin2src(args) dist_check(dist = args[0]) args = aptopts(dist) + ['show', args[1] ] cmd = (['/usr/bin/apt-cache'] + args).join(' ') # FIXME avoid that ugly shell invocation lines = `#{cmd}` if $?.exitstatus != 0 exit($?.exitstatus) end source = lines.split(/\n/).grep(/^Source: /) if source == [] puts args[1] else puts source[0].split(' ', 2)[1] end end def src2bin(argv) dist_check(dist = argv[0]) args = aptopts(dist) + ['showsrc', argv[1] ] cmd = (['/usr/bin/apt-cache'] + args).join(' ') # FIXME avoid that ugly shell invocation lines = `#{cmd}` if $?.exitstatus != 0 exit($?.exitstatus) end bins = [] lines.split(/\n\n/).each do |lp| # avoid cases where apt-cache showsrc also shows source packages # with a binary package with that name (e.g apt-cache showsrc sm) src = lp.split(/\n/).grep(/^Package: /)[0].split(': ', 2)[1] next if src != argv[1] binaries = lp.split(/\n/).grep(/^Binary: /) if binaries != [] binaries = binaries[0].split(/: /, 2)[1] bins += binaries.split(/, /) end end puts bins.uniq.join("\n") end def dist_create(argv) dist = argv[0] dir = $datadir + '/' + dist if File::exists?(dir) puts "#{dir} already exists, exiting." exit(1) end FileUtils::mkdir_p(dir) [ '/etc/apt', '/var/lib/apt/lists/partial', '/var/lib/dpkg', '/var/cache/apt/archives/partial'].each do |d| FileUtils::mkdir_p(dir + d) end File::open(dir + '/etc/apt/sources.list', 'w') do |f| f.puts <<-EOF #deb http://ftp.debian.org/debian/ unstable main contrib non-free #deb-src http://ftp.debian.org/debian/ unstable main contrib non-free #deb http://archive.ubuntu.com/ubuntu dapper main restricted #deb http://archive.ubuntu.com/ubuntu dapper universe multiverse #deb-src http://archive.ubuntu.com/ubuntu dapper main restricted #deb-src http://archive.ubuntu.com/ubuntu dapper universe multiverse EOF end File::open(dir + '/var/lib/dpkg/status', 'w') { |f| } # empty file puts "Now edit #{dir + '/etc/apt/sources.list'}" puts "Then run chdist apt-get #{dist} update" puts "And enjoy." end def dist_compare(argv, do_compare = false) dists = [] n = 0 # read params while not argv.empty? do a = argv.shift dists[n] = a dist_check(dists[n]) n += 1 end if do_compare and n != 2 puts "Can only compare if there are two distros." exit(1) end # read Sources packages = {} dists.each do |dist| packages[dist] = {} Dir::glob($datadir + '/' + dist + '/var/lib/apt/lists/*_Sources').each do |f| pkg = nil IO::readlines(f).each do |l| if l =~ /^Package: / pkg = l.split(': ', 2)[1].chomp elsif l =~ /^Version: / packages[dist][pkg] = l.split(': ', 2)[1].chomp end end end end # output packages list dists.inject([]) { |tot, d| tot += packages[d].keys }.sort.uniq.each do |pkg| str = "#{pkg}" dists.each do |dist| if packages[dist].has_key?(pkg) str += " #{packages[dist][pkg]}" else str += " UNAVAIL" end end if do_compare # compare versions if run as compare-versions if not packages[dists[0]].has_key?(pkg) str += " not_in_#{dists[0]}" elsif not packages[dists[1]].has_key?(pkg) str += " not_in_#{dists[1]}" elsif packages[dists[0]][pkg] == packages[dists[1]][pkg] str += " same_version" elsif compare_versions(packages[dists[0]][pkg], packages[dists[1]][pkg]) str += " newer_in_#{dists[0]}" else str += " newer_in_#{dists[1]}" end end puts str end end def grep_file(argv, file) dist = argv.shift dist_check(dist) f = Dir::glob($datadir + '/' + dist + "/var/lib/apt/lists/*_#{file}").join(' ') # FIXME avoid shell invoc, potential quoting problems here exec("cat #{f} | grep-dctrl #{argv.join(' ')}") end ######################################################## # Command parsing command = ARGV.shift case command when 'create' dist_create(ARGV) when 'apt-get' then aptget(ARGV) when 'apt-cache' then aptcache(ARGV) when 'apt-rdepends' then aptrdepends(ARGV) when 'bin2src' then bin2src(ARGV) when 'src2bin' then src2bin(ARGV) when 'compare-packages' then dist_compare(ARGV) when 'compare-versions' then dist_compare(ARGV, true) when 'grep-dctrl-packages' grep_file(ARGV, 'Packages') when 'grep-dctrl-sources' grep_file(ARGV, 'Sources') else puts "Command unknown. Try #{$PROGRAM_NAME} -h" exit(1) end