From e77f28c56eef5feae20bfc7716e6c11b2195ada0 Mon Sep 17 00:00:00 2001
From: Eudyptula <eitan@mosenkis.net>
Date: Wed, 1 Jul 2009 17:46:53 -0400
Subject: Update both parts for proper modularity, start catalyst-based
 backend, code cleanup, especially on backend

---
 backend/backend.php                           | 34 ++++++----
 backend/functions/build.php                   | 90 ---------------------------
 backend/functions/execution.php               | 40 ++++++++++++
 backend/functions/makedirs.php                | 18 ++++++
 backend/modules/gentoo_catalyst/build.php     | 71 +++++++++++++++++++++
 backend/modules/gentoo_catalyst/catalyst.conf | 79 +++++++++++++++++++++++
 backend/modules/gentoo_catalyst/catalystrc    |  6 ++
 backend/modules/gentoo_portage/build.php      | 78 +++++++++++++++++++++++
 8 files changed, 315 insertions(+), 101 deletions(-)
 delete mode 100644 backend/functions/build.php
 create mode 100644 backend/functions/execution.php
 create mode 100644 backend/functions/makedirs.php
 create mode 100644 backend/modules/gentoo_catalyst/build.php
 create mode 100644 backend/modules/gentoo_catalyst/catalyst.conf
 create mode 100644 backend/modules/gentoo_catalyst/catalystrc
 create mode 100644 backend/modules/gentoo_portage/build.php

(limited to 'backend')

diff --git a/backend/backend.php b/backend/backend.php
index 4e2209a..cde76f0 100755
--- a/backend/backend.php
+++ b/backend/backend.php
@@ -1,8 +1,5 @@
 #!/usr/bin/php
 <?php
-require_once(dirname(__FILE__).'/../shared/include/includes.php'); // USE __DIR__ once 5.3.0 is out (and 2 lines down)
-require_once(BACKEND.'/include/signals.php');
-declare(ticks=1);
 $pidfile='/var/run/ingenue.pid'; // Doesn't work when not run as root
 $opts=getopt('fk');
 if (isset($opts['f'])) {
@@ -21,19 +18,19 @@ if (isset($opts['k'])) {
 	if (is_file($pidfile)) {
 		$pid=trim(file_get_contents($pidfile));
 		if (posix_kill($pid, 0)) {
-			debug("Sending SIGTERM to $pid");
+			fputs(STDERR, "Sending SIGTERM to $pid");
 			if (!posix_kill($pid, SIGTERM)) {
-				debug("Failed to send SIGTERM to $pid");
+				fputs(STDERR, "Failed to send SIGTERM to $pid");
 				die(1);
 			} else {
 				// TODO wait for $pid to exit
 			}
 		} else {
-			debug("Couldn't send signal 0 to $pid");
+			fputs(STDERR, "Couldn't send signal 0 to $pid");
 			die(0);
 		}
 	} else {
-		debug('No PID file found');
+		fputs(STDERR, 'No PID file found');
 	}
 	die();
 }
@@ -43,9 +40,12 @@ if (is_file($pidfile)) {
 		die("Found already running backend PID=$pid.\n");
 }
 if (posix_geteuid() !== 0)
-	debug("Not running as root... this is not going to accomplish much.");
+	fputs(STDERR, "Not running as root... this is not going to accomplish much.");
 if (file_put_contents($pidfile, posix_getpid()))
 	$unlinkpidfile=true;
+require_once(dirname(__FILE__).'/../shared/include/includes.php'); // USE __DIR__ once 5.3.0 is out (and 2 lines down)
+require_once(BACKEND.'/include/signals.php');
+declare(ticks=1);
 require_once(SHARED.'/include/dbinit.php');
 while (true) {
 	// TODO check first for builds that need to be resumed (and figure out how to resume things)
@@ -58,7 +58,19 @@ while (true) {
 		log_msg('Starting build id='.$build->id);
 		$success=null;
 		try {
-			$success=build($build);
+			$opts=$build->get_buildopts();
+			$module=$opts['backend_module'];
+			$build_proc=$module.'_build';
+			foreach (glob(BACKEND."/modules/$module/*.php") as $inc) {
+				require_once($inc);
+			}
+			// TODO check that build_proc exists
+			$workdir=WORK.'/build-'.$build->id;
+			fatal(log_status('Creating work directory '.$workdir, mkdir($workdir, 0700)));
+			$success=$build_proc($build, $opts, $workdir);
+			if (!$conf['debug']) {
+				execute_command('Delete work directory', 'rm -rf "'.$workdir.'"');
+			}
 		} catch (Exception $e) {
 			log_msg('Caught exception: '.$e->getMessage());
 			$build->status='finished/failed: '.$e->getMessage();
@@ -75,8 +87,8 @@ while (true) {
 		$build->write();
 		unset($build);
 	}
-	log_msg('Sleeping...', false);
+//	log_msg('Sleeping...', false);
 	sleep(5);
-	log_msg("done");
+//	log_msg("done");
 }
 ?>
diff --git a/backend/functions/build.php b/backend/functions/build.php
deleted file mode 100644
index a5e2058..0000000
--- a/backend/functions/build.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-// This is the main function that carries out a build from start to finish
-function build(&$build) {
-	global $conf, $profile;
-	$opts=$build->get_buildopts();
-	$profile=new sql_profile($opts['profile']);
-	$headers=$profile->get_headers();
-	$makeconf['pkgdir']=$conf['pkgdir_root'].'/'.$profile->pkgdir;
-	$makeconf['chost']=$headers['chost'];
-	$makeconf['accept_keywords']=$headers['accept_keywords'];
-	$build->write();
-	$W=WORK.'/build-'.$build->id;
-	fatal(log_status('Creating work directory '.$W, mkdir($W, 0700)));
-	$I=$W.'/image';
-	fatal(log_status('Creating '.$I, mkdir($I, 0700)));
-	$makeconf['root']=$I;
-	$C=$W.'/config_root';
-	fatal(log_status('Creating '.$C, mkdir($C, 0700)));
-	fatal(log_status("Making symlink $C/etc -> $C", symlink('.', "$C/etc")));
-	fatal(log_status('Creating '.$W.'/log', mkdir($W.'/log', 0700)));
-	$makeconf['port_logdir']=$W.'/log';
-	$makeconf['emerge_log_dir']=$conf['port_logdir'];
-	fatal(log_status('Creating '.$W.'/tmp', mkdir($W.'/tmp', 0700)));
-	$makeconf['portage_tmpdir']=$W.'/tmp';
-	$makeconf['emerge_default_opts']=$conf['emerge_default_opts'];
-	$contents='';
-	foreach ($makeconf as $name => $val) {
-		$contents.=strtoupper($name).'='.escapeshellarg($val)."\n";
-	}
-	unset($makeconf);
-	fatal(log_status('Writing '.$C.'/make.conf', file_put_contents($C.'/etc/make.conf', $contents)));
-	unset($contents);
-	fatal(log_status('Making make.profile symlink to '.$conf['portdir'].'/profiles/'.$headers['profile'], symlink($conf['portdir'].'/profiles/'.$headers['profile'], $C.'/etc/make.profile')));
-	$env=array(
-		'PORTAGE_CONFIGROOT' => $C,
-		'PATH' => $_ENV['PATH']
-	);
-	sql_task::execute_command('Log portage setup', 'emerge --info', $build, true, null, $env);
-//	sql_task::execute_command('Pre-installing baselayout', 'emerge baselayout', $build, true, null, array_merge($env, array('USE' => 'build')));
-	//	TODO create make.conf, make.profile in target /etc
-	sql_task::execute_command('Install base system', 'emerge system', $build, true, null, $env);
-	if (isset($opts['image_type']) && $opts['image_type'] == 'livecd')
-		sql_task::execute_command('Install LiveCD utilities', 'emerge livecd-tools', $build, true, null, $env);
-	if (isset($opts['install_packages'])) {
-		$pkgs=array();
-		foreach (explode(' ', $opts['install_packages']) as $atom) {
-			$pkgs[]=escapeshellarg($atom);
-		}
-		if (count($pkgs) > 1)
-			sql_task::execute_command('Check that extra packages will install', 'emerge -p '.implode(' ', $pkgs), $build, true, null, $env);
-		foreach ($pkgs as $atom)
-			sql_task::execute_command('Install extra package '.$atom, 'emerge '.$atom, $build, true, null, $env);
-	}
-	$imgtype=isset($opts['image_type'])?$opts['image_type']:'tbz2';
-	if ($imgtype == 'tbz2') {
-		sql_task::execute_command('Compress finished image to tar/bzip2', "tar -p --same-owner -cjvf '$W/image.tar.bz2' -C '$W/image' .", $build, true, null, $env);
-		rename($W.'/image.tar.bz2', COMPLETED.'/build-'.$build->id.'.tar.bz2') || throw_exception('rename failed');
-	} elseif ($imgtype == 'tgz') {
-		sql_task::execute_command('Compress finished image to tar/gz', "tar -p --same-owner -czvf '$W/image.tar.gz' -C '$W/image' .", $build, true, null, $env);
-		rename($W.'/image.tar.gz', COMPLETED.'/build-'.$build->id.'.tar.gz') || throw_exception('rename failed');
-	} elseif ($imgtype == 'livecd' || $imgtype == 'installcd') {
-		if (strpos($headers['chost'], 'x86_64') === false)
-			$minimaliso='/home/eitan/soc/install-x86-minimal-20090623.iso';
-		else
-			$minimaliso='/home/eitan/soc/install-amd64-minimal-20090625.iso';
-		sql_task::execute_command('Mount minimal CD image', "mount -o loop -t iso9660 '$minimaliso' '$W/tmp'", $build, true, null, $env);
-		sql_task::execute_command('Copy CD image to writable temp directory', "cp -va '$W/tmp' '$W/cd'", $build, true, null, $env);
-		sql_task::execute_command('Unmount CD image', "umount '$W/tmp'", $build, true, null, $env);
-		sql_task::execute_command('Copy kernel and initrd from CD to image', "cp -va '$W/cd/isolinux/gentoo' '$W/cd/isolinux/gentoo.igz' '$W/image/boot/'", $build, true, null, $env);
-		file_put_contents("$W/unsquashfs-files", "/lib64/modules\n\lib\modules\n");
-		sql_task::execute_command('Copy kernel modules from SquashFS to image', "unsquashfs -i -d '$W/image' -e '$W/unsquashfs-files' '$W/cd/image.squashfs'", $build, true, null, $env);
-		if ($imgtype == 'livecd') {
-			rename("$W/cd/image.squashfs", "$W/image.squashfs.old") || debug('Failed to move old SquashFS');
-			sql_task::execute_command('Compress finished image to squashfs', "mksquashfs '$W/image' '$W/cd/image.squashfs' -noappend -info", $build, true, null, $env);
-		} else // Install CD
-			sql_task::execute_command('Compress finished image to tar/bzip2', "tar -p --same-owner -cjvf '$W/cd/image.tar.bz2' -C '$W/image' .", $build, true, null, $env);
-		// TODO port the rest of /usr/lib/catalyst/targets/support/create-iso.sh to support other bootloaders
-		// ISOLINUX bootloader
-		// mkisofs -J -R -l ${mkisofs_zisofs_opts} -V "${clst_iso_volume_id}" -o ${1} -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table ${clst_target_path}
-		sql_task::execute_command('Create ISO image', "mkisofs -J -R -l -V 'Ingenue Build $build->id' -o '$W/image.iso' -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table '$W/cd'", $build, true, null, $env);
-		rename("$W/image.iso", COMPLETED.'/build-'.$build->id.'.iso') || throw_exception('rename failed');
-	} else {
-		throw_exception('invalid image type: '.$imgtype);
-	}
-	if (!$conf['debug']) {
-		sql_task::execute_command('Delete work directory', 'rm -rf "'.$W.'"', $build, true, null, $env);
-	}
-	return true;
-}
-?>
diff --git a/backend/functions/execution.php b/backend/functions/execution.php
new file mode 100644
index 0000000..dd6dd88
--- /dev/null
+++ b/backend/functions/execution.php
@@ -0,0 +1,40 @@
+<?php
+function execute_command_with_all($description, $command, $fatal=true, $path=null, $env=null) {
+	global $build, $task;
+	$default_env=array(
+		'PATH' => $_ENV['PATH']
+	);		
+	$env=is_array($env)?array_merge($default_env, $env):$default_env;
+	// TODO this won't work once we have internal tasks too - we need to use a common function for tracking order
+	static $buildid=null;
+	static $order=0;
+	if ($build->id !== $buildid) {
+		$buildid=$build->id;
+		$order=0;
+	}
+	$task=new sql_task($build->id, $order++, null, $description, $command);
+	$result=$task->execute($path, $env);
+	unset($task);
+	if ($result != 0 && $fatal) {
+		if ($result > 0)
+			throw_exception($command.' returned with exit status '.$result);
+		elseif ($result == -128)
+			throw_exception($command.' received an unknown signal');
+		else
+			throw_exception($command.' received signal '.-$result);
+	}
+	return $result;
+}
+function execute_command($desc, $cmd) {
+	return execute_command_with_all($desc, $cmd, true, null, null);
+}
+function execute_command_with_env($desc, $cmd, $env) {
+	return execute_command_with_all($desc, $cmd, true, null, $env);
+}
+function execute_command_with_path($desc, $cmd, $path) {
+	return execute_command_with_all($desc, $cmd, true, $path, null);
+}
+function execute_non_fatal_command($desc, $cmd, $path=null, $env=null) {
+	return execute_command_with_all($desc, $cmd, false, $path, $env);
+}
+?>
diff --git a/backend/functions/makedirs.php b/backend/functions/makedirs.php
new file mode 100644
index 0000000..eb572c9
--- /dev/null
+++ b/backend/functions/makedirs.php
@@ -0,0 +1,18 @@
+<?php
+function makedirs() {
+	for ($i=0; $i<func_num_args(); $i++) {
+		$dir=func_get_arg($i);
+		if (is_array($dir)) {
+			call_user_func('makedirs', $dir);
+		} else {
+			makedir($dir);
+		}
+	}
+}
+function makedir($dir) {
+	global $workdir;
+	if (substr($dir, 0, 1) != '/')
+		$dir="$workdir/$dir";
+	fatal(log_status('Creating '.$dir, mkdir($dir, 0700, true)));
+}
+?>
diff --git a/backend/modules/gentoo_catalyst/build.php b/backend/modules/gentoo_catalyst/build.php
new file mode 100644
index 0000000..45b2b6e
--- /dev/null
+++ b/backend/modules/gentoo_catalyst/build.php
@@ -0,0 +1,71 @@
+<?php
+function gentoo_catalyst_build(&$build, &$opts, &$W) {
+	global $conf, $profile;
+	$profile=new sql_profile($opts['profile']);
+	$headers=$profile->get_headers();
+	$arch=explode(' ', $headers['accept_keywords']);
+	$arch=$arch[0];
+	if (substr($arch, 0, 1) == '~')
+		$arch=substr($arch, 1);
+//	$C=$W.'/config_root';
+	makedirs('catalyst_tmp', 'snapshot_cache');
+	$catalyst=array(
+		'digests' => '',
+		'contents' => '',
+		'distdir' => '',
+		// 'envscript' => '',
+		'hash_function' => 'crc32',
+		'options' => 'pkgcache metadata_overlay seedcache snapcache',
+		'portdir' => $conf['portdir'],
+		'sharedir' => '/usr/lib/catalyst', // This may not work on all systems
+		'snapshotcache' => "$W/snapshot_cache",
+		'storedir' => "$W/catalyst_tmp"
+	);
+	$ctc=fopen("$W/catalyst.conf", 'w');
+	foreach ($catalyst as $name => $val) {
+		fputs($ctc, "$name=\"$val\"\n");
+	}
+	fclose($ctc);
+	// TODO - stages 1-3 first, only do stage4 if we have extra packages to install
+	$spec=array(
+		'subarch' => $arch,
+		'version_stamp' => gmdate('Ymd-His'),
+		'target' => 'stage4',
+		'rel_type' => 'default',
+		'profile' => $headers['profile'],
+		'snapshot' => gmdate('Ymd'),
+		'source_subpath' => 'default', // FIXME
+		'portage_confdir' => '',
+		'portage_overlay' => '',
+		'pkgcache_path' => "$W/pkgcache",
+		'kerncache_path' => '',
+		'stage4/use' => $headers['use'],
+		'stage4/packages' => $opts['install_packages'],
+		'stage4/fsscript' => '',
+		'stage4/splash_theme' => '',
+		'stage4/gk_mainargs' => '',
+		'stage4/linuxrc' => '',
+		'stage4/motd' => '',
+//		'stage4/modblacklist' => '8139cp', // Not recognized by catalyst
+		'stage4/rcadd' => '',
+		'stage4/rcdel' => '',
+		'stage4/root_overlay' => '',
+		'stage4/xinitrc' => '',
+		'stage4/users' => '',
+		'boot/kernel' => '',
+		'stage4/unmerge' => '',
+		'stage4/empty' => '/var/tmp /var/cache /var/db /var/empty /var/lock /var/log /var/run /var/spool /var/state /tmp /usr/portage /usr/share/man /usr/share/info /usr/share/unimaps /usr/include /usr/share/zoneinfo /usr/share/dict /usr/share/doc /usr/share/ss /usr/share/state /usr/share/texinfo /usr/lib/python2.2 /usr/lib/portage /usr/share/gettext /usr/share/i18n /usr/share/rfc /usr/lib/X11/config /usr/lib/X11/etc /usr/lib/X11/doc /usr/src /usr/share/doc /usr/share/man /root/.ccache /etc/cron.daily /etc/cron.hourly /etc/cron.monthly /etc/cron.weekly /etc/logrotate.d /etc/rsync /usr/lib/awk /usr/lib/ccache /usr/lib/gcc-config /usr/lib/nfs /usr/local /usr/diet/include /usr/diet/man /usr/share/consolefonts/partialfonts /usr/share/consoletrans /usr/share/emacs /usr/share/gcc-data /usr/share/genkernel /etc/splash/gentoo /etc/splash/emergence /usr/share/gnuconfig /usr/share/lcms /usr/share/locale /etc/skel',
+		'stage4/rm' => '/lib/*.a /usr/lib/*.a /usr/lib/gcc-lib/*/*/libgcj* /etc/dispatch-conf.conf /etc/etc-update.conf /etc/*- /etc/issue* /etc/make.conf /etc/man.conf /etc/*.old /root/.viminfo /usr/sbin/fb* /usr/sbin/fsck.cramfs /usr/sbin/fsck.minix /usr/sbin/mkfs.minix /usr/sbin/mkfs.bfs /usr/sbin/mkfs.cramfs /lib/security/pam_access.so /lib/security/pam_chroot.so /lib/security/pam_debug.so /lib/security/pam_ftp.so /lib/security/pam_issue.so /lib/security/pam_mail.so /lib/security/pam_motd.so /lib/security/pam_mkhomedir.so /lib/security/pam_postgresok.so /lib/security/pam_rhosts_auth.so /lib/security/pam_userdb.so /usr/share/consolefonts/1* /usr/share/consolefonts/7* /usr/share/consolefonts/8* /usr/share/consolefonts/9* /usr/share/consolefonts/A* /usr/share/consolefonts/C* /usr/share/consolefonts/E* /usr/share/consolefonts/G* /usr/share/consolefonts/L* /usr/share/consolefonts/M* /usr/share/consolefonts/R* /usr/share/consolefonts/a* /usr/share/consolefonts/c* /usr/share/consolefonts/dr* /usr/share/consolefonts/g* /usr/share/consolefonts/i* /usr/share/consolefonts/k* /usr/share/consolefonts/l* /usr/share/consolefonts/r* /usr/share/consolefonts/s* /usr/share/consolefonts/t* /usr/share/consolefonts/v* /etc/splash/livecd-2006.1/16* /etc/splash/livecd-2006.1/12* /etc/splash/livecd-2006.1/6* /etc/splash/livecd-2006.1/8* /etc/splash/livecd-2006.1/images/silent-16* /etc/splash/livecd-2006.1/images/silent-12* /etc/splash/livecd-2006.1/images/silent-6* /etc/splash/livecd-2006.1/images/silent-8* /etc/splash/livecd-2006.1/images/verbose-16* /etc/splash/livecd-2006.1/images/verbose-12* /etc/splash/livecd-2006.1/images/verbose-6* /etc/splash/livecd-2006.1/images/verbose-8* /etc/make.conf.example /etc/make.globals /etc/resolv.conf'
+	);
+	$specfile=fopen("$W/stage4.spec", 'w');
+	foreach ($spec as $name => $val) {
+		if (strlen($val))
+			fputs($specfile, "$name: $val\n");
+	}
+	fclose($specfile);
+	$pkgdir=$spec['pkgcache_path'].'/'.$spec['rel_type'].'/'.$spec['target'].'-'.$spec['version_stamp'];
+	makedir(dirname($pkgdir));
+	symlink($pkgdir, $profile->pkgdir);
+	execute_command('Running Catalyst for build stage 4', "catalyst -c '$W/catalyst.conf' -f '$W/stage4.spec'");
+}
+?>
diff --git a/backend/modules/gentoo_catalyst/catalyst.conf b/backend/modules/gentoo_catalyst/catalyst.conf
new file mode 100644
index 0000000..ba5505b
--- /dev/null
+++ b/backend/modules/gentoo_catalyst/catalyst.conf
@@ -0,0 +1,79 @@
+# /etc/catalyst/catalyst.conf
+
+# Simple desriptions of catalyst settings. Please refer to the online
+# documentation for more information.
+
+# Creates a .DIGESTS file containing the hash output from any of the supported
+# options below.  Adding them all may take a long time.
+# Supported options: sha1, sha224, ripemd128, ripemd320, sha384, crc32,
+#	ripemd256, sha256, sha512, ripemd160, md5
+digests="md5 sha1"
+
+# Creates a .CONTENTS file listing the contents of the file. Pick from any of
+# the supported options below:
+# auto		- strongly recommended
+# tar-tv	- does 'tar tvf FILE'
+# tar-tvz	- does 'tar tvzf FILE'
+# tar-tvy	- does 'tar tvyf FILE'
+# isoinfo-l	- does 'isoinfo -l -i FILE'
+# isoinfo-f	- does 'isoinfo -f -i FILE'
+# 'isoinfo-f' is the only option not chosen by the automatic algorithm.
+# If this variable is empty, no .CONTENTS will be generated at all.
+contents="auto"
+
+# distdir specifies where your distfiles are located. This setting should
+# work fine for most default installations.
+distdir="/usr/portage/distfiles"
+
+# envscript allows users to set options such as http proxies, MAKEOPTS,
+# GENTOO_MIRRORS, or any other environment variables needed for building.
+# The envscript file sets environment variables like so:
+# export FOO="bar"
+envscript="/etc/catalyst/catalystrc"
+
+# Internal hash function catalyst should use for things like autoresume, 
+# seedcache, etc.  The default and fastest is crc32.  You should not ever need
+# to change this unless your OS does not support it.
+# Supported options: sha1, sha224, ripemd128, ripemd320, sha384, crc32,
+#	ripemd256, sha256, sha512, ripemd160, md5
+hash_function="crc32"
+
+# options set different build-time options for catalyst. Some examples are:
+# autoresume = Attempt to resume a failed build, clear the autoresume flags with
+#	the -a option to the catalyst cmdline.  -p will clear the autoresume flags
+#	as well as your pkgcache and kerncache
+#	( This option is not fully tested, bug reports welcome )
+# ccache = enables build time ccache support (highly recommended)
+# distcc = enable distcc support for building. You have to set distcc_hosts in
+# 	your spec file.
+# icecream = enables icecream compiler cluster support for building
+# kerncache = keeps a tbz2 of your built kernel and modules (useful if your
+#	build stops in livecd-stage2)
+# metadata_overlay = enabled the metadata_overlay cache module in portage, which
+#	uses the in-tree metadata
+# pkgcache = keeps a tbz2 of every built package (useful if your build stops
+#	prematurely)
+# seedcache = use the build output of a previous target if it exists to speed up
+#	the copy
+# snapcache = cache the snapshot so that it can be bind-mounted into the chroot.
+#	WARNING: moving parts of the portage tree from within fsscript *will* break
+#	your cache. The cache is unlinked before any empty or rm processing, though.
+#
+# (These options can be used together)
+options="autoresume kerncache metadata_overlay pkgcache seedcache snapcache"
+
+# portdir specifies the source portage tree used by the snapshot target.
+portdir="/usr/portage"
+
+# sharedir specifies where all of the catalyst runtime executables are. Most
+# users do not need to change this.
+sharedir="/usr/lib64/catalyst"
+
+# snapshot_cache specifies where the snapshots will be cached to if snapcache is
+# enabled in the options.
+snapshot_cache="/var/tmp/catalyst/snapshot_cache"
+
+# storedir specifies where catalyst will store everything that it builds, and
+# also where it will put its temporary files and caches.
+storedir="/var/tmp/catalyst"
+
diff --git a/backend/modules/gentoo_catalyst/catalystrc b/backend/modules/gentoo_catalyst/catalystrc
new file mode 100644
index 0000000..581772d
--- /dev/null
+++ b/backend/modules/gentoo_catalyst/catalystrc
@@ -0,0 +1,6 @@
+#!/bin/bash
+# This is an example catalystrc. As such, it doesn't actually *do* anything.
+
+# Uncomment the following to increase the number of threads used to compile.
+# export MAKEOPTS="-j16"
+
diff --git a/backend/modules/gentoo_portage/build.php b/backend/modules/gentoo_portage/build.php
new file mode 100644
index 0000000..693a85c
--- /dev/null
+++ b/backend/modules/gentoo_portage/build.php
@@ -0,0 +1,78 @@
+<?php
+// This is the main function that carries out a build from start to finish
+function gentoo_portage_build(&$build, &$opts, &$W) {
+	global $conf;
+	$profile=new sql_profile($opts['profile']);
+	$headers=$profile->get_headers();
+	$I=$W.'/image';
+	$C=$W.'/config_root';
+	makedirs($I, $C, "$W/log", "$W/tmp");
+	fatal(log_status("Making symlink $C/etc -> .", symlink('.', "$C/etc")));
+	$makeconf=array(
+		'pkgdir' => $conf['pkgdir_root'].'/'.$profile->pkgdir,
+		'chost' => $headers['chost'],
+		'accept_keywords' => $headers['accept_keywords'],
+		'root' => $I,
+		'port_logdir' => "$W/log",
+		'emerge_log_dir' => "$W/log",
+		'portage_tmpdir' => "$W/tmp",
+		'emerge_default_opts' => $conf['emerge_default_opts']
+	);
+	$contents='';
+	foreach ($makeconf as $name => $val)
+		$contents.=strtoupper($name).'='.escapeshellarg($val)."\n";
+	unset($makeconf);
+	fatal(log_status('Writing '.$C.'/make.conf', file_put_contents($C.'/etc/make.conf', $contents)));
+	unset($contents);
+	fatal(log_status('Making make.profile symlink to '.$conf['portdir'].'/profiles/'.$headers['profile'], symlink($conf['portdir'].'/profiles/'.$headers['profile'], $C.'/etc/make.profile')));
+	$prtg_cfgrt=array('PORTAGE_CONFIGROOT' => $C);
+	execute_command_with_env('Log portage setup', 'emerge --info', $prtg_cfgrt);
+//	execute_command_with_env('Pre-installing baselayout', 'emerge baselayout', array_merge($prtg_cfgrt, array('USE' => 'build')));
+	//	TODO create make.conf, make.profile in target /etc
+	execute_command_with_env('Install base system', 'emerge system', $prtg_cfgrt);
+	if (isset($opts['image_type']) && $opts['image_type'] == 'livecd')
+		execute_command_with_env('Install LiveCD utilities', 'emerge -1 livecd-tools', $prtg_cfgrt);
+	if (isset($opts['install_packages'])) {
+		$pkgs=array();
+		foreach (explode(' ', $opts['install_packages']) as $atom) {
+			$pkgs[]=escapeshellarg($atom);
+		}
+		if (count($pkgs) > 1)
+			execute_command_with_env('Check that extra packages will install', 'emerge -p '.implode(' ', $pkgs), $prtg_cfgrt);
+		foreach ($pkgs as $atom)
+			execute_command_with_env('Install extra package '.$atom, 'emerge '.$atom, $prtg_cfgrt);
+	}
+	$imgtype=isset($opts['image_type'])?$opts['image_type']:'tbz2';
+	if ($imgtype == 'tbz2') {
+		execute_command('Compress finished image to tar/bzip2', "tar -p --same-owner -cjvf '$W/image.tar.bz2' -C '$W/image' .");
+		rename($W.'/image.tar.bz2', COMPLETED.'/build-'.$build->id.'.tar.bz2') || throw_exception('rename failed');
+	} elseif ($imgtype == 'tgz') {
+		execute_command('Compress finished image to tar/gz', "tar -p --same-owner -czvf '$W/image.tar.gz' -C '$W/image' .");
+		rename($W.'/image.tar.gz', COMPLETED.'/build-'.$build->id.'.tar.gz') || throw_exception('rename failed');
+	} elseif ($imgtype == 'livecd' || $imgtype == 'installcd') {
+		if (strpos($headers['chost'], 'x86_64') === false)
+			$minimaliso='/home/eitan/soc/install-x86-minimal-20090623.iso';
+		else
+			$minimaliso='/home/eitan/soc/install-amd64-minimal-20090625.iso';
+		execute_command_with_env('Mount minimal CD image', "mount -o loop -t iso9660 '$minimaliso' '$W/tmp'", $prtg_cfgrt); // TODO check if env is necessary (and for umount)
+		execute_command('Copy CD image to writable temp directory', "cp -va '$W/tmp' '$W/cd'");
+		execute_command_with_env('Unmount CD image', "umount '$W/tmp'", $prtg_cfgrt);
+		execute_command('Copy kernel and initrd from CD to image', "cp -va '$W/cd/isolinux/gentoo' '$W/cd/isolinux/gentoo.igz' '$W/image/boot/'");
+		file_put_contents("$W/unsquashfs-files", "/lib64/modules\n\lib\modules\n");
+		execute_command('Copy kernel modules from SquashFS to image', "unsquashfs -i -d '$W/image' -e '$W/unsquashfs-files' '$W/cd/image.squashfs'");
+		if ($imgtype == 'livecd') {
+			rename("$W/cd/image.squashfs", "$W/image.squashfs.old") || debug('Failed to move old SquashFS');
+			execute_command('Compress finished image to squashfs', "mksquashfs '$W/image' '$W/cd/image.squashfs' -noappend -info");
+		} else // Install CD
+			execute_command('Compress finished image to tar/bzip2', "tar -p --same-owner -cjvf '$W/cd/image.tar.bz2' -C '$W/image' .");
+		// TODO port the rest of /usr/lib/catalyst/targets/support/create-iso.sh to support other bootloaders
+		// ISOLINUX bootloader
+		// mkisofs -J -R -l ${mkisofs_zisofs_opts} -V "${clst_iso_volume_id}" -o ${1} -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table ${clst_target_path}
+		execute_command('Create ISO image', "mkisofs -J -R -l -V 'Ingenue Build $build->id' -o '$W/image.iso' -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table '$W/cd'");
+		rename("$W/image.iso", COMPLETED.'/build-'.$build->id.'.iso') || throw_exception('rename failed');
+	} else {
+		throw_exception('invalid image type: '.$imgtype);
+	}
+	return true;
+}
+?>
-- 
cgit v1.2.3-65-gdbad