[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

A usefull tool (Was: Making Fedora Core CD #1 Standalone)



Dep Tree 0.1 by Chris Chabot.
This program may be freely redistributed under the terms of the GNU GPL.

With all these discussions about making Fedora Core a core cd, ideas about what should or should not be included, i thought it might be easy to be able to quantify and experiment with package dependencies and package sizes so you can find out what can and can not fit on one CD.

This script takes a package or list of packages as command line argument, and recursivly walks the full dependency tree for that/those package(s) and calculates the packages size (size of the RPM's) and installed size (size on disk) for the packages.

It queries the rpm database using the rpm command line tool, so please only use the base package name (mozilla) and not the file name (mozilla-1.6-6.i386.rpm). Also note that since this tool only queries the rpm database, and doesn't write or change anything, so safe to play around with.

For example
 # ./dep-tree.php mozilla
   <.. shows the complete tree of all  the dep. packages & package sizes..>
 Number of packages: 66
 Total size installed: 165 Mb
 Total packaged size:  59 Mb

With this tool it's a lot easier to experiment with 'what if', and try out what the real impact is of including package XYZ in the core CD.

It can also take multiple packages on the command line, and will do a full dependency tree run for all those packages, so you could see how many packages, and what packaged size something like the packages "firstboot system-config-packages mozilla" would take up..

This script requires PHP and RPM to be installed to run. Save the attached dep-tree.php to disk and run by
# chmod +x dep-tree.php
# ./dep-tree.php
or
# php -Cq ./dep-tree.php



Usage explained in detail: dep-tree.php [-d] [-r=path] package [package package]


package [package..] List of packages to include in the dependency tree run, for example: "mozilla openoffice.org sendmail"

-d Include the *-devel packages for all packages in the list (and it's dependencies). This is includes because i am a big fan of having a system that could build it's self, it's updates and any other source rpm's/tarbals you would download.

-r=/path (For users who know what they are doing only!) Use --root=/path in all rpm commands. The rpm --root command allows you to query against a rpm database other then the standard location. This is usefull for if you want to play with all installed packages or packages you don't have installed in your normal setup without having to modify your existing setup by doing something like this (Note: Please please by all that is holy, don't forget to include --root=/fc2-tests in your rpm --initdb command, else you will NUKE, DELETE and DESTROY your rpm database!)
# mkdir /fc2-test
# rpm --initdb --root=/fc2-test
# rpm -Uvh --root=/fc2-test --nomd5 --nodigest --nosignature --justdb /location/to/all/fc2/rpms/*.rpm



#!/usr/bin/php -Cq
<?
// Written by Chris Chabot
// Published under the GNU GPL for licence
// You know what it is and where to find it..

function usage()
{
	global $argv;
	
	echo "Usage: {$argv[0]} [-d] [-r=path] package [package package]\n\n".
	     "  -r=path (optional):  Use this for RPM's --root\n".
		 "  -d (optional):       Include devel package(s)\n".
	     "  package              Name of installed package(s)\n".
		 "\n";
	exit(1);
}

function get_devel_list()
{
	global $devels, $root;
	$exec   = "rpm -qa $root --qf \"%{NAME}\n\" | grep devel";
	$output = `$exec`;
	$devels = explode("\n",$output);
}

function get_sizes($package)
{
	global $size_installed, $size_packages, $root;
	$exec     = "rpm -q $root --qf \"%{SIZE} %{SIGSIZE}\" ".escapeshellarg($package);
	$output   = `$exec`;
	$sizes    = explode(' ',$output);
	if (isset($sizes[0]) && is_numeric($sizes[0])) {
		$size_installed += (int) $sizes[0];
	}
	if (isset($sizes[1]) && is_numeric($sizes[1])) {
		$size_packages += (int) $sizes[1];
		echo " (".ceil($sizes[1] / 1024)." Kb)";
	}
}

function what_provides($p_requires)
{
	global $files_done, $requires, $root;
	$packages = array();
	reset($p_requires);
	while (list($require,) = each($p_requires)) {
		// Check if require has already been done
		if (!isset($files_done[$require])) {
			$exec     = "rpm -q $root --whatprovides \"$require\" --qf \"%{NAME}\"";
			$output   = `$exec`;
			if (strpos($output,'no package') === FALSE) {
					$output               = trim($output);
					$packages[$output]    = $output;
					$files_done[$require] = $output;
			} elseif (isset($files_done[$require])) {
				$packages[$output] = $files_done[$require];
			}  else {
				// echo "No package provides: \"$require\"\n";
			}
		}
	}
	return $packages;
}

function package_requires($package)
{
	global $root;
	$exec   = "rpm -q $root --requires ".escapeshellarg($package);
	$output = `$exec`;
	$output = explode("\n",$output);
	unset($output[count($output)-1]);
	$list   = array();
	while (list(,$require) = each($output)) {
		if (($pos = strpos($require,' ')) !== FALSE) {
			$require = trim(substr($require,0,$pos));
		}
		// Skip internal rpmlib tags which are not 'provided'
		if (!isset($list[$require]) && strpos($require,'rpmlib') === false && strpos($require,'perl') === false) {
			$list[$require] = TRUE;
		}
	}
	return $list;
}

function find_package_require($package)
{
	global $requires, $level, $devel, $devels, $packages;
	// Don't re-require self
	$packages++;
	$requires[$package] = $package;
	echo str_repeat('  ',$level).$package;
	get_sizes($package);
	echo "\n";
	$p_requires = package_requires($package);
	if (count($p_requires)) {
		$pkgs = what_provides($p_requires);
		if (count($pkgs)) {
			$level++;
			reset($pkgs);
			while (list(,$pkg) = each($pkgs)) {
				// Skip dep's we've already done
				if (!isset($requires[$pkg])) {
					$requires[$pkg] = $pkg;
					find_package_require($pkg);
				}
			}
			$level--;
		}
	}
	if ($devel) {
		reset($devels);
		while (list(,$pkg) = each($devels)) {
			if ($pkg == $package."-devel") {
				find_package_require($pkg);
				break;
			}
		}
	}
}

echo "\nDep Tree 0.1 by Chris Chabot.\nThis program may be freely redistributed under the terms of the GNU GPL.\n\n";
// Program initialisation
$requires       = array();
$files_done     = array();
$devels         = array();
$packages       = 0;
$level          = 0;
$max_level      = 9999;
$size_installed = 0;
$size_packages  = 0;
$devel          = false;
$root           = '';

if ($argc < 2) {
	usage();
} else {
	for ($i = 1 ; $i < $argc ; $i++) {
		if ($argv[$i] == '-d') {
			$devel = TRUE;
			get_devel_list();
		} elseif (substr($argv[$i],0,2) == '-r') {
			$root = substr($argv[$i],3);
			if (!file_exists($root)) {
				die("Invalid RPM root specified, $root doesn't exist. Aborting\n");
			}
			$root = " --root=$root ";
		}
	}
	for ($i = 1 ; $i < $argc ; $i++) {
		if (substr($argv[$i],0,1) != '-') {
			// If package was already evaluted as dependencie, don't re-process it
			if (!isset($requires[$argv[$i]])) {
				find_package_require($argv[$i]);
			}
		}
	}
}
echo "\n\n";
echo "Number of packages: $packages\n";
echo "Total size installed: ".ceil(($size_installed / 1024) / 1024)." Mb\n";
echo "Total packaged size:  ".ceil(($size_packages / 1024) / 1024)." Mb\n";
echo "\n";

?>

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]