]>
Commit | Line | Data |
---|---|---|
47a4cb89 MT |
1 | #!/usr/bin/python |
2 | ||
3 | import argparse | |
4 | import sys | |
5 | ||
6 | import packages | |
fa6d335b | 7 | import repository |
677ff42a | 8 | import server |
e9c20259 | 9 | import util |
47a4cb89 MT |
10 | |
11 | from pakfire import Pakfire | |
12 | ||
13 | from constants import * | |
14 | from i18n import _ | |
15 | ||
16 | def ask_user(question): | |
17 | """ | |
18 | Ask the user the question, he or she can answer with yes or no. | |
19 | ||
20 | This function returns True for "yes" and False for "no". | |
21 | ||
22 | If the software is running in a non-inteactive shell, no question | |
23 | is asked at all and the answer is always "yes". | |
24 | """ | |
e9c20259 | 25 | if not util.cli_is_interactive(): |
47a4cb89 MT |
26 | return True |
27 | ||
28 | print _("%s [y/N]") % question, | |
29 | ret = raw_input() | |
30 | ||
ced5e511 | 31 | return ret in ("y", "Y", "z", "Z", "j", "J") |
47a4cb89 MT |
32 | |
33 | class Cli(object): | |
47a4cb89 MT |
34 | def __init__(self): |
35 | self.parser = argparse.ArgumentParser( | |
36 | description = _("Pakfire command line interface."), | |
37 | ) | |
38 | ||
39 | self.parse_common_arguments() | |
40 | ||
41 | self.parser.add_argument("--instroot", metavar="PATH", | |
d2e26956 | 42 | default="/", |
47a4cb89 MT |
43 | help=_("The path where pakfire should operate in.")) |
44 | ||
45 | # Add sub-commands. | |
46 | self.sub_commands = self.parser.add_subparsers() | |
47 | ||
48 | self.parse_command_install() | |
5e87fa4f | 49 | self.parse_command_localinstall() |
47a4cb89 MT |
50 | self.parse_command_info() |
51 | self.parse_command_search() | |
52 | self.parse_command_update() | |
fa6d335b | 53 | self.parse_command_provides() |
b0bcdb49 | 54 | self.parse_command_requires() |
c1962d40 | 55 | self.parse_command_grouplist() |
ce2764c1 | 56 | self.parse_command_groupinstall() |
67bc4528 | 57 | self.parse_command_repolist() |
47a4cb89 MT |
58 | |
59 | # Finally parse all arguments from the command line and save them. | |
60 | self.args = self.parser.parse_args() | |
61 | ||
62 | # Create instance of the wonderful pakfire :) | |
63 | self.pakfire = Pakfire( | |
64 | self.args.instroot, | |
65 | configs = [self.args.config], | |
f781b1ab | 66 | disable_repos = self.args.disable_repo, |
47a4cb89 MT |
67 | ) |
68 | ||
69 | self.action2func = { | |
5e87fa4f MT |
70 | "install" : self.handle_install, |
71 | "localinstall" : self.handle_localinstall, | |
72 | "update" : self.handle_update, | |
73 | "info" : self.handle_info, | |
74 | "search" : self.handle_search, | |
fa6d335b | 75 | "provides" : self.handle_provides, |
b0bcdb49 | 76 | "requires" : self.handle_requires, |
c1962d40 | 77 | "grouplist" : self.handle_grouplist, |
ce2764c1 | 78 | "groupinstall" : self.handle_groupinstall, |
67bc4528 | 79 | "repolist" : self.handle_repolist, |
47a4cb89 MT |
80 | } |
81 | ||
82 | def parse_common_arguments(self): | |
83 | self.parser.add_argument("-v", "--verbose", action="store_true", | |
84 | help=_("Enable verbose output.")) | |
85 | ||
86 | self.parser.add_argument("-c", "--config", nargs="?", | |
87 | help=_("Path to a configuration file to load.")) | |
88 | ||
f781b1ab MT |
89 | self.parser.add_argument("--disable-repo", nargs="*", metavar="REPO", |
90 | help=_("Disable a repository temporarily.")) | |
91 | ||
47a4cb89 MT |
92 | def parse_command_install(self): |
93 | # Implement the "install" command. | |
94 | sub_install = self.sub_commands.add_parser("install", | |
95 | help=_("Install one or more packages to the system.")) | |
96 | sub_install.add_argument("package", nargs="+", | |
97 | help=_("Give name of at least one package to install.")) | |
98 | sub_install.add_argument("action", action="store_const", const="install") | |
99 | ||
5e87fa4f MT |
100 | def parse_command_localinstall(self): |
101 | # Implement the "localinstall" command. | |
102 | sub_install = self.sub_commands.add_parser("localinstall", | |
103 | help=_("Install one or more packages from the filesystem.")) | |
104 | sub_install.add_argument("package", nargs="+", | |
105 | help=_("Give filename of at least one package.")) | |
106 | sub_install.add_argument("action", action="store_const", const="localinstall") | |
107 | ||
47a4cb89 MT |
108 | def parse_command_update(self): |
109 | # Implement the "update" command. | |
110 | sub_update = self.sub_commands.add_parser("update", | |
111 | help=_("Update the whole system or one specific package.")) | |
112 | sub_update.add_argument("package", nargs="*", | |
113 | help=_("Give a name of a package to update or leave emtpy for all.")) | |
114 | sub_update.add_argument("action", action="store_const", const="update") | |
115 | ||
116 | def parse_command_info(self): | |
117 | # Implement the "info" command. | |
118 | sub_info = self.sub_commands.add_parser("info", | |
119 | help=_("Print some information about the given package(s).")) | |
120 | sub_info.add_argument("package", nargs="+", | |
121 | help=_("Give at least the name of one package.")) | |
122 | sub_info.add_argument("action", action="store_const", const="info") | |
123 | ||
124 | def parse_command_search(self): | |
125 | # Implement the "search" command. | |
126 | sub_search = self.sub_commands.add_parser("search", | |
127 | help=_("Search for a given pattern.")) | |
128 | sub_search.add_argument("pattern", | |
129 | help=_("A pattern to search for.")) | |
130 | sub_search.add_argument("action", action="store_const", const="search") | |
131 | ||
fa6d335b MT |
132 | def parse_command_provides(self): |
133 | # Implement the "provides" command | |
134 | sub_provides = self.sub_commands.add_parser("provides", | |
135 | help=_("Get a list of packages that provide a given file or feature.")) | |
136 | sub_provides.add_argument("pattern", nargs="+", | |
137 | help=_("File or feature to search for.")) | |
138 | sub_provides.add_argument("action", action="store_const", const="provides") | |
139 | ||
b0bcdb49 MT |
140 | def parse_command_requires(self): |
141 | # Implement the "requires" command | |
142 | sub_requires = self.sub_commands.add_parser("requires", | |
143 | help=_("Get a list of packages that require a given file or feature.")) | |
144 | sub_requires.add_argument("pattern", nargs="+", | |
145 | help=_("File or feature to search for.")) | |
146 | sub_requires.add_argument("action", action="store_const", const="requires") | |
147 | ||
c1962d40 MT |
148 | def parse_command_grouplist(self): |
149 | # Implement the "grouplist" command | |
150 | sub_grouplist = self.sub_commands.add_parser("grouplist", | |
151 | help=_("Get list of packages that belong to the given group.")) | |
152 | sub_grouplist.add_argument("group", nargs=1, | |
153 | help=_("Group name to search for.")) | |
154 | sub_grouplist.add_argument("action", action="store_const", const="grouplist") | |
155 | ||
ce2764c1 MT |
156 | def parse_command_groupinstall(self): |
157 | # Implement the "grouplist" command | |
158 | sub_groupinstall = self.sub_commands.add_parser("groupinstall", | |
159 | help=_("Install all packages that belong to the given group.")) | |
160 | sub_groupinstall.add_argument("group", nargs=1, | |
161 | help=_("Group name.")) | |
162 | sub_groupinstall.add_argument("action", action="store_const", const="groupinstall") | |
163 | ||
67bc4528 MT |
164 | def parse_command_repolist(self): |
165 | # Implement the "repolist" command | |
166 | sub_repolist = self.sub_commands.add_parser("repolist", | |
167 | help=_("List all currently enabled repositories.")) | |
168 | sub_repolist.add_argument("action", action="store_const", const="repolist") | |
ce2764c1 | 169 | |
47a4cb89 MT |
170 | def run(self): |
171 | action = self.args.action | |
172 | ||
173 | if not self.action2func.has_key(action): | |
174 | raise | |
175 | ||
176 | try: | |
177 | func = self.action2func[action] | |
178 | except KeyError: | |
179 | raise # XXX catch and return better error message | |
180 | ||
181 | return func() | |
182 | ||
9afa5620 | 183 | def handle_info(self, long=False): |
47a4cb89 MT |
184 | for pattern in self.args.package: |
185 | pkgs = self.pakfire.repos.get_by_glob(pattern) | |
186 | ||
187 | pkgs = packages.PackageListing(pkgs) | |
188 | ||
189 | for pkg in pkgs: | |
9afa5620 | 190 | print pkg.dump(long=long) |
47a4cb89 MT |
191 | |
192 | def handle_search(self): | |
193 | pkgs = self.pakfire.repos.search(self.args.pattern) | |
194 | ||
195 | pkgs = packages.PackageListing(pkgs) | |
196 | ||
197 | for pkg in pkgs: | |
198 | print pkg.dump(short=True) | |
199 | ||
200 | def handle_update(self): | |
a412c989 | 201 | self.pakfire.update(self.args.package) |
47a4cb89 | 202 | |
5e87fa4f MT |
203 | def handle_install(self, local=False): |
204 | if local: | |
205 | repo = repository.FileSystemRepository(self.pakfire) | |
206 | ||
207 | pkgs = [] | |
208 | for pkg in self.args.package: | |
209 | if local and os.path.exists(pkg): | |
210 | pkg = packages.BinaryPackage(self.pakfire, repo, pkg) | |
211 | ||
212 | pkgs.append(pkg) | |
213 | ||
214 | self.pakfire.install(pkgs) | |
215 | ||
216 | def handle_localinstall(self): | |
217 | return self.handle_install(local=True) | |
218 | ||
fa6d335b MT |
219 | def handle_provides(self): |
220 | pkgs = self.pakfire.provides(self.args.pattern) | |
221 | ||
222 | for pkg in pkgs: | |
223 | print pkg.dump() | |
224 | ||
b0bcdb49 MT |
225 | def handle_requires(self): |
226 | pkgs = self.pakfire.requires(self.args.pattern) | |
227 | ||
228 | for pkg in pkgs: | |
229 | print pkg.dump() | |
230 | ||
c1962d40 MT |
231 | def handle_grouplist(self): |
232 | pkgs = self.pakfire.grouplist(self.args.group[0]) | |
233 | ||
234 | for pkg in pkgs: | |
235 | print " * %s" % pkg | |
236 | ||
ce2764c1 MT |
237 | def handle_groupinstall(self): |
238 | self.pakfire.groupinstall(self.args.group[0]) | |
239 | ||
67bc4528 MT |
240 | def handle_repolist(self): |
241 | repos = self.pakfire.repolist() | |
242 | repos.sort() | |
243 | ||
244 | FORMAT = " %-20s %8s %12s " | |
245 | ||
246 | title = FORMAT % (_("Repository"), _("Enabled"), _("Priority")) | |
247 | print title | |
248 | print "=" * len(title) # spacing line | |
249 | ||
250 | for repo in repos: | |
251 | # Skip the installed repository. | |
252 | if repo.name == "installed": | |
253 | continue | |
254 | ||
255 | print FORMAT % (repo.name, repo.enabled, repo.priority) | |
256 | ||
47a4cb89 MT |
257 | |
258 | class CliBuilder(Cli): | |
259 | def __init__(self): | |
260 | self.parser = argparse.ArgumentParser( | |
261 | description = _("Pakfire builder command line interface."), | |
262 | ) | |
263 | ||
264 | self.parse_common_arguments() | |
265 | ||
266 | # Add sub-commands. | |
267 | self.sub_commands = self.parser.add_subparsers() | |
268 | ||
269 | self.parse_command_build() | |
270 | self.parse_command_dist() | |
271 | self.parse_command_info() | |
272 | self.parse_command_search() | |
273 | self.parse_command_shell() | |
274 | self.parse_command_update() | |
4fbd4216 | 275 | self.parse_command_provides() |
b0bcdb49 | 276 | self.parse_command_requires() |
2c84aceb | 277 | self.parse_command_grouplist() |
67bc4528 | 278 | self.parse_command_repolist() |
47a4cb89 MT |
279 | |
280 | # Finally parse all arguments from the command line and save them. | |
281 | self.args = self.parser.parse_args() | |
282 | ||
283 | self.pakfire = Pakfire( | |
284 | builder = True, | |
285 | configs = [self.args.config], | |
f781b1ab | 286 | disable_repos = self.args.disable_repo, |
47a4cb89 MT |
287 | ) |
288 | ||
289 | self.action2func = { | |
fa6d335b MT |
290 | "build" : self.handle_build, |
291 | "dist" : self.handle_dist, | |
292 | "update" : self.handle_update, | |
293 | "info" : self.handle_info, | |
294 | "search" : self.handle_search, | |
295 | "shell" : self.handle_shell, | |
4fbd4216 | 296 | "provides" : self.handle_provides, |
b0bcdb49 | 297 | "requires" : self.handle_requires, |
2c84aceb | 298 | "grouplist" : self.handle_grouplist, |
67bc4528 | 299 | "repolist" : self.handle_repolist, |
47a4cb89 MT |
300 | } |
301 | ||
302 | def parse_command_update(self): | |
303 | # Implement the "update" command. | |
304 | sub_update = self.sub_commands.add_parser("update", | |
305 | help=_("Update the package indexes.")) | |
306 | sub_update.add_argument("action", action="store_const", const="update") | |
307 | ||
308 | def parse_command_build(self): | |
309 | # Implement the "build" command. | |
310 | sub_build = self.sub_commands.add_parser("build", | |
311 | help=_("Build one or more packages.")) | |
312 | sub_build.add_argument("package", nargs=1, | |
313 | help=_("Give name of at least one package to build.")) | |
314 | sub_build.add_argument("action", action="store_const", const="build") | |
315 | ||
316 | sub_build.add_argument("-a", "--arch", | |
317 | help=_("Build the package for the given architecture.")) | |
318 | sub_build.add_argument("--resultdir", nargs="?", | |
319 | help=_("Path were the output files should be copied to.")) | |
320 | ||
321 | def parse_command_shell(self): | |
322 | # Implement the "shell" command. | |
323 | sub_shell = self.sub_commands.add_parser("shell", | |
324 | help=_("Go into a shell.")) | |
042266f3 | 325 | sub_shell.add_argument("package", nargs="?", |
47a4cb89 MT |
326 | help=_("Give name of a package.")) |
327 | sub_shell.add_argument("action", action="store_const", const="shell") | |
328 | ||
329 | sub_shell.add_argument("-a", "--arch", | |
330 | help=_("Emulated architecture in the shell.")) | |
331 | ||
332 | def parse_command_dist(self): | |
333 | # Implement the "dist" command. | |
334 | sub_dist = self.sub_commands.add_parser("dist", | |
335 | help=_("Generate a source package.")) | |
e412b8dc MT |
336 | sub_dist.add_argument("package", nargs="+", |
337 | help=_("Give name(s) of a package(s).")) | |
47a4cb89 MT |
338 | sub_dist.add_argument("action", action="store_const", const="dist") |
339 | ||
340 | sub_dist.add_argument("--resultdir", nargs="?", | |
341 | help=_("Path were the output files should be copied to.")) | |
342 | ||
9afa5620 MT |
343 | def handle_info(self): |
344 | Cli.handle_info(self, long=True) | |
345 | ||
47a4cb89 | 346 | def handle_build(self): |
47a4cb89 MT |
347 | # Get the package descriptor from the command line options |
348 | pkg = self.args.package[0] | |
349 | ||
350 | # Check, if we got a regular file | |
351 | if os.path.exists(pkg): | |
352 | pkg = os.path.abspath(pkg) | |
353 | ||
354 | if pkg.endswith(MAKEFILE_EXTENSION): | |
3723913b | 355 | pkg = packages.Makefile(self.pakfire, pkg) |
47a4cb89 MT |
356 | |
357 | elif pkg.endswith(PACKAGE_EXTENSION): | |
3723913b MT |
358 | repo = repository.FileSystemRepository(self.pakfire) |
359 | pkg = packages.SourcePackage(self.pakfire, repo, pkg) | |
47a4cb89 MT |
360 | |
361 | else: | |
362 | # XXX walk through the source tree and find a matching makefile | |
363 | pass | |
364 | ||
0ec833c6 | 365 | self.pakfire.build(pkg, arch=self.args.arch, resultdirs=[self.args.resultdir,]) |
47a4cb89 MT |
366 | |
367 | def handle_shell(self): | |
042266f3 MT |
368 | pkg = None |
369 | ||
47a4cb89 | 370 | # Get the package descriptor from the command line options |
042266f3 | 371 | if self.args.package: |
ad1b844f | 372 | pkg = self.args.package |
47a4cb89 MT |
373 | |
374 | # Check, if we got a regular file | |
042266f3 | 375 | if pkg and os.path.exists(pkg): |
47a4cb89 MT |
376 | pkg = os.path.abspath(pkg) |
377 | ||
378 | if pkg.endswith(MAKEFILE_EXTENSION): | |
3723913b | 379 | pkg = packages.Makefile(self.pakfire, pkg) |
47a4cb89 MT |
380 | |
381 | elif pkg.endswith(PACKAGE_EXTENSION): | |
3723913b MT |
382 | repo = repository.FileSystemRepository(self.pakfire) |
383 | pkg = packages.SourcePackage(self.pakfire, repo, pkg) | |
47a4cb89 MT |
384 | |
385 | else: | |
386 | # XXX walk through the source tree and find a matching makefile | |
387 | pass | |
388 | ||
389 | self.pakfire.shell(pkg, arch=self.args.arch) | |
390 | ||
391 | def handle_dist(self): | |
e412b8dc MT |
392 | # Get the packages from the command line options |
393 | pkgs = [] | |
47a4cb89 | 394 | |
e412b8dc MT |
395 | for pkg in self.args.package: |
396 | # Check, if we got a regular file | |
397 | if os.path.exists(pkg): | |
398 | pkg = os.path.abspath(pkg) | |
47a4cb89 | 399 | |
e412b8dc MT |
400 | if pkg.endswith(MAKEFILE_EXTENSION): |
401 | pkg = packages.Makefile(self.pakfire, pkg) | |
402 | pkgs.append(pkg) | |
47a4cb89 | 403 | |
e412b8dc MT |
404 | else: |
405 | # XXX walk through the source tree and find a matching makefile | |
406 | pass | |
47a4cb89 | 407 | |
e412b8dc | 408 | self.pakfire.dist(pkgs, resultdirs=[self.args.resultdir,]) |
47a4cb89 | 409 | |
9613a111 | 410 | class CliRepo(Cli): |
92806f47 MT |
411 | def __init__(self): |
412 | self.parser = argparse.ArgumentParser( | |
9613a111 | 413 | description = _("Pakfire repo command line interface."), |
92806f47 MT |
414 | ) |
415 | ||
416 | self.parse_common_arguments() | |
417 | ||
418 | # Add sub-commands. | |
419 | self.sub_commands = self.parser.add_subparsers() | |
420 | ||
421 | self.parse_command_repo() | |
422 | ||
423 | # Finally parse all arguments from the command line and save them. | |
424 | self.args = self.parser.parse_args() | |
425 | ||
426 | self.pakfire = Pakfire( | |
427 | builder = True, | |
428 | configs = [self.args.config], | |
429 | disable_repos = self.args.disable_repo, | |
430 | ) | |
431 | ||
432 | self.action2func = { | |
433 | "repo_create" : self.handle_repo_create, | |
434 | } | |
435 | ||
436 | def parse_command_repo(self): | |
437 | sub_repo = self.sub_commands.add_parser("repo", | |
438 | help=_("Repository management commands.")) | |
439 | ||
440 | sub_repo_commands = sub_repo.add_subparsers() | |
441 | ||
442 | self.parse_command_repo_create(sub_repo_commands) | |
443 | ||
444 | def parse_command_repo_create(self, sub_commands): | |
445 | sub_create = sub_commands.add_parser("create", | |
446 | help=_("Create a new repository index.")) | |
447 | sub_create.add_argument("path", nargs=1, help=_("Path to the packages.")) | |
448 | sub_create.add_argument("inputs", nargs="+", help=_("Path to input packages.")) | |
449 | sub_create.add_argument("action", action="store_const", const="repo_create") | |
450 | ||
fa6d335b MT |
451 | def handle_repo_create(self): |
452 | path = self.args.path[0] | |
453 | ||
66af936c | 454 | self.pakfire.repo_create(path, self.args.inputs) |
9613a111 MT |
455 | |
456 | ||
457 | class CliMaster(Cli): | |
677ff42a MT |
458 | def __init__(self): |
459 | self.parser = argparse.ArgumentParser( | |
460 | description = _("Pakfire master command line interface."), | |
461 | ) | |
462 | ||
463 | self.parse_common_arguments() | |
464 | ||
465 | # Add sub-commands. | |
466 | self.sub_commands = self.parser.add_subparsers() | |
467 | ||
468 | self.parse_command_update() | |
469 | ||
470 | # Finally parse all arguments from the command line and save them. | |
471 | self.args = self.parser.parse_args() | |
472 | ||
473 | self.pakfire = Pakfire( | |
474 | builder = True, | |
475 | configs = [self.args.config], | |
476 | disable_repos = self.args.disable_repo, | |
477 | ) | |
478 | ||
479 | self.master = server.master.Master(self.pakfire) | |
480 | ||
481 | self.action2func = { | |
482 | "update" : self.handle_update, | |
483 | } | |
484 | ||
485 | def parse_command_update(self): | |
486 | # Implement the "update" command. | |
487 | sub_update = self.sub_commands.add_parser("update", | |
488 | help=_("Update the sources.")) | |
489 | sub_update.add_argument("action", action="store_const", const="update") | |
490 | ||
491 | def handle_update(self): | |
492 | self.master.update_sources() | |
9613a111 MT |
493 | |
494 | ||
495 | class CliSlave(Cli): | |
677ff42a MT |
496 | def __init__(self): |
497 | self.parser = argparse.ArgumentParser( | |
498 | description = _("Pakfire slave command line interface."), | |
499 | ) | |
500 | ||
501 | self.parse_common_arguments() | |
502 | ||
503 | # Add sub-commands. | |
504 | self.sub_commands = self.parser.add_subparsers() | |
505 | ||
a52f536c | 506 | self.parse_command_build() |
677ff42a MT |
507 | self.parse_command_keepalive() |
508 | ||
509 | # Finally parse all arguments from the command line and save them. | |
510 | self.args = self.parser.parse_args() | |
511 | ||
512 | self.pakfire = Pakfire( | |
513 | builder = True, | |
514 | configs = [self.args.config], | |
515 | disable_repos = self.args.disable_repo, | |
516 | ) | |
517 | ||
518 | self.slave = server.slave.Slave(self.pakfire) | |
519 | ||
520 | self.action2func = { | |
a52f536c | 521 | "build" : self.handle_build, |
677ff42a MT |
522 | "keepalive" : self.handle_keepalive, |
523 | } | |
524 | ||
a52f536c MT |
525 | def parse_command_build(self): |
526 | # Implement the "build" command. | |
527 | sub_keepalive = self.sub_commands.add_parser("build", | |
528 | help=_("Request a build job from the server.")) | |
529 | sub_keepalive.add_argument("action", action="store_const", const="build") | |
530 | ||
677ff42a MT |
531 | def parse_command_keepalive(self): |
532 | # Implement the "keepalive" command. | |
533 | sub_keepalive = self.sub_commands.add_parser("keepalive", | |
534 | help=_("Send a keepalive to the server.")) | |
535 | sub_keepalive.add_argument("action", action="store_const", | |
536 | const="keepalive") | |
537 | ||
538 | def handle_keepalive(self): | |
539 | self.slave.keepalive() | |
9613a111 | 540 | |
a52f536c MT |
541 | def handle_build(self): |
542 | self.slave.build_job() |