ybox 0.9.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ybox/__init__.py +2 -0
- ybox/cmd.py +307 -0
- ybox/conf/completions/ybox.fish +93 -0
- ybox/conf/distros/arch/add-gpg-key.sh +29 -0
- ybox/conf/distros/arch/distro.ini +192 -0
- ybox/conf/distros/arch/init-base.sh +10 -0
- ybox/conf/distros/arch/init-user.sh +35 -0
- ybox/conf/distros/arch/init.sh +82 -0
- ybox/conf/distros/arch/list_fmt_long.py +76 -0
- ybox/conf/distros/arch/pkgdeps.py +276 -0
- ybox/conf/distros/deb-generic/check-package.sh +77 -0
- ybox/conf/distros/deb-generic/distro.ini +190 -0
- ybox/conf/distros/deb-generic/fetch-gpg-key-id.sh +30 -0
- ybox/conf/distros/deb-generic/init-base.sh +11 -0
- ybox/conf/distros/deb-generic/init-user.sh +3 -0
- ybox/conf/distros/deb-generic/init.sh +136 -0
- ybox/conf/distros/deb-generic/list_fmt_long.py +114 -0
- ybox/conf/distros/deb-generic/pkgdeps.py +208 -0
- ybox/conf/distros/deb-oldstable/distro.ini +21 -0
- ybox/conf/distros/deb-stable/distro.ini +21 -0
- ybox/conf/distros/supported.list +5 -0
- ybox/conf/distros/ubuntu2204/distro.ini +21 -0
- ybox/conf/distros/ubuntu2404/distro.ini +21 -0
- ybox/conf/profiles/apps.ini +26 -0
- ybox/conf/profiles/basic.ini +310 -0
- ybox/conf/profiles/dev.ini +25 -0
- ybox/conf/profiles/games.ini +39 -0
- ybox/conf/resources/entrypoint-base.sh +170 -0
- ybox/conf/resources/entrypoint-common.sh +23 -0
- ybox/conf/resources/entrypoint-cp.sh +32 -0
- ybox/conf/resources/entrypoint-root.sh +20 -0
- ybox/conf/resources/entrypoint-user.sh +21 -0
- ybox/conf/resources/entrypoint.sh +249 -0
- ybox/conf/resources/prime-run +13 -0
- ybox/conf/resources/run-in-dir +60 -0
- ybox/conf/resources/run-user-bash-cmd +14 -0
- ybox/config.py +255 -0
- ybox/env.py +205 -0
- ybox/filelock.py +77 -0
- ybox/migrate/0.9.0-0.9.7:0.9.8.py +33 -0
- ybox/pkg/__init__.py +0 -0
- ybox/pkg/clean.py +33 -0
- ybox/pkg/info.py +40 -0
- ybox/pkg/inst.py +638 -0
- ybox/pkg/list.py +191 -0
- ybox/pkg/mark.py +68 -0
- ybox/pkg/repair.py +150 -0
- ybox/pkg/repo.py +251 -0
- ybox/pkg/search.py +52 -0
- ybox/pkg/uninst.py +92 -0
- ybox/pkg/update.py +56 -0
- ybox/print.py +121 -0
- ybox/run/__init__.py +0 -0
- ybox/run/cmd.py +54 -0
- ybox/run/control.py +102 -0
- ybox/run/create.py +1116 -0
- ybox/run/destroy.py +64 -0
- ybox/run/graphics.py +367 -0
- ybox/run/logs.py +57 -0
- ybox/run/ls.py +64 -0
- ybox/run/pkg.py +445 -0
- ybox/schema/0.9.1-added.sql +27 -0
- ybox/schema/0.9.6-added.sql +18 -0
- ybox/schema/init.sql +39 -0
- ybox/schema/migrate/0.9.0:0.9.1.sql +42 -0
- ybox/schema/migrate/0.9.1:0.9.2.sql +8 -0
- ybox/schema/migrate/0.9.2:0.9.3.sql +2 -0
- ybox/schema/migrate/0.9.5:0.9.6.sql +2 -0
- ybox/state.py +914 -0
- ybox/util.py +351 -0
- ybox-0.9.8.dist-info/LICENSE +19 -0
- ybox-0.9.8.dist-info/METADATA +533 -0
- ybox-0.9.8.dist-info/RECORD +76 -0
- ybox-0.9.8.dist-info/WHEEL +5 -0
- ybox-0.9.8.dist-info/entry_points.txt +8 -0
- ybox-0.9.8.dist-info/top_level.txt +1 -0
ybox/run/pkg.py
ADDED
@@ -0,0 +1,445 @@
|
|
1
|
+
"""
|
2
|
+
Code for the `ybox-pkg` script which is a high-level generic package management utility for
|
3
|
+
ybox containers.
|
4
|
+
"""
|
5
|
+
|
6
|
+
import argparse
|
7
|
+
import sys
|
8
|
+
from typing import cast
|
9
|
+
|
10
|
+
from ybox.cmd import YboxLabel, check_active_ybox, run_command
|
11
|
+
from ybox.config import Consts, StaticConfiguration
|
12
|
+
from ybox.env import Environ
|
13
|
+
from ybox.pkg.clean import clean_cache
|
14
|
+
from ybox.pkg.info import info_packages
|
15
|
+
from ybox.pkg.inst import install_package
|
16
|
+
from ybox.pkg.list import list_files, list_packages
|
17
|
+
from ybox.pkg.mark import mark_package
|
18
|
+
from ybox.pkg.repair import repair_package_state
|
19
|
+
from ybox.pkg.repo import repo_add, repo_list, repo_remove
|
20
|
+
from ybox.pkg.search import search_packages
|
21
|
+
from ybox.pkg.uninst import uninstall_package
|
22
|
+
from ybox.pkg.update import update_packages
|
23
|
+
from ybox.print import print_error, print_info
|
24
|
+
from ybox.state import YboxStateManagement
|
25
|
+
from ybox.util import (EnvInterpolation, config_reader, get_ybox_version,
|
26
|
+
select_item_from_menu)
|
27
|
+
|
28
|
+
|
29
|
+
def main() -> None:
|
30
|
+
"""main function for `ybox-pkg` script"""
|
31
|
+
main_argv(sys.argv[1:])
|
32
|
+
|
33
|
+
|
34
|
+
def main_argv(argv: list[str]) -> None:
|
35
|
+
"""
|
36
|
+
Main entrypoint of `ybox-pkg` that takes a list of arguments which are usually the
|
37
|
+
command-line arguments of the `main()` function. Pass ["-h"]/["--help"] to see all the
|
38
|
+
available arguments with help message for each.
|
39
|
+
|
40
|
+
:param argv: arguments to the function (main function passes `sys.argv[1:]`)
|
41
|
+
"""
|
42
|
+
args = parse_args(argv)
|
43
|
+
# --quiet can be specified at most two times
|
44
|
+
if args.quiet > 2:
|
45
|
+
print_error("Argument -q/--quiet can be specified at most two times")
|
46
|
+
sys.exit(1)
|
47
|
+
env = Environ()
|
48
|
+
docker_cmd = env.docker_cmd
|
49
|
+
container_name = args.ybox
|
50
|
+
|
51
|
+
if container_name:
|
52
|
+
check_active_ybox(docker_cmd, container_name, exit_on_error=True)
|
53
|
+
else:
|
54
|
+
# check active containers
|
55
|
+
containers = str(run_command([docker_cmd, "container", "ls", "--format={{ .Names }}",
|
56
|
+
f"--filter=label={YboxLabel.CONTAINER_PRIMARY.value}"],
|
57
|
+
capture_output=True, error_msg="container ls")).splitlines()
|
58
|
+
# use the active container if there is only one of them
|
59
|
+
if len(containers) == 1:
|
60
|
+
container_name = containers[0]
|
61
|
+
elif not containers:
|
62
|
+
print_error("No active ybox container found!")
|
63
|
+
sys.exit(1)
|
64
|
+
elif args.quiet:
|
65
|
+
print_error(
|
66
|
+
f"Expected one active ybox container but found: {', '.join(containers)}")
|
67
|
+
sys.exit(1)
|
68
|
+
else:
|
69
|
+
print_info("Please select the container to use:", file=sys.stderr)
|
70
|
+
if (container_name := select_item_from_menu(containers)) is None:
|
71
|
+
sys.exit(1)
|
72
|
+
|
73
|
+
if not args.quiet:
|
74
|
+
print_info(f"Running the operation on '{container_name}'", file=sys.stderr)
|
75
|
+
|
76
|
+
with YboxStateManagement(env) as state:
|
77
|
+
# ensure that all state database changes are done as a single transaction and only applied
|
78
|
+
# if there were no failures (commit/rollback are automatic at the end of `with`)
|
79
|
+
state.begin_transaction()
|
80
|
+
if (runtime_conf := state.get_container_configuration(container_name)) is None:
|
81
|
+
print_error(f"No entry for ybox container '{container_name}' found!")
|
82
|
+
sys.exit(1)
|
83
|
+
conf = StaticConfiguration(env, runtime_conf.distribution, container_name)
|
84
|
+
distro_conf_file = args.distribution_config or conf.distribution_config(conf.distribution)
|
85
|
+
env_interpolation = EnvInterpolation(env, [])
|
86
|
+
distro_config = config_reader(env.search_config_path(
|
87
|
+
distro_conf_file, only_sys_conf=True), env_interpolation)
|
88
|
+
# if required, migrate the container to work with the latest product
|
89
|
+
state.migrate_container(get_ybox_version(conf), conf, distro_config)
|
90
|
+
# the "repo_cmd" flag set by the subcommands indicate whether the subcommand was
|
91
|
+
# for package management or for repository management
|
92
|
+
pkgmgr = distro_config["pkgmgr"]
|
93
|
+
if args.is_repo_cmd:
|
94
|
+
code = args.func(args, pkgmgr, distro_config["repo"], docker_cmd, conf,
|
95
|
+
runtime_conf, state)
|
96
|
+
else:
|
97
|
+
code = args.func(args, pkgmgr, docker_cmd, conf, runtime_conf, state)
|
98
|
+
if code != 0:
|
99
|
+
sys.exit(code) # state will be automatically rolled back for exceptions
|
100
|
+
|
101
|
+
|
102
|
+
def parse_args(argv: list[str]) -> argparse.Namespace:
|
103
|
+
"""
|
104
|
+
Parse command-line arguments for the program and return the result :class:`argparse.Namespace`.
|
105
|
+
|
106
|
+
:param argv: the list of arguments to be parsed
|
107
|
+
:return: the result of parsing using the `argparse` library as a :class:`argparse.Namespace`
|
108
|
+
"""
|
109
|
+
parser = argparse.ArgumentParser(description="Package management across ybox containers")
|
110
|
+
operations = parser.add_subparsers(title="Operations", required=True, metavar="OPERATION",
|
111
|
+
help="DESCRIPTION")
|
112
|
+
add_install(add_subparser(operations, "install", "install a package with dependencies"))
|
113
|
+
add_uninstall(add_subparser(operations, "uninstall", "uninstall a package and "
|
114
|
+
"optionally its dependencies"))
|
115
|
+
add_update(add_subparser(operations, "update", "update some or all packages"))
|
116
|
+
add_list(add_subparser(operations, "list", "list installed packages"))
|
117
|
+
add_repo_add(add_subparser(operations, "repo-add",
|
118
|
+
"add a new package repository with a given name and server URL(s)"))
|
119
|
+
add_repo_remove(add_subparser(operations, "repo-remove",
|
120
|
+
"remove an existing package repository with the given name"))
|
121
|
+
add_repo_list(add_subparser(operations, "repo-list",
|
122
|
+
"list external repositories registered using 'repo-add'"))
|
123
|
+
add_list_files(add_subparser(operations, "list-files", "list files of an installed package"))
|
124
|
+
add_search(add_subparser(operations, "search",
|
125
|
+
"search repository for packages with matching string"))
|
126
|
+
add_info(add_subparser(operations, "info", "show detailed information about given package(s)"))
|
127
|
+
add_clean(add_subparser(operations, "clean", "clean package cache and intermediate files"))
|
128
|
+
add_mark(add_subparser(operations, "mark",
|
129
|
+
"mark a package as a dependency or an explicitly installed package"))
|
130
|
+
add_repair(add_subparser(operations, "repair",
|
131
|
+
"try to repair state after a failed operation or an interrupt/kill"))
|
132
|
+
return parser.parse_args(argv)
|
133
|
+
|
134
|
+
|
135
|
+
def add_subparser(operations, name: str, hlp: str) -> argparse.ArgumentParser: # type: ignore
|
136
|
+
"""
|
137
|
+
Add a sub-command parser to `ybox-pkg` having a given name and help string.
|
138
|
+
|
139
|
+
:param operations: the sub-parser obtained using :meth:`argparse.ArgumentParser.add_subparsers`
|
140
|
+
:param name: name of the sub-command (e.g. `install` for `ybox-pkg install`)
|
141
|
+
:param hlp: top-level help string for the sub-command
|
142
|
+
:return: the :class:`argparse.ArgumentParser` object for the sub-command
|
143
|
+
"""
|
144
|
+
subparser = cast(argparse.ArgumentParser,
|
145
|
+
operations.add_parser(name, help=hlp)) # type: ignore
|
146
|
+
add_common_args(subparser)
|
147
|
+
# by default set the flag for repository command as false
|
148
|
+
subparser.set_defaults(is_repo_cmd=False)
|
149
|
+
return subparser
|
150
|
+
|
151
|
+
|
152
|
+
def add_common_args(subparser: argparse.ArgumentParser) -> None:
|
153
|
+
"""
|
154
|
+
Add arguments common to all the `ybox-pkg` sub-commands like `-z/--ybox` for the
|
155
|
+
container to use, `-q/--quiet` for quiet operations with minimal user interaction etc.
|
156
|
+
|
157
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
158
|
+
"""
|
159
|
+
subparser.add_argument("-z", "--ybox", type=str,
|
160
|
+
help="the ybox container to use for package operations else the user "
|
161
|
+
"is prompted to select a container from among the active ones")
|
162
|
+
subparser.add_argument("-C", "--distribution-config", type=str,
|
163
|
+
help="path to distribution configuration file to use instead of the "
|
164
|
+
"`distro.ini` from user/system configuration paths")
|
165
|
+
subparser.add_argument("-q", "--quiet", action="count", default=0,
|
166
|
+
help="proceed without asking any questions using defaults where "
|
167
|
+
"possible; this should usually be used with explicit -z/--ybox "
|
168
|
+
"argument for the container else it is assumed that there is only "
|
169
|
+
"one active container which is selected else the operation fails; "
|
170
|
+
"specifying this flag twice will make it real quiet (e.g. install "
|
171
|
+
"will silently override system executables with local ones)")
|
172
|
+
|
173
|
+
|
174
|
+
def add_pager_arg(subparser: argparse.ArgumentParser) -> None:
|
175
|
+
"""
|
176
|
+
Add the `-P/--pager` argument to the sub-command that allows user to change the pager command
|
177
|
+
used to show the output one screenful at a time.
|
178
|
+
|
179
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
180
|
+
"""
|
181
|
+
subparser.add_argument("-P", "--pager", type=str,
|
182
|
+
help="pager to use to show the output one screenful at a time, "
|
183
|
+
"default is YBOX_PAGER environment variable if set else "
|
184
|
+
f"'{Consts.default_pager()}'; empty skips pagination; command is "
|
185
|
+
"split using shell-like syntax e.g. quoted value is one argument")
|
186
|
+
|
187
|
+
|
188
|
+
def add_install(subparser: argparse.ArgumentParser) -> None:
|
189
|
+
"""
|
190
|
+
Add the arguments required for the `ybox-pkg install` sub-command and set the `func`
|
191
|
+
attribute to point to the implementation method for package installation.
|
192
|
+
|
193
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
194
|
+
"""
|
195
|
+
subparser.add_argument("-o", "--skip-opt-deps", action="store_true",
|
196
|
+
help="skip installation of optional dependencies (or recommendations)")
|
197
|
+
subparser.add_argument("-w", "--with-opt-deps", type=str,
|
198
|
+
help="provide comma-separated optional dependencies to install "
|
199
|
+
"(in which case user will not be prompted to select them)")
|
200
|
+
subparser.add_argument("-f", "--app-flags", type=str,
|
201
|
+
help="comma separated key-value pairs for the flags to be used when "
|
202
|
+
"invoking the container executables (e.g. 'chromium=...,...'")
|
203
|
+
subparser.add_argument("-l", "--add-dep-wrappers", action="store_true",
|
204
|
+
help="create local wrapper desktop and executables for the newly "
|
205
|
+
"installed package dependencies too (both required and optional)")
|
206
|
+
subparser.add_argument("-c", "--check-package", action="store_true",
|
207
|
+
help="check for existing package before actual installation")
|
208
|
+
subparser.add_argument("-s", "--skip-executables", action="store_true",
|
209
|
+
help="skip creating wrappers for invoking executables installed by "
|
210
|
+
"the package; default is to create wrapper executables in user's "
|
211
|
+
"$HOME/.local/bin directory and link man pages to "
|
212
|
+
"$HOME/.local/share/man (or using $PYTHONUSERBASE)")
|
213
|
+
subparser.add_argument("-S", "--skip-desktop-files", action="store_true",
|
214
|
+
help="skip creating wrapper desktop files for those installed by the "
|
215
|
+
"package and its optional dependencies; default is to create "
|
216
|
+
"wrapper desktop files in user's $HOME/.local/share/applications "
|
217
|
+
"(or using $PYTHONUSERBASE)")
|
218
|
+
subparser.add_argument("package", type=str, help="the package to install")
|
219
|
+
subparser.set_defaults(func=install_package)
|
220
|
+
|
221
|
+
|
222
|
+
def add_uninstall(subparser: argparse.ArgumentParser) -> None:
|
223
|
+
"""
|
224
|
+
Add the arguments required for the `ybox-pkg uninstall` sub-command and set the `func`
|
225
|
+
attribute to point to the implementation method for package uninstallation.
|
226
|
+
|
227
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
228
|
+
"""
|
229
|
+
subparser.add_argument("-k", "--keep-config-files", action="store_true",
|
230
|
+
help="keep system configuration and/or data files of the package")
|
231
|
+
subparser.add_argument("-s", "--skip-deps", action="store_true",
|
232
|
+
help="skip uninstallation of the orphaned dependencies of the package")
|
233
|
+
subparser.add_argument("package", type=str, help="the package to uninstall")
|
234
|
+
subparser.set_defaults(func=uninstall_package)
|
235
|
+
|
236
|
+
|
237
|
+
def add_update(subparser: argparse.ArgumentParser) -> None:
|
238
|
+
"""
|
239
|
+
Add the arguments required for the `ybox-pkg update` sub-command and set the `func`
|
240
|
+
attribute to point to the implementation method for updating one or more packages.
|
241
|
+
|
242
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
243
|
+
"""
|
244
|
+
subparser.add_argument("packages", nargs="*",
|
245
|
+
help="the packages to update if provided, else update the entire "
|
246
|
+
"installation of the container (which will end up updating all "
|
247
|
+
"other containers sharing the same root if configured)")
|
248
|
+
subparser.set_defaults(func=update_packages)
|
249
|
+
|
250
|
+
|
251
|
+
def add_list(subparser: argparse.ArgumentParser) -> None:
|
252
|
+
"""
|
253
|
+
Add the arguments required for the `ybox-pkg list` sub-command and set the `func`
|
254
|
+
attribute to point to the implementation method for listing installed packages.
|
255
|
+
|
256
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
257
|
+
"""
|
258
|
+
subparser.add_argument("-a", "--all", action="store_true",
|
259
|
+
help="show all packages including dependent packages in the output "
|
260
|
+
"otherwise only the packages that have been explicitly installed "
|
261
|
+
"are shown")
|
262
|
+
subparser.add_argument("-o", "--os-pkgs", action="store_true",
|
263
|
+
help="list all packages installed in the container including those "
|
264
|
+
"not managed by 'ybox-pkg'; when multiple containers share the "
|
265
|
+
"same root directory, then it will include packages installed "
|
266
|
+
"on other containers; this can be combined with -a/--all "
|
267
|
+
"option to list all the packages including dependents")
|
268
|
+
subparser.add_argument("-p", "--plain-separator", type=str,
|
269
|
+
help="show the output in 'plain' format rather than as a table with "
|
270
|
+
"the fields separated by the given string; ; disables default "
|
271
|
+
"pager so use explicit -P/--pager for pagination; it will also "
|
272
|
+
"skip any truncation of the 'Dependency Of' column; DO NOT USE "
|
273
|
+
"a single comma or similar as separator as they can be in output "
|
274
|
+
"fields and will break parsing of the output")
|
275
|
+
subparser.add_argument("-v", "--verbose", action="store_true",
|
276
|
+
help="show some package details including version, description and "
|
277
|
+
"whether it is a dependency or a top-level package")
|
278
|
+
subparser.add_argument("-N", "--no-trunc", action="store_true",
|
279
|
+
help="do not truncate the 'Dependency Of' column values when using "
|
280
|
+
"the -v/--verbose option")
|
281
|
+
add_pager_arg(subparser)
|
282
|
+
subparser.set_defaults(func=list_packages)
|
283
|
+
|
284
|
+
|
285
|
+
def add_list_files(subparser: argparse.ArgumentParser) -> None:
|
286
|
+
"""
|
287
|
+
Add the arguments required for the `ybox-pkg list-files` sub-command and set the `func`
|
288
|
+
attribute to point to the implementation method for listing files of an installed package.
|
289
|
+
|
290
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
291
|
+
"""
|
292
|
+
add_pager_arg(subparser)
|
293
|
+
subparser.add_argument("package", type=str, help="list files of this package")
|
294
|
+
subparser.set_defaults(func=list_files)
|
295
|
+
|
296
|
+
|
297
|
+
def add_search(subparser: argparse.ArgumentParser) -> None:
|
298
|
+
"""
|
299
|
+
Add the arguments required for the `ybox-pkg search` sub-command and set the `func`
|
300
|
+
attribute to point to the implementation method for searching among all available packages.
|
301
|
+
|
302
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
303
|
+
"""
|
304
|
+
subparser.add_argument("-w", "--word", action="store_true",
|
305
|
+
help="match given search terms as full words")
|
306
|
+
subparser.add_argument("-a", "--all", action="store_true",
|
307
|
+
help="search in package descriptions in addition to the package names")
|
308
|
+
subparser.add_argument("-o", "--official", action="store_true",
|
309
|
+
help="search only in the official repositories and not the extra ones "
|
310
|
+
"(e.g. skip AUR repository on Arch Linux)")
|
311
|
+
add_pager_arg(subparser)
|
312
|
+
subparser.add_argument("search", nargs="+", help="one or more search terms")
|
313
|
+
subparser.set_defaults(func=search_packages)
|
314
|
+
|
315
|
+
|
316
|
+
def add_info(subparser: argparse.ArgumentParser) -> None:
|
317
|
+
"""
|
318
|
+
Add the arguments required for the `ybox-pkg info` sub-command and set the `func`
|
319
|
+
attribute to point to the implementation method for displaying detailed information of one
|
320
|
+
or more packages.
|
321
|
+
|
322
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
323
|
+
"""
|
324
|
+
subparser.add_argument("-a", "--all", action="store_true",
|
325
|
+
help="search for package information in the repositories, "
|
326
|
+
"otherwise search only among the installed packages")
|
327
|
+
add_pager_arg(subparser)
|
328
|
+
subparser.add_argument("packages", nargs="+", help="one or more packages")
|
329
|
+
subparser.set_defaults(func=info_packages)
|
330
|
+
|
331
|
+
|
332
|
+
def add_clean(subparser: argparse.ArgumentParser) -> None:
|
333
|
+
"""
|
334
|
+
Add the arguments required for the `ybox-pkg clean` sub-command and set the `func`
|
335
|
+
attribute to point to the implementation method for cleaning package cache and related
|
336
|
+
intermediate files.
|
337
|
+
|
338
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
339
|
+
"""
|
340
|
+
subparser.set_defaults(func=clean_cache)
|
341
|
+
|
342
|
+
|
343
|
+
def add_mark(subparser: argparse.ArgumentParser) -> None:
|
344
|
+
"""
|
345
|
+
Add the arguments required for the `ybox-pkg mark` sub-command and set the `func`
|
346
|
+
attribute to point to the implementation method for marking package as explicitly installed
|
347
|
+
or as a dependency of another package.
|
348
|
+
|
349
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
350
|
+
"""
|
351
|
+
subparser.add_argument("-e", "--explicit", action="store_true",
|
352
|
+
help="mark the package as explicitly installed; the package will "
|
353
|
+
"henceforth be managed by `ybox-pkg` if not already; "
|
354
|
+
"exactly one of -e or -D option must be specified")
|
355
|
+
subparser.add_argument("-D", "--dependency-of", type=str,
|
356
|
+
help="mark the package as a dependency of given package; both the "
|
357
|
+
"packages will henceforth be managed by `ybox-pkg` if not "
|
358
|
+
"already; exactly one of -e or -D option must be specified")
|
359
|
+
subparser.add_argument("package", type=str, help="the package to be marked")
|
360
|
+
subparser.set_defaults(func=mark_package)
|
361
|
+
|
362
|
+
|
363
|
+
def add_repair(subparser: argparse.ArgumentParser) -> None:
|
364
|
+
"""
|
365
|
+
Add the arguments required for the `ybox-pkg repair` sub-command and set the `func`
|
366
|
+
attribute to point to the implementation method for repairing system state after a failed
|
367
|
+
installation/operation or an interrupt/kill during package operations.
|
368
|
+
|
369
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
370
|
+
"""
|
371
|
+
subparser.add_argument("--extensive", action="store_true",
|
372
|
+
help="repair thoroughly by reinstalling all packages; CAUTION: use "
|
373
|
+
"this only if the normal repair fails and the system cannot be "
|
374
|
+
"recovered otherwise")
|
375
|
+
subparser.set_defaults(func=repair_package_state)
|
376
|
+
|
377
|
+
|
378
|
+
def add_repo_add(subparser: argparse.ArgumentParser) -> None:
|
379
|
+
"""
|
380
|
+
Add the arguments required for the `ybox-pkg repo-add` sub-command and set the `func`
|
381
|
+
attribute to point to the implementation method for adding a new external package repository.
|
382
|
+
|
383
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
384
|
+
"""
|
385
|
+
subparser.add_argument("-k", "--key", type=str,
|
386
|
+
help="key to be registered for verification of the packages (usually "
|
387
|
+
"a GPG/PGP signing key); this can be a URL to the key file or a "
|
388
|
+
"key ID that can be retrieved from default key server as "
|
389
|
+
"configured in the distribution's configuration file or the one "
|
390
|
+
"provided by the -s/--key-server option")
|
391
|
+
subparser.add_argument("-s", "--key-server", type=str,
|
392
|
+
help="URL of the key server to be used for retrieving a key by ID "
|
393
|
+
"which will override the default key server configured in the "
|
394
|
+
"distribution's configuration file")
|
395
|
+
subparser.add_argument("-o", "--options", type=str,
|
396
|
+
help="additional options that may be required for the repository "
|
397
|
+
"specification; for example debian/ubuntu need '<distribution> "
|
398
|
+
"<component...>' in its source specification so that need to be "
|
399
|
+
"provided using '--options=stable main' (as an example)")
|
400
|
+
subparser.add_argument("-S", "--add-source-repo", action="store_true",
|
401
|
+
help="for distributions like debian/ubuntu, this specifies that the "
|
402
|
+
"repository for package sources (deb-src) should also be added "
|
403
|
+
"using the same specification as the package repository")
|
404
|
+
subparser.add_argument("name", type=str,
|
405
|
+
help="unique name for the package repository to be added")
|
406
|
+
subparser.add_argument("urls", nargs="+",
|
407
|
+
help="one or more server URLs of the package repository; "
|
408
|
+
"note that the current distribution may only support a single URL "
|
409
|
+
"(e.g. Ubuntu/Debian), so providing multiple URLs can fail")
|
410
|
+
subparser.set_defaults(is_repo_cmd=True)
|
411
|
+
subparser.set_defaults(func=repo_add)
|
412
|
+
|
413
|
+
|
414
|
+
def add_repo_remove(subparser: argparse.ArgumentParser) -> None:
|
415
|
+
"""
|
416
|
+
Add the arguments required for the `ybox-pkg repo-remove` sub-command and set the `func`
|
417
|
+
attribute to point to the implementation method for removing an external package repository.
|
418
|
+
|
419
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
420
|
+
"""
|
421
|
+
subparser.add_argument("-f", "--force", action="store_true",
|
422
|
+
help="force remove repository registeration even on failure of "
|
423
|
+
"removal of key and/or repository details")
|
424
|
+
subparser.add_argument("name", type=str, help="name of the package repository to be removed")
|
425
|
+
subparser.set_defaults(is_repo_cmd=True)
|
426
|
+
subparser.set_defaults(func=repo_remove)
|
427
|
+
|
428
|
+
|
429
|
+
def add_repo_list(subparser: argparse.ArgumentParser) -> None:
|
430
|
+
"""
|
431
|
+
Add the arguments required for the `ybox-pkg repo-list` sub-command and set the `func`
|
432
|
+
attribute to point to the implementation method for listing information of registered external
|
433
|
+
package repositories.
|
434
|
+
|
435
|
+
:param subparser: the :class:`argparse.ArgumentParser` object for the sub-command
|
436
|
+
"""
|
437
|
+
subparser.add_argument("-p", "--plain-separator", type=str,
|
438
|
+
help="show the output in 'plain' format rather than as a table with "
|
439
|
+
"the fields separated by the given string; disables default "
|
440
|
+
"pager so use explicit -P/--pager for pagination")
|
441
|
+
subparser.add_argument("-v", "--verbose", action="store_true",
|
442
|
+
help="show more details of the repositories")
|
443
|
+
add_pager_arg(subparser)
|
444
|
+
subparser.set_defaults(is_repo_cmd=True)
|
445
|
+
subparser.set_defaults(func=repo_list)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
-- records the version of the whole schema
|
2
|
+
CREATE TABLE schema (
|
3
|
+
version TEXT NOT NULL PRIMARY KEY
|
4
|
+
) WITHOUT ROWID;
|
5
|
+
|
6
|
+
-- index on the shared_root column used in lookups
|
7
|
+
CREATE INDEX container_roots ON containers(shared_root);
|
8
|
+
|
9
|
+
-- dependencies of packages are also recorded separately to keep a proper
|
10
|
+
-- reference count and remove dependencies only if no package depends on it
|
11
|
+
CREATE TABLE package_deps (
|
12
|
+
-- name of the package
|
13
|
+
name TEXT NOT NULL,
|
14
|
+
-- name of the container
|
15
|
+
container TEXT NOT NULL,
|
16
|
+
-- name of the dependency
|
17
|
+
dependency TEXT NOT NULL,
|
18
|
+
-- type of the dependency, one of "required", "optional" or "suggestion"
|
19
|
+
-- (note that "required" dependencies are handled by underlying package manager
|
20
|
+
-- and usually will not be recorded here)
|
21
|
+
dep_type TEXT NOT NULL,
|
22
|
+
PRIMARY KEY (name, container, dependency)
|
23
|
+
) WITHOUT ROWID;
|
24
|
+
|
25
|
+
-- index on package_deps for faster lookups and deletes
|
26
|
+
CREATE INDEX pkg_deps_containers ON package_deps(container);
|
27
|
+
CREATE INDEX pkg_deps_deps ON package_deps(dependency);
|
@@ -0,0 +1,18 @@
|
|
1
|
+
-- additional package repositories that have been added are tracked display them
|
2
|
+
-- and to enable removing the signing key if required
|
3
|
+
CREATE TABLE package_repos (
|
4
|
+
-- name of the repository
|
5
|
+
name TEXT NOT NULL,
|
6
|
+
-- name of the container, or shared root directory (if the container is using a shared root)
|
7
|
+
-- where the repository is being added
|
8
|
+
container_or_shared_root TEXT NOT NULL,
|
9
|
+
-- server URL(s) that are comma separated if multiple of them
|
10
|
+
urls TEXT NOT NULL,
|
11
|
+
-- key used for verifying the packages by the package manager
|
12
|
+
key TEXT NOT NULL,
|
13
|
+
-- additional options for the repository
|
14
|
+
options TEXT NOT NULL,
|
15
|
+
-- if source code repository has also been enabled
|
16
|
+
with_source_repo BOOL NOT NULL,
|
17
|
+
PRIMARY KEY (name, container_or_shared_root)
|
18
|
+
) WITHOUT ROWID;
|
ybox/schema/init.sql
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
-- all ybox containers
|
2
|
+
CREATE TABLE containers (
|
3
|
+
-- name of the container
|
4
|
+
name TEXT NOT NULL PRIMARY KEY,
|
5
|
+
-- code name for the linux distribution of the container
|
6
|
+
distribution TEXT NOT NULL,
|
7
|
+
-- shared root directory or empty string if not using shared root
|
8
|
+
shared_root TEXT NOT NULL,
|
9
|
+
-- configuration of container in INI format string
|
10
|
+
configuration TEXT NOT NULL,
|
11
|
+
-- if the container has been destroyed but still has packages installed in shared root
|
12
|
+
-- then it is retained with a new unique name denoting a destroyed container
|
13
|
+
destroyed BOOL NOT NULL
|
14
|
+
) WITHOUT ROWID;
|
15
|
+
|
16
|
+
-- all packages installed in ybox containers using ybox-pkg including dependencies
|
17
|
+
CREATE TABLE packages (
|
18
|
+
-- name of the package
|
19
|
+
name TEXT NOT NULL,
|
20
|
+
-- name of the container that owns this package
|
21
|
+
container TEXT NOT NULL,
|
22
|
+
-- local wrappers desktop/executables created for the package (array as json)
|
23
|
+
local_copies TEXT NOT NULL,
|
24
|
+
-- type of local wrappers created which is a bit mask:
|
25
|
+
-- 0 for none, 1 for .desktop files, 2 for executables, 3 for both
|
26
|
+
local_copy_type INT NOT NULL,
|
27
|
+
-- set of flags to append to the executables when invoking from local_copies (dict as json)
|
28
|
+
flags TEXT NOT NULL,
|
29
|
+
PRIMARY KEY(name, container)
|
30
|
+
) WITHOUT ROWID;
|
31
|
+
|
32
|
+
-- index on the containers column used in joins and lookups
|
33
|
+
CREATE INDEX package_containers ON packages(container);
|
34
|
+
|
35
|
+
-- include the new tables and indexes added in version 0.9.1
|
36
|
+
SOURCE '0.9.1-added.sql';
|
37
|
+
|
38
|
+
-- include the new 'package_repos' table added in version 0.9.6
|
39
|
+
SOURCE '0.9.6-added.sql';
|
@@ -0,0 +1,42 @@
|
|
1
|
+
-- first create the new tables and index
|
2
|
+
|
3
|
+
SOURCE '../0.9.1-added.sql';
|
4
|
+
|
5
|
+
-- add the destroyed_containers table
|
6
|
+
CREATE TABLE destroyed_containers (
|
7
|
+
name TEXT NOT NULL PRIMARY KEY,
|
8
|
+
distribution TEXT NOT NULL,
|
9
|
+
shared_root TEXT NOT NULL,
|
10
|
+
configuration TEXT NOT NULL
|
11
|
+
) WITHOUT ROWID;
|
12
|
+
|
13
|
+
-- delete the orphan packages having empty container fields since it is not possible to create
|
14
|
+
-- corresponding entries in destroyed_containers due to lack of container configuration information
|
15
|
+
DELETE FROM packages WHERE container = '';
|
16
|
+
|
17
|
+
-- change comma-separated local_copies field to json
|
18
|
+
UPDATE packages SET local_copies = JSON_FROM_CSV(local_copies);
|
19
|
+
|
20
|
+
-- make entries into package_deps reading from packages.type
|
21
|
+
INSERT INTO package_deps
|
22
|
+
SELECT RTRIM(SUBSTR(type, 10), ')'), container, name, 'optional'
|
23
|
+
FROM packages
|
24
|
+
WHERE type LIKE 'optional(%)';
|
25
|
+
|
26
|
+
-- drop the packages.shared_root and packages.type columns
|
27
|
+
ALTER TABLE packages DROP COLUMN type;
|
28
|
+
ALTER TABLE packages DROP COLUMN shared_root;
|
29
|
+
|
30
|
+
-- add the local_copy_type column and fill it up guessing from local_copies
|
31
|
+
ALTER TABLE packages ADD COLUMN local_copy_type INT NOT NULL DEFAULT 0;
|
32
|
+
UPDATE packages SET local_copy_type = (
|
33
|
+
CASE WHEN local_copies LIKE '%.desktop%,%bin/%' THEN 3
|
34
|
+
WHEN local_copies LIKE '%bin/%,%.desktop%' THEN 3
|
35
|
+
WHEN local_copies LIKE '%.desktop%' THEN 1
|
36
|
+
WHEN local_copies LIKE '%bin/%' THEN 2
|
37
|
+
ELSE 0
|
38
|
+
END
|
39
|
+
);
|
40
|
+
|
41
|
+
-- add version entry, since code assumes that a valid entry will be present in the schema table
|
42
|
+
INSERT INTO schema VALUES ('0.9.1');
|
@@ -0,0 +1,8 @@
|
|
1
|
+
-- add the destroyed column to containers
|
2
|
+
ALTER TABLE containers ADD COLUMN destroyed BOOL NOT NULL DEFAULT false;
|
3
|
+
|
4
|
+
-- move the entries from "destroyed_containers" to containers with destroyed column as true
|
5
|
+
INSERT OR IGNORE INTO containers SELECT name, distribution, shared_root, configuration, true
|
6
|
+
FROM destroyed_containers;
|
7
|
+
|
8
|
+
DROP TABLE destroyed_containers;
|