1 |
""" |
2 |
# Copyright 1999-2005 Gentoo Foundation |
3 |
# This source code is distributed under the terms of version 2 of the GNU |
4 |
# General Public License as published by the Free Software Foundation, a copy |
5 |
# of which can be found in the main directory of this project. |
6 |
Gentoo Linux Installer |
7 |
|
8 |
$Id: GLIPortage.py,v 1.5 2005/12/25 05:06:35 agaffney Exp $ |
9 |
""" |
10 |
|
11 |
import os |
12 |
import re |
13 |
import GLIUtility |
14 |
|
15 |
class MissingPackagesError(Exception): |
16 |
pass |
17 |
|
18 |
class depgraph: |
19 |
|
20 |
def __init__(self): |
21 |
self.graph = {} |
22 |
|
23 |
def add(self, node, parent=None): |
24 |
if node not in self.graph: |
25 |
self.graph[node] = [[], []] |
26 |
if parent and parent not in self.graph[node][0]: |
27 |
if parent not in self.graph: |
28 |
self.graph[parent] = [[], []] |
29 |
self.graph[node][0].append(parent) |
30 |
self.graph[parent][1].append(node) |
31 |
|
32 |
def remove(self, node): |
33 |
for parent in self.graph[node][0]: |
34 |
self.graph[parent][1].remove(node) |
35 |
for child in self.graph[node][1]: |
36 |
self.graph[child][0].remove(node) |
37 |
return self.graph.pop(node) |
38 |
|
39 |
def has_node(self, node): |
40 |
return node in self.graph |
41 |
|
42 |
def leaf_nodes(self): |
43 |
return [node for node in self.graph if not self.graph[node][1]] |
44 |
|
45 |
def node_count(self): |
46 |
return len(self.graph) |
47 |
|
48 |
def important_node(self): |
49 |
important_node = None |
50 |
importance = 0 |
51 |
for node in self.graph: |
52 |
if len(self.graph[node][0]) > importance: |
53 |
importance = len(self.graph[node][0]) |
54 |
important_node = node |
55 |
return important_node |
56 |
|
57 |
class GLIPortage(object): |
58 |
|
59 |
def __init__(self, chroot_dir, grp_install, logger, debug): |
60 |
self._chroot_dir = chroot_dir |
61 |
self._logger = logger |
62 |
self._debug = debug |
63 |
self._grp_install = grp_install |
64 |
|
65 |
def resolve_deps(self, dep_list): |
66 |
if dep_list and dep_list[0] == "||": |
67 |
for dep in dep_list[1:]: |
68 |
if isinstance(dep, list): |
69 |
try: |
70 |
atoms = resolve_deps(dep) |
71 |
except MissingPackagesError: |
72 |
continue |
73 |
else: |
74 |
atoms = [dep] |
75 |
all_found = True |
76 |
for atom in atoms: |
77 |
if not atom.startswith("!") and not self.vdb.match(atom): |
78 |
all_found = False |
79 |
break |
80 |
if all_found: |
81 |
return atoms |
82 |
raise MissingPackagesError(dep_list) |
83 |
atoms = [] |
84 |
for dep in dep_list: |
85 |
if isinstance(dep, list): |
86 |
atoms.extend(resolve_deps(dep)) |
87 |
elif not dep.startswith("!"): |
88 |
if not self.vdb.match(dep): |
89 |
raise MissingPackagesError([dep]) |
90 |
atoms.append(dep) |
91 |
return atoms |
92 |
|
93 |
def get_deps(self, pkgs): |
94 |
if not self._grp_install: |
95 |
del(os.environ['ROOT']) |
96 |
return GLIUtility.spawn("emerge -p " + pkgs + r" | grep -e '^\[[a-z]' | cut -d ']' -f2 | sed -e 's:^ ::' -e 's: .\+$::'", chroot=self._chroot_dir, return_output=True)[1].split("\n") |
97 |
os.environ['ROOT'] = self._chroot_dir |
98 |
else: |
99 |
return GLIUtility.spawn("../../runtimedeps.py " + pkgs, return_output=True)[1].split("\n")[:-1] |
100 |
|
101 |
def copy_pkg_to_chroot(self, package): |
102 |
symlinks = { '/bin/': '/mnt/livecd/bin/', '/boot/': '/mnt/livecd/boot/', '/lib/': '/mnt/livecd/lib/', |
103 |
'/opt/': '/mnt/livecd/opt/', '/sbin/': '/mnt/livecd/sbin/', '/usr/': '/mnt/livecd/usr/', |
104 |
'/etc/gconf/': '/usr/livecd/gconf/' } |
105 |
|
106 |
# Copy the vdb entry for the package from the LiveCD to the chroot |
107 |
if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): copying vdb entry for " + package) |
108 |
if not GLIUtility.exitsuccess(GLIUtility.spawn("mkdir -p " + self._chroot_dir + "/var/db/pkg/" + package + " && cp -a /var/db/pkg/" + package + "/* " + self._chroot_dir + "/var/db/pkg/" + package)): |
109 |
raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not copy vdb entry for " + package) |
110 |
|
111 |
# Create list of files for tar to work with from CONTENTS file in vdb entry |
112 |
entries = GLIUtility.parse_vdb_contents("/var/db/pkg/" + package + "/CONTENTS") |
113 |
if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot: files for " + package + ": " + str(entries)) |
114 |
try: |
115 |
tarfiles = open("/tmp/tarfilelist", "w") |
116 |
for entry in entries: |
117 |
parts = entry.split(" ") |
118 |
# Hack for symlink crappiness |
119 |
for symlink in symlinks: |
120 |
if parts[0].startswith(symlink): |
121 |
parts[0] = symlinks[symlink] + parts[0][len(symlink):] |
122 |
tarfiles.write(parts[0] + "\n") |
123 |
tarfiles.close() |
124 |
except: |
125 |
raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not create filelist for " + package) |
126 |
|
127 |
# Use tar to transfer files into IMAGE directory |
128 |
tmpdir = "/var/tmp/portage" |
129 |
image_dir = tmpdir + "/" + package.split("/")[1] + "/image" |
130 |
if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running 'mkdir -p " + self._chroot_dir + image_dir + " && tar -c --files-from=/tmp/tarfilelist --no-recursion 2>/dev/null | tar -C " + self._chroot_dir + image_dir + " -x'") |
131 |
if not GLIUtility.exitsuccess(GLIUtility.spawn("mkdir -p " + self._chroot_dir + image_dir + " && tar -c --files-from=/tmp/tarfilelist --no-recursion 2>/dev/null | tar -C " + self._chroot_dir + image_dir + " -x")): |
132 |
raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not execute tar for " + package) |
133 |
|
134 |
# More symlink crappiness hacks |
135 |
for symlink in symlinks: |
136 |
if GLIUtility.is_file(self._chroot_dir + image_dir + symlinks[symlink]): |
137 |
# parts[0] = symlinks[symlink] + parts[len(symlink):] |
138 |
if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): fixing /usr/livecd/gconf/ stuff in " + image_dir + " for " + package) |
139 |
if not GLIUtility.exitsuccess(GLIUtility.spawn("mv " + self._chroot_dir + image_dir + symlinks[symlink] + " " + self._chroot_dir + image_dir + symlink)): |
140 |
raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not fix /usr/livecd/gconf/ stuff for " + package) |
141 |
|
142 |
# Run pkg_setup |
143 |
if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running pkg_setup for " + package) |
144 |
if not GLIUtility.exitsuccess(GLIUtility.spawn("env ROOT=" + self._chroot_dir + " PORTAGE_TMPDIR=" + self._chroot_dir + tmpdir + " ebuild " + self._chroot_dir + "/var/db/pkg/" + package + "/*.ebuild setup")): |
145 |
raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not execute pkg_setup for " + package) |
146 |
|
147 |
# Run qmerge |
148 |
# if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running qmerge for " + package) |
149 |
# if not GLIUtility.exitsuccess(GLIUtility.spawn("env ROOT=" + self._chroot_dir + " PORTAGE_TMPDIR=" + self._chroot_dir + tmpdir + " ebuild " + self._chroot_dir + "/var/db/pkg/" + package + "/*.ebuild qmerge")): |
150 |
# raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not execute qmerge for " + package) |
151 |
|
152 |
# Run pkg_preinst |
153 |
if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running preinst for " + package) |
154 |
if not GLIUtility.exitsuccess(GLIUtility.spawn("env ROOT=" + self._chroot_dir + " PORTAGE_TMPDIR=" + self._chroot_dir + tmpdir + " ebuild " + self._chroot_dir + "/var/db/pkg/" + package + "/*.ebuild preinst")): |
155 |
raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not execute preinst for " + package) |
156 |
|
157 |
# Copy files from image_dir to chroot |
158 |
if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): copying files from " + image_dir + " to / for " + package) |
159 |
if not GLIUtility.exitsuccess(GLIUtility.spawn("cp -a " + self._chroot_dir + image_dir + "/* " + self._chroot_dir)): |
160 |
raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not copy files from " + image_dir + " to / for " + package) |
161 |
|
162 |
# Run pkg_postinst |
163 |
if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running postinst for " + package) |
164 |
if not GLIUtility.exitsuccess(GLIUtility.spawn("env ROOT=" + self._chroot_dir + " PORTAGE_TMPDIR=" + self._chroot_dir + tmpdir + " ebuild " + "/var/db/pkg/" + package + "/*.ebuild postinst")): |
165 |
raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not execute postinst for " + package) |
166 |
|
167 |
# Remove image_dir |
168 |
if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): removing + " + image_dir + " for " + package) |
169 |
if not GLIUtility.exitsuccess(GLIUtility.spawn("rm -rf " + self._chroot_dir + image_dir)): |
170 |
raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not remove + " + image_dir + " for " + package) |
171 |
|
172 |
def add_pkg_to_world(self, package): |
173 |
if package.find("/") == -1: |
174 |
package = GLIUtility.spawn("portageq best_version / " + package, chroot=self._chroot_dir, return_output=True)[1].strip() |
175 |
if not package: return False |
176 |
expr = re.compile('^(.+?)(-\d.+)?$') |
177 |
res = expr.match(package) |
178 |
if res: |
179 |
GLIUtility.spawn("echo " + res.group(1) + " >> " + self._chroot_dir + "/var/lib/portage/world") |
180 |
|
181 |
def get_best_version_vdb(self, package): |
182 |
return GLIUtility.spawn("portageq best_version / " + package, return_output=True)[1].strip() |
183 |
# |
184 |
# def get_best_version_tree(self, package): |
185 |
# return portage.best(tree.match(package)) |