]>
Commit | Line | Data |
---|---|---|
47a4cb89 MT |
1 | #!/usr/bin/python |
2 | ||
3 | import logging | |
4 | ||
5 | import depsolve | |
1de8761d | 6 | import packages |
47a4cb89 MT |
7 | import util |
8 | ||
9 | from i18n import _ | |
10 | ||
11 | class ActionError(Exception): | |
12 | pass | |
13 | ||
14 | ||
15 | class Action(object): | |
16 | def __init__(self, pakfire, pkg, deps=None): | |
17 | self.pakfire = pakfire | |
18 | self.pkg = pkg | |
19 | self.deps = deps or [] | |
20 | ||
21 | def __cmp__(self, other): | |
22 | # XXX ugly | |
23 | return cmp(self.__repr__(), other.__repr__()) | |
24 | ||
25 | def __repr__(self): | |
26 | return "<%s %s>" % (self.__class__.__name__, self.pkg.friendly_name) | |
27 | ||
28 | def remove_dep(self, dep): | |
29 | if not self.deps: | |
30 | return | |
31 | ||
32 | while dep in self.deps: | |
33 | logging.debug("Removing dep %s from %s" % (dep, self)) | |
34 | self.deps.remove(dep) | |
35 | ||
36 | def run(self): | |
37 | raise NotImplementedError | |
38 | ||
39 | @property | |
40 | def local(self): | |
41 | """ | |
42 | Reference to local repository (database). | |
43 | """ | |
44 | return self.pakfire.repos.local | |
45 | ||
46 | ||
47 | class ActionExtract(Action): | |
48 | def run(self): | |
49 | logging.debug("Extracting package %s" % self.pkg.friendly_name) | |
50 | ||
51 | # Create package in the database | |
66af936c | 52 | virtpkg = self.local.index.add_package(self.pkg) |
47a4cb89 MT |
53 | |
54 | # Grab an instance of the extractor and set it up | |
55 | extractor = self.pkg.get_extractor(self.pakfire) | |
56 | ||
57 | # Extract all files to instroot | |
66af936c | 58 | extractor.extractall(self.pakfire.path) |
47a4cb89 MT |
59 | |
60 | # Remove all temporary files | |
61 | extractor.cleanup() | |
62 | ||
63 | ||
64 | class ActionScript(Action): | |
65 | def run(self): | |
66 | pass # XXX TBD | |
67 | ||
68 | ||
69 | class ActionScriptPreIn(ActionScript): | |
70 | pass | |
71 | ||
72 | ||
73 | class ActionScriptPostIn(ActionScript): | |
74 | pass | |
75 | ||
76 | ||
77 | class ActionScriptPreUn(ActionScript): | |
78 | pass | |
79 | ||
80 | ||
81 | class ActionScriptPostUn(ActionScript): | |
82 | pass | |
83 | ||
84 | ||
85 | class ActionInstall(Action): | |
86 | pass | |
87 | ||
88 | ||
89 | class ActionRemove(Action): | |
90 | pass | |
91 | ||
92 | ||
93 | class TransactionSet(object): | |
1de8761d MT |
94 | def __init__(self): |
95 | self.installs = [] | |
96 | self.install_deps = [] | |
47a4cb89 | 97 | |
1de8761d MT |
98 | self.updates = [] |
99 | self.update_deps = [] | |
47a4cb89 | 100 | |
1de8761d MT |
101 | self.removes = [] |
102 | self.remove_deps = [] | |
47a4cb89 | 103 | |
20d2b270 MT |
104 | @property |
105 | def download_lists(self): | |
106 | # All elements in these lists must be local. | |
107 | return (self.installs, self.install_deps, self.updates, self.update_deps) | |
108 | ||
edd6a268 MT |
109 | @property |
110 | def downloads(self): | |
111 | """ | |
112 | Return a list containing all packages that need to be downloaded. | |
113 | """ | |
20d2b270 MT |
114 | pkgs = [] |
115 | for dl_list in self.download_lists: | |
116 | pkgs += dl_list | |
117 | pkgs.sort() | |
118 | ||
119 | for pkg in pkgs: | |
edd6a268 MT |
120 | # Skip all packages that are already local. |
121 | if pkg.local: | |
122 | continue | |
123 | ||
124 | yield pkg | |
125 | ||
1de8761d MT |
126 | def install(self, pkg, dep=False): |
127 | logging.info(" --> Marking package for install: %s" % pkg.friendly_name) | |
47a4cb89 | 128 | |
1de8761d MT |
129 | if dep: |
130 | self.install_deps.append(pkg) | |
131 | else: | |
132 | self.installs.append(pkg) | |
47a4cb89 | 133 | |
1de8761d MT |
134 | def remove(self, pkg, dep=False): |
135 | logging.info(" --> Marking package for remove: %s" % pkg.friendly_name) | |
136 | ||
137 | if dep: | |
138 | self.remove_deps.append(pkg) | |
139 | else: | |
140 | self.removes.append(pkg) | |
141 | ||
142 | def update(self, pkg, dep=False): | |
143 | logging.info(" --> Marking package for update: %s" % pkg.friendly_name) | |
144 | ||
145 | if dep: | |
146 | self.update_deps.append(pkg) | |
147 | else: | |
148 | self.updates.append(pkg) | |
149 | ||
150 | def download(self): | |
4f91860e MT |
151 | """ |
152 | Convert all packages to BinaryPackage. | |
153 | """ | |
14ea3228 MT |
154 | pkgs = [] |
155 | for pkg in self.downloads: | |
156 | pkgs.append(pkg) | |
157 | ||
158 | # If there are no packages to download skip the rest. | |
159 | if not pkgs: | |
160 | return | |
161 | ||
162 | logging.info("Downloading packages:") | |
163 | i = 0 | |
164 | for download in pkgs: | |
165 | i += 1 | |
166 | pkg = download.download(text="(%2d/%02d): " % (i, len(pkgs))) | |
20d2b270 MT |
167 | |
168 | for download_list in self.download_lists: | |
169 | if download in download_list: | |
170 | download_list.remove(download) | |
171 | download_list.append(pkg) | |
172 | break | |
1de8761d | 173 | |
14ea3228 MT |
174 | # Just an empty line to seperate the downloads from the extractions. |
175 | logging.info("") | |
176 | ||
1de8761d MT |
177 | |
178 | class Transaction(object): | |
179 | def __init__(self, pakfire, ds): | |
180 | self.pakfire = pakfire | |
181 | self.ds = ds | |
182 | ||
183 | self._actions = [] | |
47a4cb89 MT |
184 | |
185 | def _install_pkg(self, pkg): | |
1de8761d MT |
186 | assert isinstance(pkg, packages.BinaryPackage) |
187 | ||
47a4cb89 MT |
188 | # XXX add dependencies for running the script here |
189 | action_prein = ActionScriptPreIn(self.pakfire, pkg) | |
190 | ||
191 | action_extract = ActionExtract(self.pakfire, pkg, deps=[action_prein]) | |
192 | ||
193 | # XXX add dependencies for running the script here | |
194 | action_postin = ActionScriptPostIn(self.pakfire, pkg, deps=[action_extract]) | |
195 | ||
196 | for action in (action_prein, action_extract, action_postin): | |
197 | self.add_action(action) | |
198 | ||
47a4cb89 | 199 | def _update_pkg(self, pkg): |
1de8761d MT |
200 | assert isinstance(pkg, packages.BinaryPackage) |
201 | ||
47a4cb89 MT |
202 | action_extract = ActionExtract(self.pakfire, pkg) |
203 | ||
204 | self.add_action(action_extract) | |
47a4cb89 MT |
205 | |
206 | def _remove_pkg(self, pkg): | |
207 | # XXX TBD | |
1de8761d | 208 | pass |
47a4cb89 MT |
209 | |
210 | def populate(self): | |
47a4cb89 MT |
211 | # Determine which packages we have to add |
212 | # and which we have to remove. | |
213 | ||
1de8761d MT |
214 | # Add all packages that need to be installed. |
215 | for pkg in self.ds.ts.installs + self.ds.ts.install_deps: | |
216 | self._install_pkg(pkg) | |
47a4cb89 | 217 | |
1de8761d MT |
218 | # Add all packages that need to be updated. |
219 | for pkg in self.ds.ts.updates + self.ds.ts.update_deps: | |
220 | self._update_pkg(pkg) | |
47a4cb89 | 221 | |
1de8761d MT |
222 | # Add all packages that need to be removed. |
223 | for pkg in self.ds.ts.removes + self.ds.ts.remove_deps: | |
224 | self._remove_pkg(pkg) | |
47a4cb89 MT |
225 | |
226 | def add_action(self, action): | |
227 | logging.debug("New action added: %s" % action) | |
228 | ||
229 | self._actions.append(action) | |
230 | ||
231 | def remove_action(self, action): | |
232 | logging.debug("Removing action: %s" % action) | |
233 | ||
234 | self._actions.remove(action) | |
235 | for _action in self.actions: | |
236 | _action.remove_dep(action) | |
237 | ||
47a4cb89 MT |
238 | @property |
239 | def actions(self): | |
240 | for action in self._actions: | |
241 | yield action | |
242 | ||
243 | @property | |
244 | def packages(self): | |
245 | for action in self._actions: | |
246 | yield action.pkg | |
247 | ||
248 | def run_action(self, action): | |
249 | try: | |
250 | action.run() | |
251 | except ActionError, e: | |
252 | logging.error("Action finished with an error: %s - %s" % (action, e)) | |
253 | ||
254 | def run(self): | |
1de8761d MT |
255 | # Download all packages. |
256 | self.ds.ts.download() | |
257 | ||
258 | # Create all the actions that need to be done. | |
259 | self.populate() | |
260 | ||
47a4cb89 MT |
261 | while True: |
262 | if not [a for a in self.actions]: | |
263 | break | |
264 | ||
265 | for action in self.actions: | |
266 | if action.deps: | |
267 | #logging.debug("Skipping %s which cannot be run now." % action) | |
268 | continue | |
269 | ||
270 | self.run_action(action) | |
271 | self.remove_action(action) | |
272 |