X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=billie;fp=billie;h=0000000000000000000000000000000000000000;hb=59fd5aa2a8be3b76dbc968429c457f096adfa472;hp=5d9d0035331ea6956b166853b5eef37dedf9416e;hpb=9540d873fa78598454af57f5f8a4875969ed0439;p=dak.git diff --git a/billie b/billie deleted file mode 100755 index 5d9d0035..00000000 --- a/billie +++ /dev/null @@ -1,389 +0,0 @@ -#!/usr/bin/env python - -# Prepare and maintain partial trees by architecture -# Copyright (C) 2004 Daniel Silverstone -# $Id: billie,v 1.4 2004-11-27 16:06:42 troup Exp $ - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -############################################################################### -## So Martin, do you have a quote for me yet? -## Make something damned stupid up and attribute it to me, that's okay -############################################################################### - -import pg, pwd, sys; -import utils, db_access; -import apt_pkg, logging; - -from stat import S_ISDIR, S_ISLNK, S_ISREG; -import os; -import cPickle; - -## Master path is the main repository -#MASTER_PATH = "/org/ftp.debian.org/scratch/dsilvers/master"; - -MASTER_PATH = "***Configure Billie::FTPPath Please***"; -TREE_ROOT = "***Configure Billie::TreeRootPath Please***"; -TREE_DB_ROOT = "***Configure Billie::TreeDatabasePath Please***"; -trees = [] - -############################################################################### -# A BillieTarget is a representation of a target. It is a set of archs, a path -# and whether or not the target includes source. -################## - -class BillieTarget: - def __init__(self, name, archs, source): - self.name = name; - self.root = "%s/%s" % (TREE_ROOT,name); - self.archs = archs.split(","); - self.source = source; - self.dbpath = "%s/%s.db" % (TREE_DB_ROOT,name); - self.db = BillieDB(); - if os.path.exists( self.dbpath ): - self.db.load_from_file( self.dbpath ); - - ## Save the db back to disk - def save_db(self): - self.db.save_to_file( self.dbpath ); - - ## Returns true if it's a poolish match - def poolish_match(self, path): - for a in self.archs: - if path.endswith( "_%s.deb" % (a) ): - return 1; - if path.endswith( "_%s.udeb" % (a) ): - return 1; - if self.source: - if (path.endswith( ".tar.gz" ) or - path.endswith( ".diff.gz" ) or - path.endswith( ".dsc" )): - return 1; - return 0; - - ## Returns false if it's a badmatch distswise - def distish_match(self,path): - for a in self.archs: - if path.endswith("/Contents-%s.gz" % (a)): - return 1; - if path.find("/binary-%s/" % (a)) != -1: - return 1; - if path.find("/installer-%s/" % (a)) != -1: - return 1; - if path.find("/source/") != -1: - if self.source: - return 1; - else: - return 0; - if path.find("/Contents-") != -1: - return 0; - if path.find("/binary-") != -1: - return 0; - if path.find("/installer-") != -1: - return 0; - return 1; - -############################################################################## -# The applicable function is basically a predicate. Given a path and a -# target object its job is to decide if the path conforms for the -# target and thus is wanted. -# -# 'verbatim' is a list of files which are copied regardless -# it should be loaded from a config file eventually -################## - -verbatim = [ - ]; - -verbprefix = [ - "/tools/", - "/README", - "/doc/" - ]; - -def applicable(path, target): - if path.startswith("/pool/"): - return target.poolish_match(path); - if (path.startswith("/dists/") or - path.startswith("/project/experimental/")): - return target.distish_match(path); - if path in verbatim: - return 1; - for prefix in verbprefix: - if path.startswith(prefix): - return 1; - return 0; - - -############################################################################## -# A BillieDir is a representation of a tree. -# It distinguishes files dirs and links -# Dirs are dicts of (name, BillieDir) -# Files are dicts of (name, inode) -# Links are dicts of (name, target) -############## - -class BillieDir: - def __init__(self): - self.dirs = {}; - self.files = {}; - self.links = {}; - -############################################################################## -# A BillieDB is a container for a BillieDir... -############## - -class BillieDB: - ## Initialise a BillieDB as containing nothing - def __init__(self): - self.root = BillieDir(); - - def _internal_recurse(self, path): - bdir = BillieDir(); - dl = os.listdir( path ); - dl.sort(); - dirs = []; - for ln in dl: - lnl = os.lstat( "%s/%s" % (path, ln) ); - if S_ISDIR(lnl[0]): - dirs.append(ln); - elif S_ISLNK(lnl[0]): - bdir.links[ln] = os.readlink( "%s/%s" % (path, ln) ); - elif S_ISREG(lnl[0]): - bdir.files[ln] = lnl[1]; - else: - util.fubar( "Confused by %s/%s -- not a dir, link or file" % - ( path, ln ) ); - for d in dirs: - bdir.dirs[d] = self._internal_recurse( "%s/%s" % (path,d) ); - - return bdir; - - ## Recurse through a given path, setting the sequence accordingly - def init_from_dir(self, dirp): - self.root = self._internal_recurse( dirp ); - - ## Load this BillieDB from file - def load_from_file(self, fname): - f = open(fname, "r"); - self.root = cPickle.load(f); - f.close(); - - ## Save this BillieDB to a file - def save_to_file(self, fname): - f = open(fname, "w"); - cPickle.dump( self.root, f, 1 ); - f.close(); - - -############################################################################## -# Helper functions for the tree syncing... -################## - -def _pth(a,b): - return "%s/%s" % (a,b); - -def do_mkdir(targ,path): - if not os.path.exists( _pth(targ.root, path) ): - os.makedirs( _pth(targ.root, path) ); - -def do_mkdir_f(targ,path): - do_mkdir(targ, os.path.dirname(path)); - -def do_link(targ,path): - do_mkdir_f(targ,path); - os.link( _pth(MASTER_PATH, path), - _pth(targ.root, path)); - -def do_symlink(targ,path,link): - do_mkdir_f(targ,path); - os.symlink( link, _pth(targ.root, path) ); - -def do_unlink(targ,path): - os.unlink( _pth(targ.root, path) ); - -def do_unlink_dir(targ,path): - os.system( "rm -Rf '%s'" % _pth(targ.root, path) ); - -############################################################################## -# Reconciling a target with the sourcedb -################ - -def _internal_reconcile( path, srcdir, targdir, targ ): - # Remove any links in targdir which aren't in srcdir - # Or which aren't applicable - rm = [] - for k in targdir.links.keys(): - if applicable( _pth(path, k), targ ): - if not srcdir.links.has_key(k): - rm.append(k); - else: - rm.append(k); - for k in rm: - #print "-L-", _pth(path,k) - do_unlink(targ, _pth(path,k)) - del targdir.links[k]; - - # Remove any files in targdir which aren't in srcdir - # Or which aren't applicable - rm = [] - for k in targdir.files.keys(): - if applicable( _pth(path, k), targ ): - if not srcdir.files.has_key(k): - rm.append(k); - else: - rm.append(k); - for k in rm: - #print "-F-", _pth(path,k) - do_unlink(targ, _pth(path,k)) - del targdir.files[k]; - - # Remove any dirs in targdir which aren't in srcdir - rm = [] - for k in targdir.dirs.keys(): - if not srcdir.dirs.has_key(k): - rm.append(k); - for k in rm: - #print "-D-", _pth(path,k) - do_unlink_dir(targ, _pth(path,k)) - del targdir.dirs[k]; - - # Add/update files - for k in srcdir.files.keys(): - if applicable( _pth(path,k), targ ): - if not targdir.files.has_key(k): - #print "+F+", _pth(path,k) - do_link( targ, _pth(path,k) ); - targdir.files[k] = srcdir.files[k]; - else: - if targdir.files[k] != srcdir.files[k]: - #print "*F*", _pth(path,k); - do_unlink( targ, _pth(path,k) ); - do_link( targ, _pth(path,k) ); - targdir.files[k] = srcdir.files[k]; - - # Add/update links - for k in srcdir.links.keys(): - if applicable( _pth(path,k), targ ): - if not targdir.links.has_key(k): - targdir.links[k] = srcdir.links[k]; - #print "+L+",_pth(path,k), "->", srcdir.links[k] - do_symlink( targ, _pth(path,k), targdir.links[k] ); - else: - if targdir.links[k] != srcdir.links[k]: - do_unlink( targ, _pth(path,k) ); - targdir.links[k] = srcdir.links[k]; - #print "*L*", _pth(path,k), "to ->", srcdir.links[k] - do_symlink( targ, _pth(path,k), targdir.links[k] ); - - # Do dirs - for k in srcdir.dirs.keys(): - if not targdir.dirs.has_key(k): - targdir.dirs[k] = BillieDir(); - #print "+D+", _pth(path,k) - _internal_reconcile( _pth(path,k), srcdir.dirs[k], - targdir.dirs[k], targ ); - - -def reconcile_target_db( src, targ ): - _internal_reconcile( "", src.root, targ.db.root, targ ); - -############################################################################### - -def load_config(): - global MASTER_PATH - global TREE_ROOT - global TREE_DB_ROOT - global trees - - MASTER_PATH = Cnf["Billie::FTPPath"]; - TREE_ROOT = Cnf["Billie::TreeRootPath"]; - TREE_DB_ROOT = Cnf["Billie::TreeDatabasePath"]; - - for a in Cnf.ValueList("Billie::BasicTrees"): - trees.append( BillieTarget( a, "%s,all" % a, 1 ) ) - - for n in Cnf.SubTree("Billie::CombinationTrees").List(): - archs = Cnf.ValueList("Billie::CombinationTrees::%s" % n) - source = 0 - if "source" in archs: - source = 1 - archs.remove("source") - archs = ",".join(archs) - trees.append( BillieTarget( n, archs, source ) ); - -def do_list (): - print "Master path",MASTER_PATH - print "Trees at",TREE_ROOT - print "DBs at",TREE_DB_ROOT - - for tree in trees: - print tree.name,"contains",", ".join(tree.archs), - if tree.source: - print " [source]" - else: - print "" - -def do_help (): - print """Usage: billie [OPTIONS] -Generate hardlink trees of certain architectures - - -h, --help show this help and exit - -l, --list list the configuration and exit -""" - - -def main (): - global Cnf - - Cnf = utils.get_conf() - - Arguments = [('h',"help","Billie::Options::Help"), - ('l',"list","Billie::Options::List"), - ]; - - arguments = apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv); - Cnf["Billie::Options::cake"] = ""; - Options = Cnf.SubTree("Billie::Options") - - print "Loading configuration..." - load_config(); - print "Loaded." - - if Options.has_key("Help"): - do_help(); - return; - if Options.has_key("List"): - do_list(); - return; - - - src = BillieDB() - print "Scanning", MASTER_PATH - src.init_from_dir(MASTER_PATH) - print "Scanned" - - for tree in trees: - print "Reconciling tree:",tree.name - reconcile_target_db( src, tree ); - print "Saving updated DB...", - tree.save_db(); - print "Done" - -############################################################################## - -if __name__ == '__main__': - main()