Index: projects/portbuild/conf/common.conf =================================================================== --- projects/portbuild/conf/common.conf (revision 221761) +++ projects/portbuild/conf/common.conf (revision 221762) @@ -1,21 +1,20 @@ # # package building configuration file containing things that are common # both to the server-side (pointyhat instance) and the client side # (individual build clients). # # original author: linimon # # $FreeBSD: ports/Tools/portbuild/conf/common.conf,v 1.1 2010/12/01 02:35:20 linimon Exp $ # # # top-level package building things. These will probably be common # to all package build masters. # LOCALBASE=/usr/local -PKGSUFFIX=.tbz ARCHS_REQUIRING_AOUT_COMPAT="i386" ARCHS_REQUIRING_LINPROCFS="amd64 i386" ARCHS_SUPPORTING_COMPAT_IA32="amd64 i386 ia64" Index: projects/portbuild/qmanager/packagebuild =================================================================== --- projects/portbuild/qmanager/packagebuild (revision 221761) +++ projects/portbuild/qmanager/packagebuild (revision 221762) @@ -1,656 +1,671 @@ #!/usr/bin/env python # Improved build dispatcher. Invoked on server-side from dopackages. # We try to build leaf packages (those # which can be built immediately without requiring additional # dependencies to be built) in the order such that the ones required # by the longest dependency chains are built first. # # This has the effect of favouring deep parts of the package tree and # evening out the depth over time, hopefully avoiding the situation # where the entire cluster waits for a deep part of the tree to # build on a small number of machines # # We can dynamically respond to changes in build machine availability, # since the queue manager will block jobs that cannot be immediately # satisfied and will unblock us when a job slot becomes available. # # When a package build fails, it is requeued with a lower priority # such that it will rebuild again as soon as no "phase 1" packages # are available to build. This prevents the cluster staying idle # until the last phase 1 package builds. # # Other advantages are that this system is easily customizable and in # the future will let us customize things like the matching policy of # jobs to machines. For example, we could avoid dispatching multiple # openoffice builds to the same system. # # TODO: # * Combine build prep stages? # - initial check for file up-to-date # * check mtime for package staleness (cf make) # * option to skip phase 2 import os import sys pbc = os.getenv('PORTBUILD_CHECKOUT') \ if os.getenv('PORTBUILD_CHECKOUT') else "/var/portbuild" pbd = os.getenv('PORTBUILD_DATA') \ if os.getenv('PORTBUILD_DATA') else "/var/portbuild" sys.path.insert(0, '%s/lib/python' % pbc) from qmanagerclient import * from freebsd_config import * import string, threading, time, subprocess from itertools import chain from stat import * from Queue import Queue from heapq import * CONFIG_SUBDIR="conf" CONFIG_FILENAME="server.conf" config = getConfig( pbc, CONFIG_SUBDIR, CONFIG_FILENAME ) QMANAGER_MAX_JOB_ATTEMPTS = int( \ config.get( 'QMANAGER_MAX_JOB_ATTEMPTS' ) ) QMANAGER_PRIORITY_PACKAGES = string.split( \ config.get( 'QMANAGER_PRIORITY_PACKAGES' ) ) QMANAGER_RUNAWAY_PERCENTAGE = float( \ config.get( 'QMANAGER_RUNAWAY_PERCENTAGE' ) ) QMANAGER_RUNAWAY_THRESHOLD = int( \ config.get( 'QMANAGER_RUNAWAY_THRESHOLD' ) ) DEBUG = False categories = {} ports = {} +pkg_sufx = None + # When a build fails we requeue it with a lower priority such that it # will never preempt a phase 1 build but will build when spare # capacity is available. PHASE2_BASE_PRIO=1000 # Process success quickly so other jobs are started SUCCESS_PRIO = -1000 # Failure should be a less common event :) FAILURE_PRIO = -900 # Port status codes PENDING = 1 # Yet to build PHASE2 = 2 # Failed once class PriorityQueue(Queue): """Variant of Queue that retrieves open entries in priority order (lowest first). Entries are typically tuples of the form: (priority number, data) This class can be found at: Python-2.6a3/Lib/Queue.py """ maxsize = 0 def _init(self, maxsize): self.queue = [] def _qsize(self, len=len): return len(self.queue) def _put(self, item, heappush=heappush): heappush(self.queue, item) def _get(self, heappop=heappop): return heappop(self.queue) class Index(object): def __init__(self, indexfile): self.indexfile = indexfile def parse(self, targets = None): print "[MASTER] Read index" f = file(self.indexfile) index = f.readlines() f.close() f = None del f lines=[] print "[MASTER] Phase 1" for i in index: (name, path, prefix, comment, descr, maintainer, categories, bdep, rdep, www, edep, pdep, fdep) = i.rstrip().split("|") if targets is None or name in targets: lines.append((name, bdep, rdep, edep, pdep, fdep)) Port(name, path, "", "", "", "", categories, "") index = None del index print "[MASTER] Phase 2" for (name, bdep, rdep, edep, pdep, fdep) in lines: ports[name].setdeps(bdep, rdep, edep, pdep, fdep) lines = None del lines print "[MASTER] Done" def depthindex(targets): """ Initial population of depth tree """ for i in targets: i.depth_recursive() class Port(object): def __init__(self, name, path, prefix, comment, descr, maintainer, cats, www): __slots__ = ["name", "path", "prefix", "comment", "descr", "maintainer", "www", "bdep", "rdep", "edep", "pdep", "fdep", "alldep", "parents", "depth", "categories"] self.name = name self.path = path self.prefix = prefix self.comment = comment self.descr = descr self.maintainer = maintainer self.www = www + self.sufx = pkg_sufx # Populated later self.bdep = [] self.rdep = [] self.edep = [] self.pdep = [] self.fdep = [] self.alldep = [] self.parents = [] self.id = None # XXX self.status = PENDING self.attempts = 0 # Whether the package build has completed and is hanging around # to resolve dependencies for others XXX use status self.done = False # Depth is the maximum length of the dependency chain of this port self.depth = None self.categories=[] scats = cats.split() if len(scats) != len(set(scats)): print "[MASTER] Warning: port %s includes duplicated categories: %s" % (name, cats) for c in set(scats): try: cat = categories[c] except KeyError: cat = Category(c) self.categories.append(cat) cat.add(self) ports[name] = self def remove(self): """ Clean ourselves up but don't touch references in other objects; they still need to know about us as dependencies etc """ self.fdep = None self.edep = None self.pdep = None self.bdep = None self.rdep = None self.alldep = None self.parents = None for cat in self.categories: cat.remove(self) ports[self.name] = None del ports[self.name] del self def destroy(self): """ Remove a package and all references to it """ for pkg in self.alldep: if pkg.parents is not None: # Already removed but not destroyed try: pkg.parents.remove(self) except ValueError: continue for pkg in self.parents: try: pkg.fdep.remove(self) except ValueError: pass try: pkg.edep.remove(self) except ValueError: pass try: pkg.pdep.remove(self) except ValueError: pass try: pkg.bdep.remove(self) except ValueError: pass try: pkg.rdep.remove(self) except ValueError: pass pkg.alldep.remove(self) sys.exc_clear() self.remove() def setdeps(self, bdep, rdep, edep, pdep, fdep): self.fdep = [ports[p] for p in fdep.split()] self.edep = [ports[p] for p in edep.split()] self.pdep = [ports[p] for p in pdep.split()] self.bdep = [ports[p] for p in bdep.split()] self.rdep = [ports[p] for p in rdep.split()] self.alldep = list(set(chain(self.fdep, self.edep, self.pdep, self.bdep, self.rdep))) for p in self.alldep: p.parents.append(self) def depth_recursive(self): """ Recursively populate the depth tree up from a given package through dependencies, assuming empty values on entries not yet visited """ if self.depth is None: if len(self.parents) > 0: max = 0 for i in self.parents: w = i.depth_recursive() if w > max: max = w self.depth = max + 1 else: self.depth = 1 for port in QMANAGER_PRIORITY_PACKAGES: if self.name.startswith(port): # Artificial boost to try and get it building earlier self.depth = 100 return self.depth def destroy_recursive(self): """ Remove a port and everything that depends on it """ parents=set([self]) while len(parents) > 0: pkg = parents.pop() assert pkg.depth is not None parents.update(pkg.parents) pkg.destroy() def success(self): """ Build succeeded and possibly uncovered some new leaves """ parents = self.parents[:] self.done = True self.remove() newleafs = [p for p in parents if all(c.done for c in p.alldep)] return newleafs def failure(self): """ Build failed """ self.destroy_recursive() def packagename(self, arch, branch, buildid): """ Return the path where a package may be found""" - return "%s/%s/%s/builds/%s/packages/All/%s.tbz" \ - % (pbd, arch, branch, buildid, self.name) + return "%s/%s/%s/builds/%s/packages/All/%s%s" \ + % (pbd, arch, branch, buildid, self.name, self.sufx) def is_stale(self, arch, branch, buildid): """ Does a package need to be (re)-built? Returns: False: if it exists and has newer mtime than all of its dependencies. True: otherwise """ my_pkgname = self.packagename(arch, branch, buildid) pkg_exists = os.path.exists(my_pkgname) if pkg_exists: my_mtime = os.stat(my_pkgname)[ST_MTIME] dep_packages = [pkg.packagename(arch, branch, buildid) for pkg in self.alldep] deps_exist = all(os.path.exists(pkg) for pkg in dep_packages) return not (pkg_exists and deps_exist and all(os.stat(pkg)[ST_MTIME] <= my_mtime for pkg in dep_packages)) class Category(object): def __init__(self, name): self.name = name self.ports = {} categories[name] = self def add(self, port): self.ports[port] = port def remove(self, port): self.ports[port]=None del self.ports[port] def gettargets(targets): """ split command line arguments into list of packages to build. Returns set or iterable of all ports that will be built including dependencies """ plist = set() if len(targets) == 0: targets = ["all"] for i in targets: if i == "all": return ports.itervalues() if i.endswith("-all"): cat = i.rpartition("-")[0] plist.update(p.name for p in categories[cat].ports) - elif i.rstrip(".tbz") in ports: - plist.update([ports[i.rstrip(".tbz")].name]) + elif i.rstrip(pkg_sufx) in ports: + plist.update([ports[i.rstrip(pkg_sufx)].name]) else: raise KeyError, i # Compute transitive closure of all dependencies pleft=plist.copy() while len(pleft) > 0: pkg = pleft.pop() new = [p.name for p in ports[pkg].alldep] plist.update(new) pleft.update(new) for p in set(ports.keys()).difference(plist): ports[p].destroy() return [ports[p] for p in plist] class worker(threading.Thread): # Protects threads lock = threading.Lock() # Running threads, used for collecting status threads = {} def __init__(self, mach, job, arch, branch, buildid, queue): threading.Thread.__init__(self) self.machine = mach self.job = job self.arch = arch self.branch = branch self.buildid = buildid self.queue = queue self.setDaemon(True) def run(self): pkg = self.job print "[MASTER] Running job %s" % (pkg.name), if pkg.status == PHASE2: print " (phase 2)" else: print try: runenv={'HOME':"/root", 'PATH':'/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:%s/scripts' + pbc, - 'FD':" ".join(["%s.tbz" % p.name for p in pkg.fdep]), - 'ED':" ".join(["%s.tbz" % p.name for p in pkg.edep]), - 'PD':" ".join(["%s.tbz" % p.name for p in pkg.pdep]), - 'BD':" ".join(["%s.tbz" % p.name for p in pkg.bdep]), - 'RD':" ".join(["%s.tbz" % p.name for p in pkg.rdep])} + 'FD':" ".join([p.name + p.sufx for p in pkg.fdep]), + 'ED':" ".join([p.name + p.sufx for p in pkg.edep]), + 'PD':" ".join([p.name + p.sufx for p in pkg.pdep]), + 'BD':" ".join([p.name + p.sufx for p in pkg.bdep]), + 'RD':" ".join([p.name + p.sufx for p in pkg.rdep])} for var in ["NOCLEAN", "NO_RESTRICTED", "NOPLISTCHECK", "NO_DISTFILES", "FETCH_ORIGINAL", "TRYBROKEN", "PORTBUILD_CHECKOUT", "PORTBUILD_DATA" ]: if var in os.environ: runenv[var] = os.environ.get(var) build = subprocess.Popen( ["/bin/sh", "%s/scripts/pdispatch" % pbc, self.arch, self.branch, self.buildid, self.machine, - "/tmp/%s/scripts/portbuild" % self.buildid, "%s.tbz" % pkg.name, + "/tmp/%s/scripts/portbuild" % self.buildid, pkg.name + pkg.sufx, pkg.path], env=runenv, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, bufsize=0) except OSError, e: print >>sys.stderr, "[%s:%s]: Execution failed: %s" % \ (pkg.id, pkg.name, e) while True: try: line = build.stdout.readline() except: print "[%s:%s]: Failed reading from build script" % \ (pkg.id, pkg.name) break if line == "": break print "[%s:%s] %s" % (pkg.id, pkg.name, line.rstrip()) retcode = build.wait() # time.sleep(random.randint(0,60)) # # r = random.random() # if r < 0.1: # retcode = 1 # elif r < 0.15: # retcode = 254 # else: # retcode = 0 conn = QManagerClientConn(stderr = sys.stderr) timeout = 1 try: (code, vars) = conn.command("release", {'id':pkg.id}) except RequestError, e: print "[MASTER] Error releasing job %s (%s): %s" % (pkg.name, pkg.id, e.value) if DEBUG: print "[MASTER] got retcode %d from pkg %s" % (retcode, pkg.name) if retcode == 254: # Requeue soft failure at original priority # XXX exponential backoff? time.sleep(60) # print "Requeueing %s" % pkg.id self.queue.put((-pkg.depth, pkg)) elif retcode == 253: # setting up a machine, we should immediately retry self.queue.put((-pkg.depth, pkg)) elif retcode == 0: self.queue.put((SUCCESS_PRIO, pkg)) else: self.queue.put((FAILURE_PRIO, pkg)) # Clean up worker.lock.acquire() worker.threads[self]=None del worker.threads[self] worker.lock.release() @staticmethod def dispatch(mach, job, arch, branch, buildid, queue): wrk = worker(mach, job, arch, branch, buildid, queue) worker.lock.acquire() worker.threads[wrk] = wrk worker.lock.release() wrk.start() def main(arch, branch, buildid, args): - global index + global index, pkg_sufx basedir=os.path.realpath(pbd+"/"+arch+"/"+branch+"/builds/"+buildid) buildid=basedir.split("/")[-1] portsdir=basedir+"/ports" # get the major branch number. branchbase = branch.split("-")[ 0 ] # XXX ERWLA - Ugly hack branchbase = branchbase.split(".")[ 0 ] indexfile=portsdir+"/INDEX-"+branchbase + + archconfig = getConfig(pbd, arch, "portbuild.conf") + try: + branchconfig = getConfig(pbd, "%s/%s" % (arch, branch), "portbuild.conf") + archconfig.merge(branchconfig) + except: + pass + + pkg_sufx = archconfig.get('pkg_sufx') + if not pkg_sufx: + print "error: pkg_sufx not defined in portbuild.conf" + sys.exit(1) print "[MASTER] parseindex..." index = Index(indexfile) index.parse() print "[MASTER] length = %s" % len(ports) print "[MASTER] Finding targets..." targets = gettargets(args) print "[MASTER] Calculating depth..." depthindex(targets) print "[MASTER] Pruning duds..." dudsfile=basedir+"/duds" for line in file(dudsfile): try: dud = ports[line.rstrip()] except KeyError: continue print "[MASTER] Skipping %s (duds)" % dud.name dud.destroy_recursive() queue = PriorityQueue() # XXX can do this while parsing index if we prune targets/duds # first for pkg in ports.itervalues(): if len(pkg.alldep) == 0: queue.put((-pkg.depth, pkg)) # XXX check osversion, pool mdl=["arch = %s" % arch] # Main work loop completed_jobs = 0 failed_jobs = 0 while len(ports) > 0: print "[MASTER] Ports remaining=%s, Queue length=%s" % (len(ports), queue.qsize()) if len(ports) < 10: print "[MASTER] Remaining ports: %s" % ports.keys() (prio, job) = queue.get() if DEBUG: print "[MASTER] Job %s pulled from queue with prio %d" % ( job.name, prio ) if prio == SUCCESS_PRIO: print "[MASTER] Job %s succeeded" % job.name for new in job.success(): queue.put((-new.depth, new)) completed_jobs = completed_jobs + 1 continue elif prio == FAILURE_PRIO: if job.status == PHASE2: print "[MASTER] Job %s failed" % job.name job.failure() continue else: # XXX MCL 20110421 completed_jobs = completed_jobs + 1 failed_jobs = failed_jobs + 1 if DEBUG: print "[MASTER] jobs: %d failed jobs out of %d:" % \ ( failed_jobs, completed_jobs ) if completed_jobs > QMANAGER_RUNAWAY_THRESHOLD and \ float( failed_jobs ) / completed_jobs > QMANAGER_RUNAWAY_PERCENTAGE: print "[MASTER] ERROR: runaway build detected: %d failed jobs out of %d:" % \ ( failed_jobs, completed_jobs ) print "[MASTER] RUN TERMINATED." break job.attempts = job.attempts + 1 # XXX MCL in theory, if all this code worked correctly, # this condition would never trigger. In practice, # however, it does, so bomb out before filling portmgr's # mbox. # XXX MCL 20110422 perhaps this code has been fixed now; # XXX it did not use to work: if job.attempts > QMANAGER_MAX_JOB_ATTEMPTS: print "[MASTER] Job %s failed %d times; RUN TERMINATED." % ( job.name, job.attempts ) break else: # Requeue at low priority print "[MASTER] Job %s failed (requeued for phase 2)" % job.name job.status = PHASE2 queue.put((PHASE2_BASE_PRIO-job.depth, job)) continue elif job.status == PHASE2: depth = -(prio - PHASE2_BASE_PRIO) else: depth = -prio print "[MASTER] Working on job %s, depth %d" % (job.name, depth) if job.is_stale(arch, branch, buildid): conn = QManagerClientConn(stderr = sys.stderr) (code, vars) = conn.command("acquire", {"name":job.name, "type":"%s/%s/%s package" % \ (arch, branch, buildid), "priority":10, "mdl":mdl}) if code[0] == "2": machine=vars['machine'] job.id=vars['id'] # print "Got ID %s" % job.id worker.dispatch(machine, job, arch, branch, buildid, queue) else: print "[MASTER] Error acquiring job %s: %s" % (pkg.name, code) else: print "[MASTER] Skipping %s since it already exists" % job.name for new in job.success(): queue.put((-new.depth, new)) print "[MASTER] Waiting for threads" threads = worker.threads.copy() for t in threads: print "[MASTER] Outstanding thread: %s" % t.job.name for t in threads: print "[MASTER] Waiting for thread %s" % t.job.name t.join() print "[MASTER] Finished" if __name__ == "__main__": try: main(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4:]) sys.exit( 0 ) except Exception, e: # XXX MCL TODO move this above print "packagebuild: Exception:" try: print str( e ) except: pass sys.exit( 1 ) Index: projects/portbuild/scripts/buildscript =================================================================== --- projects/portbuild/scripts/buildscript (revision 221761) +++ projects/portbuild/scripts/buildscript (revision 221762) @@ -1,432 +1,433 @@ #!/bin/sh # $FreeBSD: ports/Tools/portbuild/scripts/buildscript,v 1.39 2010/06/30 14:51:47 linimon Exp $ # client-side script to actually build a package # usage: $0 DIRNAME PHASE # PHASE is 1 (checksum) or 2 (package) cleanup() { status=$1 # Don't keep distfiles if 'make checksum' failed keep_distfiles=$(make -V ALWAYS_KEEP_DISTFILES) if [ ${status} -eq 1 -o -z "${keep_distfiles}" ]; then cd ${dir} distdir=$(make -V DISTDIR) if [ ! -z "${distdir}" ]; then rm -rf ${distdir}/* fi fi if [ -e ${dir}/.keep ]; then cd ${dir} objdir=$(make -V WRKDIR) tar cfjC /tmp/work.tbz ${objdir}/.. work fi if [ ${status} -gt 0 ]; then cat /tmp/make.log${status} fi echo 1 > /tmp/status touch /.dirty echo "================================================================" echo -n "build of ${dir} ended at " date exit 0 } add_pkg() { pkgs=$* echo add_pkg $pkgs cd /tmp/depends # XXX TODO more hard-coding export PKG_PATH=/tmp/depends if [ ! -z "${pkgs}" ]; then arch=$(uname -m) echo "adding dependencies" for i in $pkgs; do echo "pkg_add $i" - base=$(basename $i .tgz) - base=$(basename $base .tbz) + base=$(basename $i ${pkg_sufx}) if pkg_info -q -e $base; then echo "skipping $base, already added" else if ! pkg_add $i; then echo "error in dependency $i, exiting" cleanup 0 fi fi done fi } del_pkg() { pkgs=$* cd /tmp/depends # XXX TODO more hard-coding export PKG_PATH=/tmp/depends if [ ! -z "${pkgs}" ]; then recursion=1 dellist="" while [ $recursion -eq 1 ]; do unset delpkg nextpkg recursion=0 for i in $pkgs; do - base=$(basename $i .tgz) - base=$(basename $base .tbz) + base=$(basename $i ${pkg_sufx}) if [ -s /var/db/pkg/${base}/+REQUIRED_BY ]; then recursion=1 nextpkg="${base} ${nextpkg}" elif [ -d /var/db/pkg/${base}/ ]; then delpkg="${base} ${delpkg}" fi done pkgs="${nextpkg}" if [ "$dellist" != "" -a "$dellist" = "$delpkg" ]; then echo "deleted list =\""$dellist"\", packages to delete ="\"$delpkg\" echo "The following packages were left behind (perhaps your dependency list is incomplete):" ls /var/db/pkg echo "error in pkg_delete, exiting" cleanup 0 else for j in ${delpkg}; do echo "Deleting ${j}" if ! (pkg_delete -f $j); then echo "--> error in pkg_delete, exiting" cleanup 0 fi done dellist=$delpkg fi done fi } dir=$1 phase=$2 ED=$3 PD=$4 FD=$5 BD=$6 RD=$7 #export PATH=/ccache/libexec/ccache/:$PATH #export CCACHE_PATH=/usr/bin:/usr/local/bin # pick up value from environment set up in portbuild script L=`echo ${LOCALBASE} | sed 's,^/,,'` Z=`ident ${dir}/Makefile | grep 'FreeBSD:' | sed 's/^[ \t]*//'` cd $dir || exit 1 restr=$(make -V RESTRICTED) + +# Inherit from environment set by portbuild. +pkg_sufx=${PKG_SUFX} # Keep restricted distfiles in a subdirectory for extra protection # against leakage if [ ! -z "$restr" ]; then # pick up value from environment set up in portbuild script echo "DISTDIR=${DISTDIR}" export DISTDIR=${DISTDIR}/RESTRICTED echo "DISTDIR=${DISTDIR}" mkdir -p ${DISTDIR} fi if [ $phase = 1 ]; then # note: if you change this header, also change processonelog and processlogs2 cd $dir || exit 1 echo "building for: $(uname -mr)" echo "maintained by: $(make maintainer)" echo "port directory: ${dir}" echo "Makefile ident: ${Z}" echo "build started at $(date)" echo "FETCH_DEPENDS=${FD}" echo "PATCH_DEPENDS=${PD}" echo "EXTRACT_DEPENDS=${ED}" echo "BUILD_DEPENDS=${BD}" echo "RUN_DEPENDS=${RD}" echo "prefixes: LOCALBASE=${L}" # Stash a copy of /etc/master.passwd and /etc/group to detect whether someone modifies it cp /etc/master.passwd /etc/master.passwd-save cp /etc/group /etc/group-save # Files we do not care about changing between pre-build and post-cleanup cat > /tmp/mtree.preexclude < /tmp/mtree.pristine add_pkg $FD cd $dir || exit 1 pkgname=$(make package-name) echo "================================================================" echo "========================================" # pick up value from environment set up in portbuild script if /pnohang ${BUILD_TIMEOUT} /tmp/make.log1 ${pkgname} make checksum; then cat /tmp/make.log1 echo "0" > /tmp/status else cleanup 1 fi else cd $dir || exit 1 pkgname=$(make package-name) echo "================================================================" echo "========================================" add_pkg ${ED} cd $dir /pnohang ${BUILD_TIMEOUT} /tmp/make.log2 ${pkgname} make extract || cleanup 2 cat /tmp/make.log2 del_pkg ${ED} # Fetch depends still need to be here for 'make extract' since that target # always reruns 'make fetch' due to the lack of fetch cookie (and no place # to put it since WRKDIR isn't created by 'make fetch') del_pkg $FD echo "================================================================" echo "========================================" add_pkg ${PD} cd $dir /pnohang ${BUILD_TIMEOUT} /tmp/make.log3 ${pkgname} make patch || cleanup 3 cat /tmp/make.log3 del_pkg ${PD} echo "================================================================" echo "========================================" add_pkg ${BD} # Files we do not care about changing between pre-build and post-cleanup cat > /tmp/mtree.buildexclude < /tmp/mtree.prebuild xvfb=0 if which -s Xvfb; then xvfb=1 pid=$(echo $$ % 32768 | bc) # XXX MCL HUH? X11BASE=$(which Xvfb | sed -e 's./bin/Xvfb..') Xvfb :${pid} -fp ${X11BASE}/lib/X11/fonts/misc & # pick up value from environment set up in portbuild script DISPLAY=${JAIL_ADDR}:${pid} export DISPLAY fi cd $dir /pnohang ${BUILD_TIMEOUT} /tmp/make.log4 ${pkgname} make build || cleanup 4 cat /tmp/make.log4 echo "================================================================" echo "========================================" cd $dir /pnohang ${BUILD_TIMEOUT} /tmp/make.log5 ${pkgname} make -k regression-test cat /tmp/make.log5 mtree -X /tmp/mtree.buildexclude -x -f /tmp/mtree.prebuild -p / | egrep -v "^(${L}/var|${L}/lib/X11/xserver/SecurityPolicy|${L}/share/nls/POSIX|${L}/share/nls/en_US.US-ASCII|etc/services|compat |usr/X11R6 |etc/manpath.config|etc/.*.bak|${L}/info/dir|${L}/lib/X11/fonts/.*/fonts\.|usr/local/man/..( |/man. )|${L}/lib/X11/fonts/TrueType|${L}/etc/gconf/gconf.xml.defaults/%gconf-tree.*.xml|var/db/fontconfig/* )" > /tmp/list.preinstall if [ -s /tmp/list.preinstall ]; then echo "================================================================" echo "Fatal error: filesystem was touched prior to 'make install' phase" cat /tmp/list.preinstall echo "================================================================" cleanup 0 fi echo "================================================================" echo "========================================" add_pkg ${RD} cat > /tmp/mtree.exclude < /tmp/mtree cd $dir if /pnohang ${BUILD_TIMEOUT} /tmp/make.log6 ${pkgname} make install; then cat /tmp/make.log6 echo "0" > /tmp/status else cleanup 6 fi echo "================================================================" echo "========================================" cd $dir if /pnohang ${BUILD_TIMEOUT} /tmp/make.log7 ${pkgname} make package; then cat /tmp/make.log7 echo "0" > /tmp/status prefix=$(make -V PREFIX) del_pkg ${pkgname} else cleanup 7 fi mtree -X /tmp/mtree.exclude -x -f /tmp/mtree -p / | egrep -v "^(${L}/var|${L}/lib/X11/xserver/SecurityPolicy|${L}/share/nls/POSIX|${L}/share/nls/en_US.US-ASCII|etc/services|compat |usr/X11R6 |etc/manpath.config|etc/.*.bak|${L}/info/dir|${L}/lib/X11/fonts/.*/fonts\.|usr/local/man/..( |/man. )|${L}/lib/X11/fonts/TrueType|${L}/etc/gconf/gconf.xml.defaults/%gconf-tree.*.xml|var/db/fontconfig/* )" > /tmp/list3 # Compare the state of the filesystem now to before the 'make install' phase dirty=0 if [ -s /tmp/list3 ]; then cd / grep ' extra$' /tmp/list3 | awk '{print $1}' | xargs -J % find % -ls > /tmp/list4 grep ' missing$' /tmp/list3 > /tmp/list5 grep -vE ' (extra|missing)$' /tmp/list3 > /tmp/list6 # pick up value from environment set up in portbuild script if [ "x${NOPLISTCHECK}" = "x" ]; then if grep -vq "$L/etc/" /tmp/list4; then echo "1" > /tmp/status dirty=1 fi if [ -s /tmp/list5 -o -s /tmp/list6 ]; then echo "1" > /tmp/status dirty=1 fi fi echo "================================================================" fi echo echo "=== Checking filesystem state" if [ -s /tmp/list4 ]; then echo "list of extra files and directories in / (not present before this port was installed but present after it was deinstalled)" cat /tmp/list4 fi if [ -s /tmp/list5 ]; then echo "list of files present before this port was installed but missing after it was deinstalled)" cat /tmp/list5 fi if [ -s /tmp/list6 ]; then echo "list of filesystem changes from before and after port installation and deinstallation" cat /tmp/list6 fi if [ "${dirty}" = 1 ]; then cleanup 0 fi # BUILD_DEPENDS and RUN_DEPENDS are both present at install-time (e.g. gmake) # Concatenate and remove duplicates BRD=$(echo $BD $RD | tr ' ' '\n' | sort -u | tr '\n' ' ') del_pkg ${BRD} cd /var/db/pkg if [ $(echo $(echo * | wc -c)) != 2 ]; then echo "leftover packages:" * del_pkg * echo "1" > /tmp/status cleanup 0 fi # Compare the state of the filesystem now to clean system (should again be clean) mtree -X /tmp/mtree.preexclude -x -f /tmp/mtree.pristine -p / | egrep -v "^(${L}/var|${L}/lib/X11/xserver/SecurityPolicy|${L}/share/nls/POSIX|${L}/share/nls/en_US.US-ASCII|etc/services|compat |usr/X11R6 |etc/manpath.config|etc/.*.bak|${L}/info/dir|${L}/lib/X11/fonts/.*/fonts\.|usr/local/man/..( |/man. )|${L}/lib/X11/fonts/TrueType )" > /tmp/list3 echo echo "=== Checking filesystem state after all packages deleted" if [ -s /tmp/list3 ]; then cd / grep ' extra$' /tmp/list3 | awk '{print $1}' | xargs -J % find % -ls > /tmp/list4 grep ' missing$' /tmp/list3 > /tmp/list5 grep -vE ' (extra|missing)$' /tmp/list3 > /tmp/list6 if [ "x${NOPLISTCHECK}" = "x" ]; then if grep -vq "$L/etc/" /tmp/list4; then #echo "1" > /tmp/status fi if [ -s /tmp/list5 ]; then #echo "1" > /tmp/status fi fi echo "================================================================" if [ -s /tmp/list4 ]; then echo "list of extra files and directories in / (not present on clean system but present after everything was deinstalled)" cat /tmp/list4 touch /.dirty fi if [ -s /tmp/list5 ]; then echo "list of files present on clean system but missing after everything was deinstalled)" cat /tmp/list5 touch /.dirty fi if [ -s /tmp/list6 ]; then echo "list of filesystem changes from before and after all port installation/deinstallation" cat /tmp/list6 touch /.dirty fi fi cmp /etc/group /etc/group-save || (echo "=== /etc/group was modified:"; diff -du /etc/group-save /etc/group) cmp /etc/master.passwd /etc/master.passwd-save || (echo "=== /etc/master.passwd was modified:"; diff -du /etc/master.passwd-save /etc/master.passwd) if [ ${xvfb} = 1 ]; then kill $(jobid %1) fi # XXX Don't keep distfiles if checksum mismatches cd ${dir} keep_distfiles=$(make -V ALWAYS_KEEP_DISTFILES) distdir=$(make -V DISTDIR) if [ -z "${keep_distfiles}" -a ! -z "${distdir}" ]; then rm -rf ${distdir}/* fi if [ -e ${dir}/.keep ]; then cd ${dir} objdir=$(make -V WRKDIR) tar cfjC /tmp/work.tbz ${objdir}/.. work fi echo "================================================================" echo -n "build of ${dir} ended at " date fi exit 0 Index: projects/portbuild/scripts/chopindex =================================================================== --- projects/portbuild/scripts/chopindex (revision 221761) +++ projects/portbuild/scripts/chopindex (revision 221762) @@ -1,55 +1,56 @@ #!/usr/bin/env python import os, sys +import re if len(sys.argv) != 3: print "%s: " % sys.argv[0] sys.exit() indexfile = sys.argv[1] pkgdir = sys.argv[2] if not pkgdir.endswith("/All"): pkgdir = pkgdir + "/All" -packages = [pkg for (pkg, ext) in map(os.path.splitext, os.listdir(pkgdir)) if ext == ".tbz"] +packages = [pkg for (pkg, ext) in map(os.path.splitext, os.listdir(pkgdir)) if re.match('[.]t[bgx]z', ext)] index=[] pkgs=[] for i in file(indexfile): out = i.rstrip().split("|") out[7] = out[7].split(" ") # build dep out[8] = out[8].split(" ") # run dep index.append(out) # Keep track of all the packages we have seen in the index. In # principle there is no need to track the build/run deps since # they will also be listed in field 0. We could add a sanity # check for this. pkgs.append(out[0]) pkgs.extend(out[7]) pkgs.extend(out[8]) used=set(pkgs) notfound=used.difference(set(packages)) # Write out the new index, stripping out the entries for missing # packages as well as dependencies from existing packages on the # missing ones. # # This is slightly dubious since it will intentionally list packages # that are present but missing dependencies on non-redistributable # things like jdk that were successfully built but removed already, so # the dependency lists will not be complete. It matches the old # chopindex.sh behaviour though. # # I think it would be better to just prune those incomplete packages # from the INDEX altogether, but I don't know if anyone is relying on # this historical behaviour. for data in index: if data[0] not in notfound: print "%s|%s|%s|%s" % ("|".join(data[:7]), " ".join([j for j in data[7] if j not in notfound]), " ".join([j for j in data[8] if j not in notfound]), "|".join(data[9:])) Index: projects/portbuild/scripts/claim-chroot =================================================================== --- projects/portbuild/scripts/claim-chroot (revision 221761) +++ projects/portbuild/scripts/claim-chroot (revision 221762) @@ -1,167 +1,167 @@ #!/bin/sh # client-side script to claim a chroot # usage: claim-chroot ${arch} ${branch} ${pkgname} ${buildid} # Care needs to be taken with the output of this script, it cannot # output anything except space-separated pairs of "keyword value". # # Keywords: # chroot : successfully claimed a chroot # setup : we own the rights to setup the build env # wait : someone else is setting up the build env # In case of other error, just exit. # XXX if the setupnode process was a single process invocation we # could use a lockf lock, and be able to tell if the setup process was # still running or died prematurely pbd=${PORTBUILD_DATA:-/var/portbuild} usage () { echo "usage: claim-chroot arch branch buildid" exit 1 } if [ $# -ne 4 ]; then usage fi arch=$1 branch=$2 buildid=$3 pkgname=$4 shift 4 # If client has just rebooted it may not have any files yet if [ ! -f /tmp/.boot_finished ]; then echo "wait boot" exit 1 fi # Do we need to set up the client after cold boot? # # NB: mkdir is being used as an atomic test-and-set operation to # provide mutual exclusion against other callers, since we only want # one of them to perform setup builddir=${pbd}/${arch}/${branch}/builds/${buildid} # Is the build environment populated? Again we only want a single # instance to gain setup rights if not. if (mkdir /tmp/.setup-${buildid} 2> /dev/null); then # The buildenv is not set up, tell the caller to do it echo "setup ${builddir}" exit 1 fi if [ ! -f ${builddir}/.ready ]; then # The buildenv is still being set up echo "wait ${builddir}" exit 1 fi . ${pbd}/${arch}/client.conf . ${pbd}/${arch}/common.conf . ${pbd}/${arch}/portbuild.conf if [ -f ${pbd}/${arch}/${branch}/builds/${buildid}/portbuild.conf ]; then . ${pbd}/${arch}/${branch}/builds/${buildid}/portbuild.conf fi . ${pbd}/${arch}/portbuild.$(hostname) buildroot=${scratchdir} -pkgname=${pkgname%.${PKGSUFFIX}} +pkgname=${pkgname%.${pkg_sufx}} chrootdir=${buildroot}/${branch}/${buildid}/chroot # Perform initial sanity checks # Check squid is running if [ ! -z "${squid_dir}" ]; then /usr/local/sbin/squid -k check 2> /dev/null status=$? if [ "${status}" != "0" ]; then touch ${scratchdir}/.squid /usr/local/etc/rc.d/squid start > /dev/null & echo "error squid" exit 1 else rm -f ${scratchdir}/.squid fi fi # Check for enough disk space df=$(df -k ${scratchdir} | tail -1 | awk '{print $4}') if [ ${df} -lt 102400 ]; then touch ${scratchdir}/.disk echo "error disk" exit 1 else rm -f ${scratchdir}/.disk fi found=0 # Look for pre-existing chroot directories that are populated and unused for dir in ${chrootdir}/*; do if [ -f ${dir}/.ready -o -f ${dir}/.dirty ]; then # Atomically claim the directory mkdir ${dir}/used 2>/dev/null || continue touch ${dir}/used/${pkgname} if [ -f ${dir}/.dirty ]; then /tmp/${buildid}/scripts/clean-chroot ${arch} ${branch} ${buildid} ${dir} 2 >/dev/null 2>/dev/null & continue fi found=1 chroot=${dir} break fi done chrootnum=$$ # If we didn't find a pre-existing directory, create and claim a new one. while [ ${found} != 1 ]; do if [ "${use_zfs}" = "1" ]; then chroot=${chrootdir}/${chrootnum} # XXX deal with failure zfs clone ${scratchdir#/}/${branch}/${buildid}/world@base ${chroot#/} mkdir ${chroot}/used elif [ "${use_md_swap}" = "1" ]; then unit=$(mdconfig -a -t swap -s ${md_size}) if [ -z "${unit}" ]; then echo "error mdconfig" exit 1 fi newfs /dev/${unit} > /dev/null chrootnum=$(echo ${unit} | sed 's,md,,') chroot=${chrootdir}/${chrootnum} mkdir -p ${chroot}/used 2>/dev/null || continue # Need to make sure that used/ is also present after mounting # the fresh md so as to not leave open any races mount -o async /dev/${unit} ${chroot}/used mkdir ${chroot}/used/used touch ${chroot}/used/used/${pkgname} umount -f ${chroot}/used mount -o async /dev/${unit} ${chroot}/ touch ${chroot}/.notready else chrootnum=$(($chrootnum+1)) chroot=${chrootdir}/${chrootnum} mkdir -p ${chrootdir} 2> /dev/null || continue mkdir ${chroot} 2>/dev/null || continue mkdir ${chroot}/used 2>/dev/null || continue touch ${chroot}/.notready fi if [ "${use_tmpfs}" = "1" ]; then mount -t tmpfs -o "size=${tmpfs_size}" foo ${chroot} mkdir ${chroot}/used 2>/dev/null || echo "ERROR: mkdir race" touch ${chroot}/.notready fi touch ${chroot}/used/${pkgname} found=1 done echo "chroot ${chroot}" Index: projects/portbuild/scripts/dopackages =================================================================== --- projects/portbuild/scripts/dopackages (revision 221761) +++ projects/portbuild/scripts/dopackages (revision 221762) @@ -1,793 +1,793 @@ #!/bin/sh # $FreeBSD: ports/Tools/portbuild/scripts/dopackages,v 1.57 2010/12/01 02:30:14 linimon Exp $ # main server-side script to run a package build # configurable variables pbc=${PORTBUILD_CHECKOUT:-/var/portbuild} pbd=${PORTBUILD_DATA:-/var/portbuild} PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:${pbc}/scripts # writable by portmgr umask 002 journalname="journal" usage () { echo "usage: arch branch buildid datestamp [-incremental] [-continue] [-restart] [-nofinish] [-finish] [-nocleanup] [-keep] [-nobuild] [-noindex] [-noduds] [-norestr] [-nochecksubdirs] [-nosrc] [-srcvcs] [-noports] [-portsvcs] [-noplistcheck] [-nodistfiles] [-fetch-original] [-cdrom] [-trybroken] [-target ]" # XXX MCL I think it's going to be too hard to move the create in here, now. echo " -incremental : Start a new incremental build" echo " -continue : Restart an interrupted build, skipping failed ports" echo " -restart : Restart an interrupted build, rebuilding failed ports" echo " -nofinish : Do not post-process upon build completion" echo " -finish : Post-process a completed build" echo " -nocleanup : Do not clean up and deactivate the build once it finishes" echo " -keep : Do not automatically recycle this build" echo " -nobuild : Only do the build preparation steps, do not build packages" echo " -noindex : Do not build the INDEX" echo " -noduds : Do not build the duds file" echo " -nochecksubdirs : Do not check the SUBDIRS" echo " -norestr : Do not build the restricted.sh file" echo " -nosrc : Do not update the src tree" echo " -srcvcs : Update the src tree via CVS, don't use a pre-existing snapshot" echo " -noports : Do not update the ports tree" echo " -portsvcs : Update the ports tree via CVS, don't use a pre-existing snapshot" echo " -noplistcheck : Don't check the plist during the build" echo " -nodistfiles : Don't collect distfiles" echo " -fetch-original : Fetch from original MASTER_SITE" echo " -cdrom : Prepare a build for distribution on CDROM " echo " -trybroken : Try to build BROKEN ports" echo " -target : Build ports listed in file, rather than the whole ports tree" exit 1 } if [ $# -lt 4 ]; then usage fi arch=$1 branch=$2 buildid=$3 datestamp=$4 shift 4 . ${pbc}/conf/server.conf . ${pbc}/conf/common.conf . ${pbc}/scripts/buildenv validate_env ${arch} ${branch} || usage # XXX MCL too early to do this here. buildid=$(resolve ${pbd} ${arch} ${branch} ${buildid}) if [ -z "${buildid}" ]; then echo "Invalid build ID ${buildid}" exit 1 fi if [ -f ${pbd}/${arch}/portbuild.conf ]; then . ${pbc}/conf/server.conf . ${pbd}/${arch}/portbuild.conf else usage fi pbab=${pbd}/${arch}/${branch} trap "exit 1" 1 2 3 9 10 11 15 mailexit () { echo | mail -s "$(basename $0) ended for ${arch}-${branch} ${buildid} at $(date)" ${mailto} exit $1 } srctar() { rm -f ${builddir}/src-2*.tbz* tar cfCj ${builddir}/src-${buildid}.tbz ${builddir} src/ 2>/dev/null md5 ${builddir}/src-${buildid}.tbz > ${builddir}/src-${buildid}.tbz.md5 } portstar() { rm -f ${builddir}/ports-2*.tbz* tar cfCj ${builddir}/ports-${buildid}.tbz ${builddir} ports/ 2>/dev/null md5 ${builddir}/ports-${buildid}.tbz > ${builddir}/ports-${buildid}.tbz.md5 } # usage: makeindex pb arch branch builddir [target] # note: can take ~24 minutes! makeindex () { pbc=$1 arch=$2 branch=$3 buildid=$4 builddir=$5 target=$6 cd ${builddir}/ports echo "================================================" echo "generating index" echo "================================================" echo "index generation started at $(date)" ${pbc}/scripts/makeindex ${arch} ${branch} ${buildid} ${target} || return 1 echo "index generation ended at $(date)" echo $(wc -l ${INDEXFILE} | awk '{print $1}') "lines in INDEX" # Save a copy of it for the next build since ports directories may # not be preserved cp ${INDEXFILE} ${builddir}/bak } # usage: checkindex builddir # Perform some sanity checks on the INDEX so we don't blow up later on checkindex () { builddir=$1 cd ${builddir}/ports if [ ! -f ${INDEXFILE} ]; then echo "misssing INDEXFILE ${INDEXFILE} in ${builddir}/ports" return 1 fi if grep -q non-existent ${INDEXFILE}; then echo "errors in INDEX:" grep -n non-existent ${INDEXFILE} return 1 fi if ! awk -F '|' '{if (NF != 13) { error=1; printf("line %d: %s\n", NR, $0)}} END {if (error == 1) exit(1)}' ${INDEXFILE}; then echo "error in INDEX" return 1 fi } # usage: makeduds pb arch branch builddir [target] # note: can take ~21 minutes! makeduds () { pbc=$1 arch=$2 branch=$3 buildid=$4 builddir=$5 target=$6 cd ${builddir}/ports echo "================================================" echo "generating duds" echo "================================================" echo "duds generation started at $(date)" if [ -e ${builddir}/duds ]; then cp -p ${builddir}/duds ${builddir}/duds.old fi if ! ${pbc}/scripts/makeduds ${arch} ${branch} ${buildid} ${target}; then echo "error(s) detected, exiting script at $(date). Failed duds list was:" cat ${builddir}/duds mailexit 1 fi echo "duds generation ended at $(date)" echo $(wc -l ${builddir}/duds | awk '{print $1}') "items in duds" if [ -f ${builddir}/duds.old ]; then echo "duds diff:" diff ${builddir}/duds.old ${builddir}/duds else echo "no previous duds to compare against." fi cp -p ${builddir}/duds ${builddir}/duds.orig } # usage: restrictedlist pb arch branch builddir [target] # note: can take ~25 minutes! restrictedlist () { pbc=$1 arch=$2 branch=$3 buildid=$4 builddir=$5 target=$6 cd ${builddir}/ports echo "================================================" echo "creating restricted list" echo "================================================" echo "restricted list generation started at $(date)" ${pbc}/scripts/makerestr ${arch} ${branch} ${buildid} ${target} || return 1 echo "restricted list generation ended at $(date)" echo $(grep -c '^#' ${builddir}/restricted.sh) "ports in ${builddir}/restricted.sh" } # usage: cdromlist pb arch branch builddir # note: can take ~48 minutes! cdromlist () { pbc=$1 arch=$2 branch=$3 builddir=$4 cd ${builddir}/ports echo "================================================" echo "creating cdrom list" echo "================================================" echo "cdrom list generation started at $(date)" make ECHO_MSG=true clean-for-cdrom-list \ | sed -e "s./usr/ports/distfiles/./distfiles/.g" \ -e "s./usr/ports/./${branch}/.g" \ > ${builddir}/cdrom.sh echo "cdrom list generation ended at $(date)" echo $(grep -c '^#' ${builddir}/cdrom.sh) "ports in ${builddir}/cdrom.sh" } # XXX Should use SHA256 instead, but I'm not sure what consumes this file (if anything) # XXX Should generate these as the packages are copied in, instead of all at once at the end # usage: generatemd5 pb arch branch builddir generatemd5 () { pbc=$1 arch=$2 branch=$3 builddir=$4 echo "started generating CHECKSUM.MD5 at $(date)" cd ${builddir}/packages/All - find . -name '*.tbz' | sort | sed -e 's/^..//' | xargs md5 > CHECKSUM.MD5 + find . -name "*${pkg_sufx}" | sort | sed -e 's/^..//' | xargs md5 > CHECKSUM.MD5 echo "ended generating CHECKSUM.MD5 at $(date)" } dobuild() { pbc=$1 arch=$2 branch=$3 builddir=$4 echo "================================================" echo "building packages" echo "================================================" echo "started at $(date)" start=$(date +%s) ${pbc}/qmanager/packagebuild ${arch} ${branch} ${buildid} > ${builddir}/${journalname} 2>&1 < /dev/null result=$? if [ $result -ne 0 ]; then echo "ERROR: packagebuild ${arch} ${branch} ${buildid} failed: see ${builddir}/${journalname} for details" fi echo "ended at $(date)" end=$(date +%s) echo "Build took $(date -u -j -r $((end - start)) | awk '{print $4}')" - echo $(ls -1 ${builddir}/packages/All | grep tbz | wc -l) "packages built" + echo $(ls -1 ${builddir}/packages/All | grep ${pkg_sufx} | wc -l) "packages built" echo $(wc -l ${PORTSDIR}/${INDEXFILE} | awk '{print $1}') "lines in INDEX" echo $(echo $(du -sk ${builddir}/packages | awk '{print $1}') / 1024 | bc) "MB of packages" echo $(echo $(du -sk ${builddir}/distfiles | awk '{print $1}') / 1024 | bc) "MB of distfiles" cd ${builddir} if grep -qE '(ptimeout|pnohang): killing' ${journalname}; then echo "The following port(s) timed out:" grep -E '(ptimeout|pnohang): killing' ${journalname} | sed -e 's/^.*ptimeout:/ptimeout:/' -e 's/^.*pnohang:/pnohang:/' fi } me=$(hostname) starttime=$(date +%s) echo "Subject: $me package building logs" echo echo "Called with arguments: $@" echo "Started at ${starttime}" nobuild=0 noindex=0 noduds=0 nosrc=0 srcvcs=0 noports=0 portsvcs=0 norestr=0 nochecksubdirs=0 noplistcheck=0 cdrom=0 restart=0 cont=0 finish=0 nofinish=0 nodistfiles=0 fetch_orig=0 trybroken=0 incremental=0 keep=0 nocleanup=0 # optional arguments while [ $# -gt 0 ]; do case "x$1" in x-nobuild) nobuild=1 ;; x-noindex) noindex=1 ;; x-noduds) noduds=1 ;; x-cdrom) cdrom=1 ;; x-nosrc) nosrc=1 ;; x-srccvs|x-srcvcs) srcvcs=1 ;; x-noports) noports=1 ;; x-portscvs|x-portsvcs) portsvcs=1 ;; x-norestr) norestr=1 ;; x-nochecksubdirs) nochecksubdirs=1 ;; x-noplistcheck) noplistcheck=1 ;; x-nodistfiles) nodistfiles=1 ;; x-fetch-original) fetch_orig=1 ;; x-trybroken) trybroken=1 ;; x-continue) cont=1 ;; x-restart) restart=1 ;; x-nofinish) nofinish=1 ;; x-finish) nobuild=1 finish=1 ;; x-incremental) incremental=1 ;; x-keep) keep=1 ;; x-nocleanup) nocleanup=1 ;; x-target) shift target=$(realpath $1) ;; *) usage ;; esac shift done if [ "$restart" = 1 -o "$cont" = 1 -o "$finish" = 1 ]; then skipstart=1 else skipstart=0 fi # XXX check for conflict between -noports and -portsvcs etc # We have valid options, start the build if [ "$nodistfiles" = 1 ]; then export NO_DISTFILES=1 fi if [ "$noplistcheck" = 1 ]; then export NOPLISTCHECK=1 fi if [ "$cdrom" = 1 ]; then export FOR_CDROM=1 fi if [ "$fetch_orig" = 1 ]; then export FETCH_ORIGINAL=1 fi if [ "$trybroken" = 1 ]; then export TRYBROKEN=1 fi builddir=${pbab}/builds/${buildid} # bomb out if there are no bindist files if [ ! -f ${builddir}/bindist.tbz -o ! -f ${builddir}/bindist.tbz.md5 ]; then echo "missing bindist.tbz and/or bindist.tbz.md5; exiting script at $(date)." mailexit 1 fi # Start setting up build environment if [ "${skipstart}" -eq 0 ]; then newbuildid=${datestamp} # this is where the latest/previous dance is performed # MCL note 20091109: buildid must exist. For now, use the following # MCL manual command to start new buildenvs, before the first use of # MCL dopackages: "build create arch branch" build clone ${arch} ${branch} ${buildid} ${newbuildid} buildid=${newbuildid} builddir=${pbab}/builds/${buildid} fi # bomb out if build clone failed if [ ! -d ${builddir} ]; then mailexit 1 fi # Set up our environment variables buildenv ${pbd} ${arch} ${branch} ${builddir} # XXX MCL might not return 'latest' ??? echo | mail -s "$(basename $0) started for ${arch}-${branch} ${buildid} at $(date)" ${mailto} # make necessary subdirectories if they don't exist mkdir -p ${builddir}/bak/restricted || mailexit 1 if [ "${keep}" -eq 1 ]; then touch ${builddir}/.keep fi # Mark as active so that it is not automatically cleaned up on the # clients touch ${builddir}/.active # Update link to current logfile created by dopackages.wrapper ln -sf ${pbd}/${arch}/archive/buildlogs/log.${branch}.${datestamp} \ ${builddir}/build.log # Update build-specific portbuild.conf. if [ -f ${pbd}/${arch}/${branch}/portbuild.conf ]; then ln -sf ${pbd}/${arch}/${branch}/portbuild.conf ${builddir}/portbuild.conf . ${builddir}/portbuild.conf fi if [ "$skipstart" = 0 ]; then # Update build if [ "$incremental" = 1 ]; then # Stash a copy of the index since we may be about to replace # it with the ZFS update if [ -f ${PORTSDIR}/${INDEXFILE} ]; then cp ${PORTSDIR}/${INDEXFILE} ${builddir}/bak/${INDEXFILE} fi fi if [ ${noports} -eq 0 ]; then if [ -L ${builddir}/ports -o ${portsvcs} -eq 1 ]; then echo "================================================" echo "updating ${PORTSDIR} from ${VCS}" echo "================================================" cd ${PORTSDIR} updated=$(date '+%Y/%m/%d %H:%M') echo ${updated} > ${builddir}/.updated ${VCS} ${VCS_UPDATE_DATE} "${updated}" # XXX Check for conflicts else # echo "XXX at build portsupdate portsupdate ${arch} ${branch} ${buildid} $@ " build portsupdate ${arch} ${branch} ${buildid} $@ # echo "XXX past build portsupdate portsupdate ${arch} ${branch} ${buildid} $@ " fi else # XXX MCL why??? # XXX rm -f ${builddir}/.updated fi if [ "$incremental" = 1 ]; then if [ -f ${builddir}/bak/${INDEXFILE} ]; then cp ${builddir}/bak/${INDEXFILE} ${PORTSDIR}/${INDEXFILE}.old fi fi # Create tarballs for distributing to clients. Should not cause # much extra delay because we will do this in conjunction with # recursing over the ports tree anyway just below, and might have # just finished vcs updating, so it is likely to be in cache. portstar & if [ ${nosrc} -eq 0 ]; then if [ -L ${builddir}/src -o ${srcvcs} -eq 1 ]; then echo "================================================" echo "updating ${SRC_BASE} from ${VCS}" echo "================================================" cd ${SRC_BASE} if [ -z "${updated}" ]; then # Don't overwrite/create .updated if we didn't set it # with the ports update updated=$(date) fi ${VCS} ${VCS_UPDATE_ARGS} "${updated}" # XXX Check for conflicts else build srcupdate ${arch} ${branch} ${buildid} $@ fi fi srctar & # Begin build preprocess cd ${PORTSDIR} if [ "$nochecksubdirs" = 0 ]; then echo "================================================" echo "running make checksubdirs" echo "================================================" make checksubdirs fi # XXX MCL could background these? # not run in background to check return status if [ "$noindex" = 0 ]; then makeindex ${pbc} ${arch} ${branch} ${buildid} ${builddir} ${target} || mailexit 1 fi checkindex ${builddir} || mailexit 1 if [ "$noduds" = 0 ]; then makeduds ${pbc} ${arch} ${branch} ${buildid} ${builddir} ${target} || mailexit 1 fi wait # for tar creation if [ "$trybroken" = 1 ]; then echo "================================================" echo "pruning stale entries from the failed ports list" echo "================================================" # XXX failure and newfailure are arch/branch-global for now. We # will need to work out how to deal with updates from # concurrent builds though (one build may fail after a more # recent build has fixed the breakage) if [ -f ${pbab}/failure ]; then cp ${pbab}/failure ${builddir}/bak/ fi if [ -f ${pbab}/newfailure ]; then cp ${pbab}/newfailure ${builddir}/bak/ fi lockf -k ${pbab}/failure.lock ${pbc}/scripts/prunefailure ${arch} ${branch} ${builddir} fi # XXX These can happen after build start if [ "$norestr" = 0 ]; then restrictedlist ${pbc} ${arch} ${branch} ${buildid} ${builddir} ${target} & job_restrictedlist=$! fi if [ "$cdrom" = 1 ]; then cdromlist ${pbc} ${arch} ${branch} ${builddir} & job_cdromlist=$! fi cd ${builddir} if [ -d distfiles ]; then mv distfiles .distfiles~ rm -rf .distfiles~ & fi mkdir -p distfiles/ olderrors=$(readlink ${builddir}/errors) oldlogs=$(readlink ${builddir}/logs) # XXX MCL hardcoding of archive/errorlogs newerrors=${pbd}/${arch}/archive/errorlogs/e.${branch}.${buildid} newlogs=${pbd}/${arch}/archive/errorlogs/a.${branch}.${buildid} # Cycle out the previous symlinks rm -f bak/errors rm -f bak/logs if [ -e errors ]; then mv errors bak/ fi if [ -e logs ]; then mv logs bak/ fi # Create new log directories for archival rm -rf ${newerrors} mkdir -p ${newerrors} ln -sf ${newerrors} ${builddir}/errors rm -rf ${newlogs} mkdir -p ${newlogs} ln -sf ${newlogs} ${builddir}/logs echo "error logs in ${newerrors}" if [ -f "${builddir}/.updated" ]; then cp -p ${builddir}/.updated ${newerrors}/.updated cp -p ${builddir}/.updated ${newlogs}/.updated else rm -f ${newerrors}/.updated ${newlogs}/.updated fi cp -p ${builddir}/duds ${newerrors}/duds cp -p ${builddir}/duds ${newlogs}/duds if [ -f "${builddir}/duds.verbose" ]; then cp -p ${builddir}/duds.verbose ${newerrors}/duds.verbose cp -p ${builddir}/duds.verbose ${newlogs}/duds.verbose fi cp -p ${builddir}/ports/${INDEXFILE} ${newerrors}/INDEX cp -p ${builddir}/ports/${INDEXFILE} ${newlogs}/INDEX if [ "$incremental" = 1 ]; then # Copy back in the restricted packages that were saved after the # previous build if [ -d ${builddir}/bak/restricted/ ]; then cd ${builddir}/bak/restricted find . | cpio -dumpl ${builddir} fi cd ${builddir} # Create hardlinks to previous set of logs if [ ! -z "${oldlogs}" -a -d ${oldlogs} ]; then cd ${oldlogs} && find . -name \*.log\* | cpio -dumpl ${newlogs} fi if [ ! -z "${olderrors}" -a -d ${olderrors} ]; then cd ${olderrors} && find . -name \*.log\* | cpio -dumpl ${newerrors} fi # Identify the ports that have changed and thus whose packages # need to be removed before rebuilding cd ${PORTSDIR} if [ -f ${INDEXFILE}.old ]; then cut -f 1,2,3,8,9,11,12,13 -d \| ${INDEXFILE}.old | sort > ${INDEXFILE}.old1 cut -f 1,2,3,8,9,11,12,13 -d \| ${INDEXFILE} | sort > ${INDEXFILE}.1 comm -2 -3 ${INDEXFILE}.old1 ${INDEXFILE}.1 | cut -f 1 -d \| > ${builddir}/.oldports echo "Removing $(wc -l ${builddir}/.oldports | awk '{print $1}') packages in preparation for incremental build" rm ${INDEXFILE}.old1 ${INDEXFILE}.1 cd ${PACKAGES}/All - sed "s,$,${PKGSUFFIX}," ${builddir}/.oldports | xargs rm -f + sed "s,$,${pkg_sufx}," ${builddir}/.oldports | xargs rm -f # XXX MCL takes an unknown period of time. # XXX MCL return value not checked. ${pbc}/scripts/prunepkgs ${PORTSDIR}/${INDEXFILE} ${PACKAGES} cd ${builddir}/errors/ sed "s,\$,.log," ${builddir}/.oldports | xargs rm -f sed "s,\$,.log.bz2," ${builddir}/.oldports | xargs rm -f cd ${builddir}/logs/ sed 's,$,.log,' ${builddir}/.oldports | xargs rm -f sed 's,$,.log.bz2,' ${builddir}/.oldports | xargs rm -f fi else cd ${builddir} if [ -d packages ]; then # echo "XXX at mv packages .packages~" mv packages .packages~ rm -rf .packages~ & # echo "XXX past mv packages .packages~" fi mkdir -p packages/All fi wait $job_restrictedlist || mailexit 1 wait $job_cdromlist || mailexit 1 fi # if [ "$skipstart" = 0 ] # only need to wait for some tasks, so this is probably redundant. wait if [ "$nobuild" = 0 ]; then cd ${builddir} if [ "$cont" = 1 ]; then find errors/ -name \*.log | sed -e 's,\.log$,,' -e 's,^errors/,,' > duds.errors cat duds duds.errors | sort -u > duds.new mv duds.new duds else cp duds.orig duds fi # Compile ptimeout. /usr/bin/gcc -o ${builddir}/ptimeout -Wall ${pbc}/sources/ptimeout.c dobuild ${pbc} ${arch} ${branch} ${builddir} fi # Clean up temporary duds file if [ "$cont" = 1 ]; then cp duds.orig duds fi cd ${builddir}/packages/All if [ "$nofinish" = 0 ]; then if [ "$norestr" = 0 ]; then # Before deleting restricted packages, save a copy so we don't # have to rebuild them next time ${pbc}/scripts/keeprestr ${arch} ${branch} ${buildid} else rm -rf ${builddir}/bak/restricted/ fi # Always delete restricted packages/distfiles since they're # published on the website echo "deleting restricted ports" sh ${builddir}/restricted.sh if [ "$cdrom" = 1 ]; then echo "deleting cdrom restricted ports" sh ${builddir}/cdrom.sh fi # Remove packages not listed in INDEX ${pbc}/scripts/prunepkgs ${builddir}/ports/${INDEXFILE} ${builddir}/packages fi # XXX Checking for bad packages should be done after the package is uploaded #rm -rf ${builddir}/bad #mkdir -p ${builddir}/bad #echo "checking packages" -#for i in *${PKGSUFFIX}; do +#for i in *${pkg_sufx}; do # if ! ${PKGZIPCMD} -t $i; then # echo "Warning: package $i is bad, moving to ${builddir}/bad" # # the latest link will be left behind... # mv $i ${builddir}/bad # rm ../*/$i # fi #done if [ "$nofinish" = 0 ]; then generatemd5 ${pbc} ${arch} ${branch} ${builddir} & # Remove INDEX entries for packages that do not exist ${pbc}/scripts/chopindex ${builddir}/ports/${INDEXFILE} ${builddir}/packages > ${builddir}/packages/INDEX # Copy UPDATING and MOVED into the packages folder cp ${builddir}/ports/UPDATING ${builddir}/packages/UPDATING cp ${builddir}/ports/MOVED ${builddir}/packages/MOVED for f in INDEX MOVED UPDATING; do bzip2 -k ${builddir}/packages/$f md5 ${builddir}/packages/$f.bz2 > ${builddir}/packages/$f.bz2.md5 sha256 ${builddir}/packages/$f.bz2 > ${builddir}/packages/$f.bz2.sha256 done ls -asFlrt ${builddir}/packages/All > ${builddir}/logs/ls-lrt cp -p ${builddir}/${journalname} ${builddir}/logs echo "================================================" echo "copying distfiles" echo "================================================" echo "started at $(date)" cd ${builddir} ${pbc}/scripts/dodistfiles ${arch} ${branch} ${buildid} # Always delete restricted distfiles echo "deleting restricted distfiles" sh ${builddir}/restricted.sh if [ "$cdrom" = 1 ]; then echo "deleting cdrom restricted distfiles" sh ${builddir}/cdrom.sh fi wait fi if [ "${nocleanup}" -eq 1 ]; then echo "Not cleaning up build, when you are finished be sure to run:" echo " ${pbc}/scripts/build cleanup ${arch} ${branch} ${buildid} -full" else ${pbc}/scripts/build cleanup ${arch} ${branch} ${buildid} -full fi endtime=$(date +%s) echo "================================================" echo "all done at $(date)" echo "entire process took $(date -u -j -r $(($endtime - $starttime)) | awk '{print $4}')" echo "================================================" exit 0 Index: projects/portbuild/scripts/dopackagestats =================================================================== --- projects/portbuild/scripts/dopackagestats (revision 221761) +++ projects/portbuild/scripts/dopackagestats (revision 221762) @@ -1,386 +1,386 @@ #!/bin/sh # $FreeBSD: ports/Tools/portbuild/scripts/dopackagestats,v 1.33 2010/08/16 23:59:32 linimon Exp $ # # create HTML showing numbers of packages vs errors. Run this in a directory # accessible to the web server. # pbc=${PORTBUILD_CHECKOUT:-/var/portbuild} pbd=${PORTBUILD_DATA:-/var/portbuild} . ${pbc}/conf/server.conf here=`pwd` tmp=`basename $0 | sed -e "s/^do//"`".html" OUTFILE="${here}/${tmp}" TMPFILE="${here}/.${tmp}" #journalname="make" journalname="journal" # stylesheet seems like overkill for something this simple TABLEBGCOLOR="#F0F0F0" THCOLOR="#E0E0FF" TDCOLOR_DONE="lightgreen" TDCOLOR_NOT_DONE="lightyellow" # subroutines write_header () { echo "" > ${TMPFILE} echo "" >> ${TMPFILE} echo "FreeBSD package building statistics" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "

FreeBSD package building statistics

" >> ${TMPFILE} echo "

as of `date`

" >> ${TMPFILE} } write_table_begin () { echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} # MCL removed 20090808 -- this takes way too long # echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} } write_row () { # first, gather data arch=$1 build=$2 directory=${pbd}/${arch}/${build}/builds/latest journal=${directory}/${journalname} branch=`echo $build | awk -F '-' '{print $1}'` if [ "$branch" = "4" ]; then indexfile=$directory/ports/INDEX else indexfile=$directory/ports/INDEX-$branch fi # work around the fact that 5-exp is really 6-exp-prime if [ ! -f $indexfile ]; then if [ -d $directory/ports ]; then indexfile=$directory/ports/`cd $directory/ports 2> /dev/null && ls INDEX* 2> /dev/null | head -1` else # work around the fact that 4 is EOL and thus has no ports/ directory indexfile=$directory/logs/`cd $directory/logs 2> /dev/null && ls INDEX* 2> /dev/null | head -1` fi fi # column: date of ports update have_updated="" updated="" if [ -f $directory/ports/.updated ]; then updated="$(cat $directory/ports/.updated | awk '{printf("%s %s\n",$2,$3)}')" if [ ! -z "$updated" ]; then have_updated="yes" fi fi # column: datestamp and URL of latest log have_latest="" latest="" # MCL removed 20090808 -- this takes way too long # if [ -d $directory/logs ]; then # latest_suffix="$(cd $directory/logs 2> /dev/null && ls -rtTl | grep '\.log' | tail -1 | awk '{printf("%s\">%s %s\n",$10,$6,$7)}')" # if [ -z "$latest_suffix" ]; then # latest="" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} # MCL removed 20090808 -- this takes way too long # echo "" >> ${TMPFILE} # note: ports/INDEX-n is copied to a file called errorlogs/INDEX echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} } write_table_end () { echo "
 updatedlatest logINDEXbuild logspackageserrorsskippednot yet builtqueue lengthrunning?completed?
$arch-$build" >> ${TMPFILE} if [ ! -z "$have_updated" ]; then echo "" >> ${TMPFILE} echo "$updated" >> ${TMPFILE} else echo " " >> ${TMPFILE} fi echo "" >> ${TMPFILE} # if [ ! -z "$have_latest" ]; then # echo "$latest" >> ${TMPFILE} # else # echo " " >> ${TMPFILE} # fi # echo "" >> ${TMPFILE} if [ ! -z "$have_index" ]; then echo "" >> ${TMPFILE} echo "$n_index" >> ${TMPFILE} else echo " " >> ${TMPFILE} fi echo "" >> ${TMPFILE} if [ ! -z "$have_logs" ]; then echo "" >> ${TMPFILE} echo "$n_logs" >> ${TMPFILE} else echo " " >> ${TMPFILE} fi echo "" >> ${TMPFILE} if [ ! -z "$have_packages" ]; then echo "" >> ${TMPFILE} echo "$n_packages" >> ${TMPFILE} else echo " " >> ${TMPFILE} fi echo "" >> ${TMPFILE} if [ ! -z "$have_errors" ]; then echo "" >> ${TMPFILE} echo "$n_errors" >> ${TMPFILE} else echo " " >> ${TMPFILE} fi echo "" >> ${TMPFILE} if [ ! -z "$have_duds" ]; then echo "" >> ${TMPFILE} echo "$n_duds" >> ${TMPFILE} else echo " " >> ${TMPFILE} fi echo "" >> ${TMPFILE} if [ ! -z "$m_not_yet_built" ]; then echo "$n_not_yet_built" >> ${TMPFILE} else echo " " >> ${TMPFILE} fi echo "" >> ${TMPFILE} if [ ! -z "$queue_length" ]; then echo "$queue_length" >> ${TMPFILE} else echo " " >> ${TMPFILE} fi echo "$running_flag$completed_flag
" >> ${TMPFILE} echo "
" >> ${TMPFILE} } write_footer () { echo "

explanation of columns:

" >> ${TMPFILE} echo "
    " >> ${TMPFILE} # MCL removed 20090808 -- this takes way too long #echo "
  • latest log is the date of the latest logfile.
  • " >> ${TMPFILE} echo "
  • updated is the date of the latest tree update done by the script. It may be inaccurate if a manual checkout was done later.
  • " >> ${TMPFILE} echo "
  • INDEX is number of ports in the INDEX file built from the latest tree update.
  • " >> ${TMPFILE} echo "
  • build logs is number of packages attempted. Note: if a run was restarted, you may see duplicates here.
  • " >> ${TMPFILE} echo "
  • packages is number of packages successfully built. Note: if a run was restarted, you may see duplicates here.
  • " >> ${TMPFILE} echo "
  • errors is number of packages that failed. Note: if a run was restarted, you may see duplicates here.
  • " >> ${TMPFILE} echo "
  • skipped is number of packages that were skipped due to NO_PACKAGE, IGNORE, BROKEN, FORBIDDEN, and so forth (\"duds\" file).
  • " >> ${TMPFILE} echo "
  • not yet built is the INDEX column minus the build logs plus the errors plus the skipped. These are packages that have not been built for one reason or another. Note: interrupted and/or restarted builds can make this number inaccurate because of the duplicates, above.
  • " >> ${TMPFILE} echo "
  • running is whether there are still processes running.
  • " >> ${TMPFILE} echo "
  • completed is whether that build terminated normally or not, as seen from the logfile.
  • " >> ${TMPFILE} echo "
" >> ${TMPFILE} # no longer true 20080917 # echo "

notes:

" >> ${TMPFILE} # echo "
    " >> ${TMPFILE} # echo "
  • on the -exp builds, editors/openoffice.org* are skipped to save time.
  • " >> ${TMPFILE} # echo "
" >> ${TMPFILE} echo "" >> ${TMPFILE} echo "" >> ${TMPFILE} } # main write_header # display all the mainstream builds first # (i.e. where build = branch, e.g. "7", "10") for arch in ${SUPPORTED_ARCHS}; do cd ${pbd}/${arch} builds=`ls | \ grep "${SRC_BRANCHES_PATTERN}$" | \ sort -n` if [ ! -z "$builds" ]; then write_table_begin for build in ${builds}; do write_row ${arch} ${build} done write_table_end fi done # then display all the non-mainstream builds (probably only of interest # to portmgr; would break up the logical flow of the above) # examples: 8.1; 8-exp; 8-exp-gettext; 8.1R for arch in ${SUPPORTED_ARCHS}; do cd ${pbd}/${arch} branches=`ls | \ grep "${SRC_BRANCHES_PATTERN}[-\.]" | \ sed -e "s@[-\.].*@@" | \ uniq | \ sort -n` if [ ! -z "$branches" ]; then for branch in $branches; do builds=`ls -d $branch* | \ grep -v "${SRC_BRANCHES_PATTERN}$" | \ sort` if [ ! -z "$builds" ]; then write_table_begin for build in ${builds}; do write_row ${arch} ${build} done write_table_end fi done fi done write_footer mv -f ${TMPFILE} ${OUTFILE} Index: projects/portbuild/scripts/pdispatch =================================================================== --- projects/portbuild/scripts/pdispatch (revision 221761) +++ projects/portbuild/scripts/pdispatch (revision 221762) @@ -1,213 +1,213 @@ #!/bin/sh # $FreeBSD: ports/Tools/portbuild/scripts/pdispatch,v 1.40 2011/01/26 10:41:53 linimon Exp $ # -# pdispatch [ ...] +# pdispatch [ ...] # # server-side script to dispatch the job to a host via the ptimeout script. pbc=${PORTBUILD_CHECKOUT:-/var/portbuild} pbd=${PORTBUILD_DATA:-/var/portbuild} arch=$1 branch=$2 buildid=$3 host=$4 command=$5 shift 5 pbab=${pbd}/${arch}/${branch} . ${pbc}/conf/server.conf . ${pbc}/conf/common.conf . ${pbd}/${arch}/portbuild.conf if [ -f ${pbd}/${arch}/${branch}/builds/${buildid}/portbuild.conf ]; then . ${pbd}/${arch}/${branch}/builds/${buildid}/portbuild.conf fi . ${pbc}/scripts/buildenv timeout=${PDISPATCH_TIMEOUT} loglength=${PDISPATCH_LOGLENGTH} hdrlength=${PDISPATCH_HDRLENGTH} buildid=$(resolve ${pbd} ${arch} ${branch} ${buildid}) if [ -z "${buildid}" ]; then echo "Invalid build ID ${buildid}" exit 1 fi builddir=${pbab}/builds/${buildid} buildenv ${pbd} ${arch} ${branch} ${builddir} # XXX needed still? unset DISPLAY # Allow override by HPN-SSH for performance if [ -z "${ssh_cmd}" ]; then ssh_cmd=ssh fi if [ -z "${scp_cmd}" ]; then scp_cmd=scp fi -pkgname=$(basename $1 ${PKGSUFFIX}) +pkgname=$(basename $1 ${pkg_sufx}) if [ -z "${pkgname}" ]; then echo "null packagename" exit 1 fi args=${1+"$@"} flags="" clean=1 if [ "x$NOCLEAN" != "x" ]; then flags="${flags} -noclean" clean=0 fi if [ "x$NO_RESTRICTED" != "x" ]; then flags="${flags} -norestr" fi if [ "x$NOPLISTCHECK" != "x" ]; then flags="${flags} -noplistcheck" fi if [ "x$NO_DISTFILES" = "x" ]; then flags="${flags} -distfiles" fi if [ "x$FETCH_ORIGINAL" != "x" ]; then flags="${flags} -fetch-original" fi if [ "x$TRYBROKEN" != "x" ]; then flags="${flags} -trybroken" fi chroot= . ${pbd}/${arch}/portbuild.conf test -f ${pbd}/${arch}/portbuild.${host} && . ${pbd}/${arch}/portbuild.${host} # Upload scripts/claim-chroot as per-build scripts aren't in place yet. cmdpath=$(cat ${pbc}/scripts/claim-chroot | ssh -a ${client_user}@${host} 't=$(mktemp -t claim-chroot); cat >$t; echo $t; chmod 755 $t') case ${cmdpath} in /tmp/*) ;; *) echo "Failed to scp claim-chroot to ${host}."; exit 254;; esac chrootdata=$(${ssh_cmd} -a -n ${client_user}@${host} ${sudo_cmd} ${cmdpath} ${arch} ${branch} ${buildid} ${pkgname} 2>&1) ${ssh_cmd} -a ${client_user}@${host} "rm -f ${cmdpath}" if [ -z "${chrootdata}" ]; then echo "Failed to claim chroot on ${host}" exit 254 fi case "${chrootdata}" in *${cmdpath}*) # Error executing script, assume system is booting chrootdata="wait boot" ;; esac # echo "Got ${chrootdata} from ${host}" set -- ${chrootdata} if [ $# -ge 2 ]; then case $1 in chroot) chroot=$2 ;; setup) echo "Setting up ${arch}/${branch} build ID ${buildid} on ${host}" # Run in the background so we can potentially # claim a slot on another machine. In # practise I think we often end up trying # again on the same machine though. # Make sure to close stdin/stderr in the child # or make will hang until the child process # exits ${pbc}/scripts/dosetupnode ${arch} ${branch} ${buildid} ${host} > /tmp/setupnode.$$ 2>&1 & exit 253 ;; error) echo "Error reported by ${host}: $2" ;; wait) echo "Waiting for setup of ${host} to finish" ;; esac shift 2 fi if [ -z "${chroot}" ]; then exit 254 fi . ${pbd}/${arch}/portbuild.conf test -f ${pbd}/${arch}/portbuild.${host} && . ${pbd}/${arch}/portbuild.${host} rm -f ${builddir}/logs/${pkgname}.log ${builddir}/logs/${pkgname}.log.bz2 rm -f ${builddir}/errors/${pkgname}.log ${builddir}/errors/${pkgname}.log.bz2 ${builddir}/ptimeout $timeout ${ssh_cmd} -a -n ${client_user}@${host} ${sudo_cmd} ${command} ${arch} ${branch} ${buildid} ${chroot} ${flags} \"$ED\" \"$PD\" \"$FD\" \"$BD\" \"$RD\" ${args} 2>&1 error=$? # Pull in the results of the build from the client ${scp_cmd} ${client_user}@${host}:${chroot}/tmp/${pkgname}.log ${builddir}/logs/${pkgname}.log -(${ssh_cmd} -a -n ${client_user}@${host} test -f ${chroot}/tmp/work.tbz ) && ${scp_cmd} ${client_user}@${host}:${chroot}/tmp/work.tbz ${builddir}/wrkdirs/${pkgname}.tbz +(${ssh_cmd} -a -n ${client_user}@${host} test -f ${chroot}/tmp/work.tbz ) && ${scp_cmd} ${client_user}@${host}:${chroot}/tmp/work.tbz ${builddir}/wrkdirs/${pkgname}${pkg_sufx} # XXX Set dirty flag if any of the scp's fail mkdir -p ${builddir}/distfiles/.pbtmp/${pkgname} ${ssh_cmd} -a -n ${client_user}@${host} tar -C ${chroot}/tmp/distfiles --exclude ${chroot}/tmp/distfiles/RESTRICTED -cf - . | \ tar --unlink -C ${builddir}/distfiles/.pbtmp/${pkgname} -xvf - && \ touch ${builddir}/distfiles/.pbtmp/${pkgname}/.done if [ "${error}" = 0 ]; then ${ssh_cmd} -a -n ${client_user}@${host} tar -C ${chroot}/tmp -cf - packages | \ tar --unlink -C ${builddir} -xvf - # XXX why is this needed? - test -f ${builddir}/packages/All/${pkgname}${PKGSUFFIX} && \ - touch ${builddir}/packages/All/${pkgname}${PKGSUFFIX} + test -f ${builddir}/packages/All/${pkgname}${pkg_sufx} && \ + touch ${builddir}/packages/All/${pkgname}${pkg_sufx} if [ -f ${builddir}/errors/${pkgname}.log ]; then rm -f ${builddir}/errors/${pkgname}.log # Force rebuild of html page to remove this package from list touch ${builddir}/errors/.force fi lockf -k ${pbab}/failure.lock ${pbc}/scripts/buildsuccess ${arch} ${branch} ${buildid} ${pkgname} log=${builddir}/logs/$pkgname.log if grep -q "even though it is marked BROKEN" ${log}; then echo | mail -s "${pkgname} BROKEN but built on ${arch} ${branch}" ${mailto} fi if grep -q "^list of .*file" ${log}; then buildlogdir=$(realpath ${builddir}/logs/) baselogdir=$(basename ${buildlogdir}) (sed -e '/^build started/,$d' $log;echo;echo "For the full build log, see"; echo; echo " http://${MASTER_URL}/errorlogs/${arch}-errorlogs/${baselogdir}/$(basename $log)";echo;sed -e '1,/^=== Checking filesystem state/d' $log) | mail -s "${pkgname} pkg-plist errors on ${arch} ${branch}" ${mailto} fi else log=${builddir}/errors/${pkgname}.log ${scp_cmd} ${client_user}@${host}:${chroot}/tmp/${pkgname}.log ${log} result=$? if [ $result -ne 0 ]; then (echo ${chroot}@${host}; ${ssh_cmd} -a -n ${client_user}@${host} ls -laR ${chroot}/tmp) | mail -s "${pkgname} logfile not found" ${mailto} else if ! grep -q "even though it is marked BROKEN" ${log}; then buildlogdir=$(realpath ${builddir}/logs/) baselogdir=$(basename ${buildlogdir}) if [ $(wc -l ${log} | awk '{print $1}') -le $((loglength + hdrlength)) ]; then (echo "You can also find this build log at"; echo; echo " http://${MASTER_URL}/errorlogs/${arch}-errorlogs/${baselogdir}/$(basename $log)";echo;cat ${log}) | mail -s "${pkgname} failed on ${arch} ${branch}" ${mailto} else (echo "Excerpt from the build log at"; echo; echo " http://${MASTER_URL}/errorlogs/${arch}-errorlogs/${baselogdir}/$(basename $log)";echo;sed -e '/^build started/,$d' $log;echo;echo " [... lines trimmed ...]";echo;tail -${loglength} ${log}) | mail -s "${pkgname} failed on ${arch} ${branch}" ${mailto} fi fi lockf -k ${pbab}/failure.lock ${pbc}/scripts/buildfailure ${arch} ${branch} ${buildid} ${pkgname} fi fi ${ssh_cmd} -a -n ${client_user}@${host} ${sudo_cmd} /tmp/${buildid}/scripts/clean-chroot ${arch} ${branch} ${buildid} ${chroot} ${clean} # XXX Set a dirty variable earlier and check here if grep -q "^build of .*ended at" ${builddir}/logs/${pkgname}.log; then exit ${error} else echo "Build of ${pkgname} in ${host}:/${chroot} failed uncleanly" exit 255 fi Index: projects/portbuild/scripts/portbuild =================================================================== --- projects/portbuild/scripts/portbuild (revision 221761) +++ projects/portbuild/scripts/portbuild (revision 221762) @@ -1,348 +1,349 @@ #!/bin/sh # $FreeBSD: ports/Tools/portbuild/scripts/portbuild,v 1.65 2011/01/23 02:39:54 linimon Exp $ # client-side script to do all the work surrounding an individual package # build, and then the package build itself # note: unredirected 'echo' output goes to the journal file # usage: $0 ARCH BRANCH BUILDID CHROOT [-noclean] [-norestr] [-noplistcheck] [-distfiles] [-fetch-original] [-trybroken] PKGNAME.tgz DIRNAME [DEPENDENCY.tgz ...] pbd=${PORTBUILD_DATA:-/var/portbuild} mount_fs() { fs=$1 mntpt=$2 master=$3 if [ ${disconnected} = 1 ]; then mount -t nullfs -r ${fs} ${mntpt} else mount_nfs -o ro -3 -i ${master}:${fs} ${mntpt} fi } copypkg() { pbd=$1 host=$2 from=$3 to=$4 http_proxy=$5 if [ ${host} = $(hostname) ]; then cp ${pbd}/${arch}/${branch}/packages/All/${from} ${to} else if [ ! -z "${http_proxy}" ]; then env HTTP_PROXY=${http_proxy} fetch -m -o ${to} http://${host}/errorlogs/${arch}-${branch}-packages-latest/All/${from} else fetch -m -o ${to} http://${host}/errorlogs/${arch}-${branch}-packages-latest/All/${from} fi fi } bailout() { chroot=$1 clean=$2 error=$3 pkgname=$4 echo -n "$pkgname failed unexpectedly on $(hostname) at " date exit $error } arch=$1 branch=$2 buildid=$3 chroot=$4 shift 4 # Default niceness value nice=0 . ${pbd}/${arch}/client.conf . ${pbd}/${arch}/common.conf # note: should NOT need anything from server.conf . ${pbd}/${arch}/portbuild.conf if [ -f ${pbd}/${arch}/${branch}/builds/${buildid}/portbuild.conf ]; then . ${pbd}/${arch}/${branch}/builds/${buildid}/portbuild.conf fi . ${pbd}/${arch}/portbuild.$(hostname) . ${pbd}/scripts/buildenv buildroot=${scratchdir} error=0 clean=1 if [ "x$1" = "x-noclean" ]; then clean=0 shift fi norestr=0 if [ "x$1" = "x-norestr" ]; then norestr=1 # consumed by bsd.port.mk export NO_RESTRICTED=1 shift fi noplistcheck=0 if [ "x$1" = "x-noplistcheck" ]; then noplistcheck=1 # consumed by buildscript directly export NOPLISTCHECK=1 shift fi nodistfiles=1 if [ "x$1" = "x-distfiles" ]; then # consumed by buildscript via make(1) export ALWAYS_KEEP_DISTFILES=1 nodistfiles=0 shift fi if [ "x$1" = "x-fetch-original" ]; then # consumed by buildscript via make(1) export FETCH_ORIGINAL=1 shift fi if [ "x$1" = "x-trybroken" ]; then # consumed by bsd.port.mk export TRYBROKEN=1 shift fi ED=$1 PD=$2 FD=$3 BD=$4 RD=$5 builddir=${pbd}/${arch}/${branch}/builds/${buildid} buildenv.common # Want to use the /etc/make.conf in the chroot unset __MAKE_CONF # set overrides for make.conf export BACKUP_FTP_SITE=${CLIENT_BACKUP_FTP_SITE} -pkgname=$(basename $6 ${PKGSUFFIX}) +pkgname=$(basename $6 ${pkg_sufx}) dirname=$7 shift 2 echo $pkgname echo $dirname # set overrides for bsd.port.mk variables export WRKDIRPREFIX=${CLIENT_WRKDIRPREFIX} export DISTDIR=${CLIENT_DISTDIR} export LOCALBASE=${LOCALBASE} export PACKAGES=${CLIENT_PACKAGES_LOCATION} export SRC_BASE=${CLIENT_SRCBASE} +export PKG_SUFX=${pkg_sufx} # to catch missing dependencies #export DEPENDS_TARGET=/usr/bin/true # don't pass -j, -k etc. to sub-makes unset MAKEFLAGS unset PORTSDIR # wait 2 hours before killing build with no output export BUILD_TIMEOUT=${CLIENT_BUILD_TIMEOUT} # prevent runaway processes ulimit -f ${CLIENT_ULIMIT_F} ulimit -t ${CLIENT_ULIMIT_T} # directories to clean cleandirs="${LOCALBASE} /compat /var/db/pkg" export FTP_TIMEOUT=${CLIENT_FTP_TIMEOUT} export HTTP_TIMEOUT=${CLIENT_HTTP_TIMEOUT} export PATH=/sbin:/bin:/usr/sbin:/usr/bin:${LOCALBASE}/sbin:${LOCALBASE}/bin export MALLOC_OPTIONS=${CLIENT_MALLOC_OPTIONS} echo "building ${pkgname} in ${chroot}" bindist=${buildroot}/${branch}/${buildid}/tarballs/bindist.tar bindistlocal=${buildroot}/${branch}/${buildid}/tarballs/bindist-$(hostname).tar if [ -f ${chroot}/.notready ]; then tar -C ${chroot} -xpf ${bindist} if [ -f ${bindistlocal} ]; then tar -C ${chroot} -xpf ${bindistlocal} fi # to be able to run certain kernel-dependent binaries # inside the chroot area cp -p /rescue/mount /rescue/umount ${chroot}/sbin cp -p /rescue/ps ${chroot}/bin rm ${chroot}/.notready touch ${chroot}/.ready fi if [ "${use_jail}" = "1" ]; then # Figure out jail IP addr chrootpid=$(basename ${chroot}) ipbase=$((${chrootpid}+2)) ip1=$(($ipbase /(256*256))) ip2=$((($ipbase - ($ip1*256*256)) /256)) ip3=$((($ipbase - ($ip1*256*256) - ($ip2*256)))) fi trap "bailout ${chroot} ${clean} ${error} ${pkgname}" 1 2 3 9 10 11 15 rm -rf ${chroot}/tmp/* cd ${chroot}/tmp mkdir -p depends distfiles packages echo "building ${pkgname} on $(hostname)" | tee ${chroot}/tmp/${pkgname}.log echo "in directory ${chroot}" | tee -a ${chroot}/tmp/${pkgname}.log # intentionally set up ${PORTSDIR} with symlink to catch broken ports mkdir -p ${chroot}/a/ports rm -rf ${chroot}/usr/ports # Don't build in a world-writable standard directory because some ports # hardcode this path and try to load things from it at runtime, which is # bad for user security rm -rf ${chroot}/${WRKDIRPREFIX} mkdir -p ${chroot}/${WRKDIRPREFIX} # pick up value from /portbuild.conf if [ ! -z "${ccache_dir}" ]; then mkdir -p ${chroot}/root/.ccache/ if [ "${ccache_dir_nfs}" = "1" ]; then mount_nfs -o rw -T -3 ${ccache_dir} ${chroot}/root/.ccache/ else mount -o rw -t nullfs ${ccache_dir} ${chroot}/root/.ccache/ fi fi mount_fs ${builddir}/ports ${chroot}/a/ports ${CLIENT_NFS_MASTER} ln -sf ../a/ports ${chroot}/usr/ports mkdir -p ${chroot}/usr/src mount_fs ${builddir}/src ${chroot}${CLIENT_SRCBASE} ${CLIENT_NFS_MASTER} # set overrides for uname buildenv.client ${chroot}${CLIENT_SRCBASE} mount -t devfs foo ${chroot}/dev umount -f ${chroot}/compat/linux/proc > /dev/null 2>&1 # just in case... for dir in ${cleandirs}; do if ! rm -rf ${chroot}${dir} >/dev/null 2>&1; then chflags -R noschg ${chroot}${dir} rm -rf ${chroot}${dir} >/dev/null 2>&1 fi done rm -rf ${chroot}/var/db/pkg/* mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.root.dist -p ${chroot} \ >/dev/null 2>&1 mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.var.dist -p ${chroot}/var \ >/dev/null 2>&1 mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.usr.dist -p ${chroot}/usr \ >/dev/null 2>&1 mkdir -p ${chroot}${LOCALBASE} mtree -deU -f ${chroot}/a/ports/Templates/BSD.local.dist -p ${chroot}${LOCALBASE} \ >/dev/null 2>&1 for i in ${ARCHS_REQUIRING_LINPROCFS}; do if [ ${i} = ${arch} ]; then # JDK ports need linprocfs :( mkdir -p ${chroot}/compat/linux/proc mount -t linprocfs linprocfs ${chroot}/compat/linux/proc break fi done _ldconfig_dirs="/lib /usr/lib /usr/lib/compat" ldconfig_dirs="" for i in ${_ldconfig_dirs}; do if [ -d ${chroot}/${i} ]; then ldconfig_dirs="${ldconfig_dirs} ${i}" fi done chroot ${chroot} /sbin/ldconfig ${ldconfig_dirs} for i in ${ARCHS_REQUIRING_AOUT_COMPAT}; do if [ ${i} = ${arch} ]; then chroot ${chroot} /sbin/ldconfig -aout /usr/lib/aout /usr/lib/compat/aout break fi done set x $ED $FD $PD $BD $RD shift 1 while [ $# -gt 0 ]; do # XXX MCL more hard-coding if [ ! -f ${chroot}/tmp/depends/$1 ]; then echo "copying package $1 for ${pkgname}" copypkg ${pbd} ${CLIENT_UPLOAD_HOST} $1 ${chroot}/tmp/depends "${http_proxy}" # Test for copy failure and bail # XXX MCL more hard-coding if [ ! -f ${chroot}/tmp/depends/$1 ]; then echo "ERROR: Couldn't copy $1" | tee -a ${chroot}/tmp/${pkgname}.log bailout ${chroot} ${clean} 255 ${pkgname} fi fi shift done cp -p /tmp/${buildid}/scripts/buildscript ${chroot} cp -p /tmp/${buildid}/sources/pnohang.c ${chroot} # phase 0, compile pnohang chroot ${chroot} /usr/bin/gcc -o /pnohang -Wall /pnohang.c 2>&1 | tee -a ${chroot}/tmp/${pkgname}.log if [ $? -ne 0 ]; then error=255 fi if [ "${error}" = 0 ]; then # phase 1, make checksum # Needs to be chroot not jail so that port can be fetched chroot ${chroot} /buildscript ${dirname} 1 "$ED" "$PD" "$FD" "$BD" "$RD" 2>&1 | tee -a ${chroot}/tmp/${pkgname}.log if [ -f ${chroot}/tmp/status ]; then error=$(cat ${chroot}/tmp/status) else error=255 fi fi if [ "${error}" = 0 ]; then # make checksum succeeded # phase 2, make package ln -sf ${pkgname}.log2 ${chroot}/tmp/make.log if [ "${use_jail}" = 1 ]; then ifconfig lo0 alias 127.${ip1}.${ip2}.${ip3}/32 jail -J ${chroot}/tmp/jail.id ${chroot} jail-${chrootpid} 127.${ip1}.${ip2}.${ip3} /usr/bin/env JAIL_ADDR=127.${ip1}.${ip2}.${ip3} HTTP_PROXY=${http_proxy} /usr/bin/nice -n $nice /buildscript ${dirname} 2 "$ED" "$PD" "$FD" "$BD" "$RD" > ${chroot}/tmp/${pkgname}.log2 2>&1 ifconfig lo0 delete 127.${ip1}.${ip2}.${ip3} else chroot ${chroot} /usr/bin/nice -n ${nice} /buildscript ${dirname} 2 "$ED" "$PD" "$FD" "$BD" "$RD" > ${chroot}/tmp/${pkgname}.log2 2>&1 fi grep pnohang ${chroot}/tmp/${pkgname}.log2 cat ${chroot}/tmp/${pkgname}.log2 >> ${chroot}/tmp/${pkgname}.log rm ${chroot}/tmp/${pkgname}.log2 error=$(cat ${chroot}/tmp/status) fi rm -rf ${chroot}/${WRKDIRPREFIX} # Record build completion time for ganglia echo "${arch} ${branch} ${buildid}" > ${buildroot}/stamp/${pkgname} exit $error Index: projects/portbuild/scripts/prunefailure =================================================================== --- projects/portbuild/scripts/prunefailure (revision 221761) +++ projects/portbuild/scripts/prunefailure (revision 221762) @@ -1,92 +1,92 @@ #!/bin/sh # # Prune the failure files of stale entries # # This must be called via: # # lockf -k ${pbd}/${arch}/${branch}/failure.lock ${pbc}/scripts/prunefailure ${arch} ${branch} ${buildid} # # to avoid racing with any package builds in progress that might try to append to # these files. # configurable variables pbc=${PORTBUILD_CHECKOUT:-/var/portbuild} pbd=${PORTBUILD_DATA:-/var/portbuild} cleanup() { echo "Problem writing new failure file!" rm -f failure.new exit 1 } if [ $# -ne 3 ]; then echo "prunefailure " exit 1 fi arch=$1 branch=$2 buildid=$3 shift 3 . ${pbc}/conf/server.conf . ${pbc}/conf/common.conf . ${pbd}/${arch}/portbuild.conf if [ -f ${pbd}/${arch}/${branch}/builds/${buildid}/portbuild.conf ]; then . ${pbd}/${arch}/${branch}/builds/${buildid}/portbuild.conf fi . ${pbc}/scripts/buildenv builddir=${pbd}/${arch}/${branch}/builds/${buildid} buildenv ${pbd} ${arch} ${branch} ${builddir} home=${pbd}/${arch}/${branch} cd $home pkgdir=${builddir}/packages/All index=${PORTSDIR}/${INDEXFILE} if [ "`wc -l $index | awk '{print $1}'`" -lt 9000 ]; then echo "INDEX is corrupted, terminating!" exit 1 fi echo "===> Pruning old failure file" rm -f failure.new IFS='|' while read dir name ver olddate date count; do if [ -z "$dir" -o -z "$name" -o -z "$ver" -o -z "$olddate" -o -z "$date" -o -z "$count" ]; then echo Malformed entry "$dir|$name|$ver|$olddate|$date|$count" # Clean up the 'latest error log' symlink rm -f ${pbd}/${arch}/${branch}/latest/${dir} continue fi entry=$(grep "|/usr/ports/$dir|" $index) if [ -z "$entry" ]; then echo $dir not in index rm -f ${pbd}/${arch}/${branch}/latest/${dir} continue fi newver=$(echo $entry | awk '{print $1}') - if [ -e "${builddir}/packages/All/$newver${PKGSUFFIX}" ]; then + if [ -e "${builddir}/packages/All/$newver${pkg_sufx}" ]; then echo "$newver package exists, should not still be here!" rm -f ${pbd}/${arch}/${branch}/latest/${dir} continue fi if grep -qxF $newver ${builddir}/duds.full; then echo "$newver listed in duds, should not be here" rm -f ${pbd}/${arch}/${branch}/latest/${dir} continue fi (echo "$dir|$name|$newver|$olddate|$date|$count" >> $home/failure.new) || cleanup done < $home/failure mv failure.new failure Index: projects/portbuild/scripts/prunepkgs =================================================================== --- projects/portbuild/scripts/prunepkgs (revision 221761) +++ projects/portbuild/scripts/prunepkgs (revision 221762) @@ -1,66 +1,66 @@ #!/bin/sh if [ $# -lt 2 ]; then echo "usage: prunepkgs [-dummy]" return 1 fi index=$1 pkgdir=$2 if [ $# -eq 3 -a "$3" = "-dummy" ]; then dummy=1; else dummy=0; fi testprunelink() { if [ ! -e $1 ]; then dest=$(readlink $1) echo "$1 -> $dest pruned." if [ "${dummy}" = "0" ]; then rm -f $1 fi fi } # Set up work dir tmpdir=$(mktemp -d -t prunepkgs) trap "rm -rf $tmpdir; exit 1" 1 2 3 5 10 13 15 # Check for non-package files -extras=$(find ${pkgdir} -type f \! \( -name INDEX -o -name CHECKSUM.MD5 -o -name \*.tgz -o -name \*.tbz \) ) +extras=$(find ${pkgdir} -type f \! \( -name INDEX -o -name CHECKSUM.MD5 -o -name '*.t[bgx]z' \) ) echo "==> Removing extra files" echo $extras if [ "x${extras}" != "x" ]; then if [ "${dummy}" = "0" ]; then rm -f ${extras} fi fi # Check for files not present in INDEX echo "==> Removing extra package files" -find $pkgdir/All -type f -name \*.tgz -o -name \*.tbz | sed -e "s,${pkgdir}/All/,," -e 's,\.tbz$,,' -e 's,\.tgz$,,' |sort > ${tmpdir}/files +find $pkgdir/All -type f -name '*.t[bgx]z' | sed -e "s,${pkgdir}/All/,," -e 's,\.t[bgx]z$,,' |sort > ${tmpdir}/files cut -f 1 -d '|' ${index} |sort > ${tmpdir}/packages extras=$(comm -2 -3 ${tmpdir}/files ${tmpdir}/packages) echo $extras if [ "${dummy}" = "0" ]; then for i in $extras; do - rm -f $pkgdir/All/${i}.tgz $pkgdir/All/${i}.tbz + rm -f $pkgdir/All/${i}.t[bgx]z done fi rm -rf ${tmpdir} # Look for dead links and prune them echo "==> Removing dead symlinks" links=$(find $pkgdir -type l) for i in $links; do testprunelink $i done Index: projects/portbuild/scripts/stats =================================================================== --- projects/portbuild/scripts/stats (revision 221761) +++ projects/portbuild/scripts/stats (revision 221762) @@ -1,22 +1,22 @@ #!/bin/sh pbc=${PORTBUILD_CHECKOUT:-/var/portbuild} pbd=${PORTBUILD_DATA:-/var/portbuild} . ${pbc}/conf/server.conf if [ $# -ne 1 ]; then echo "usage: " exit 1 fi branch=$1 for i in ${SUPPORTED_ARCHS}; do all=${pbd}/$i/${branch}/builds/latest/packages/All if [ -d ${all} ]; then - count=$(find ${all} -name \*.tbz -o -name \*.tgz |wc -l) + count=$(find ${all} -name '*.t[bgx]z' | wc -l) echo -n "$i: ${count} " fi done echo