ybox 0.9.9__tar.gz → 0.9.10__tar.gz

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.
Files changed (115) hide show
  1. {ybox-0.9.9/src/ybox.egg-info → ybox-0.9.10}/PKG-INFO +35 -12
  2. {ybox-0.9.9 → ybox-0.9.10}/README.md +33 -11
  3. {ybox-0.9.9 → ybox-0.9.10}/pyproject.toml +1 -0
  4. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/__init__.py +1 -1
  5. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/cmd.py +17 -1
  6. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/completions/ybox.fish +2 -0
  7. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/arch/init-user.sh +2 -2
  8. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/arch/init.sh +1 -0
  9. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/arch/pkgdeps.py +2 -0
  10. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/deb-generic/pkgdeps.py +2 -1
  11. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/profiles/basic.ini +29 -16
  12. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/profiles/dev.ini +0 -6
  13. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/resources/entrypoint-root.sh +1 -0
  14. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/resources/entrypoint-user.sh +5 -3
  15. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/resources/entrypoint.sh +22 -13
  16. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/resources/prime-run +0 -2
  17. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/resources/run-in-dir +4 -0
  18. ybox-0.9.10/src/ybox/conf/resources/run-user-bash-cmd +30 -0
  19. ybox-0.9.10/src/ybox/conf/resources/ybox-systemd.template +22 -0
  20. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/config.py +9 -1
  21. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/pkg/clean.py +1 -7
  22. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/pkg/info.py +1 -7
  23. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/pkg/inst.py +20 -14
  24. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/pkg/list.py +1 -6
  25. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/pkg/repair.py +4 -0
  26. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/pkg/search.py +1 -7
  27. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/run/cmd.py +2 -1
  28. ybox-0.9.10/src/ybox/run/control.py +169 -0
  29. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/run/create.py +186 -48
  30. ybox-0.9.10/src/ybox/run/destroy.py +127 -0
  31. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/run/logs.py +2 -1
  32. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/run/ls.py +2 -1
  33. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/run/pkg.py +46 -4
  34. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/state.py +22 -3
  35. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/util.py +5 -5
  36. {ybox-0.9.9 → ybox-0.9.10/src/ybox.egg-info}/PKG-INFO +35 -12
  37. {ybox-0.9.9 → ybox-0.9.10}/src/ybox.egg-info/SOURCES.txt +2 -0
  38. {ybox-0.9.9 → ybox-0.9.10}/tests/create_migration_db.py +1 -0
  39. {ybox-0.9.9 → ybox-0.9.10}/tests/functional/distro_base.py +4 -4
  40. {ybox-0.9.9 → ybox-0.9.10}/tests/functional/test_create_destroy.py +1 -3
  41. ybox-0.9.10/tests/resources/migration/0.9.0.db.gz +0 -0
  42. ybox-0.9.10/tests/resources/migration/0.9.1.db.gz +0 -0
  43. ybox-0.9.10/tests/resources/migration/0.9.2.db.gz +0 -0
  44. ybox-0.9.10/tests/resources/migration/0.9.5.db.gz +0 -0
  45. ybox-0.9.10/tests/resources/migration/0.9.6.db.gz +0 -0
  46. ybox-0.9.10/tests/resources/migration/0.9.7.db.gz +0 -0
  47. ybox-0.9.10/tests/resources/migration/0.9.8.db.gz +0 -0
  48. {ybox-0.9.9 → ybox-0.9.10}/tests/unit/test_cmd.py +48 -1
  49. {ybox-0.9.9 → ybox-0.9.10}/tests/unit/test_config.py +2 -1
  50. {ybox-0.9.9 → ybox-0.9.10}/tests/unit/test_env.py +5 -1
  51. {ybox-0.9.9 → ybox-0.9.10}/tests/unit/test_state.py +2 -1
  52. ybox-0.9.9/src/ybox/conf/resources/run-user-bash-cmd +0 -14
  53. ybox-0.9.9/src/ybox/run/control.py +0 -102
  54. ybox-0.9.9/src/ybox/run/destroy.py +0 -64
  55. ybox-0.9.9/tests/resources/migration/0.9.0.db.gz +0 -0
  56. ybox-0.9.9/tests/resources/migration/0.9.1.db.gz +0 -0
  57. ybox-0.9.9/tests/resources/migration/0.9.2.db.gz +0 -0
  58. ybox-0.9.9/tests/resources/migration/0.9.5.db.gz +0 -0
  59. ybox-0.9.9/tests/resources/migration/0.9.6.db.gz +0 -0
  60. ybox-0.9.9/tests/resources/migration/0.9.7.db.gz +0 -0
  61. {ybox-0.9.9 → ybox-0.9.10}/LICENSE +0 -0
  62. {ybox-0.9.9 → ybox-0.9.10}/MANIFEST.in +0 -0
  63. {ybox-0.9.9 → ybox-0.9.10}/setup.cfg +0 -0
  64. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/arch/add-gpg-key.sh +0 -0
  65. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/arch/distro.ini +0 -0
  66. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/arch/init-base.sh +0 -0
  67. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/arch/list_fmt_long.py +0 -0
  68. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/deb-generic/check-package.sh +0 -0
  69. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/deb-generic/distro.ini +0 -0
  70. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/deb-generic/fetch-gpg-key-id.sh +0 -0
  71. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/deb-generic/init-base.sh +0 -0
  72. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/deb-generic/init-user.sh +0 -0
  73. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/deb-generic/init.sh +0 -0
  74. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/deb-generic/list_fmt_long.py +0 -0
  75. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/deb-oldstable/distro.ini +0 -0
  76. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/deb-stable/distro.ini +0 -0
  77. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/supported.list +0 -0
  78. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/ubuntu2204/distro.ini +0 -0
  79. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/distros/ubuntu2404/distro.ini +0 -0
  80. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/profiles/apps.ini +0 -0
  81. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/profiles/games.ini +0 -0
  82. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/resources/entrypoint-base.sh +0 -0
  83. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/resources/entrypoint-common.sh +0 -0
  84. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/conf/resources/entrypoint-cp.sh +0 -0
  85. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/env.py +0 -0
  86. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/filelock.py +0 -0
  87. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/migrate/0.9.0-0.9.7:0.9.8.py +0 -0
  88. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/pkg/__init__.py +0 -0
  89. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/pkg/mark.py +0 -0
  90. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/pkg/repo.py +0 -0
  91. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/pkg/uninst.py +0 -0
  92. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/pkg/update.py +0 -0
  93. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/print.py +0 -0
  94. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/run/__init__.py +0 -0
  95. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/run/graphics.py +0 -0
  96. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/schema/0.9.1-added.sql +0 -0
  97. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/schema/0.9.6-added.sql +0 -0
  98. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/schema/init.sql +0 -0
  99. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/schema/migrate/0.9.0:0.9.1.sql +0 -0
  100. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/schema/migrate/0.9.1:0.9.2.sql +0 -0
  101. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/schema/migrate/0.9.2:0.9.3.sql +0 -0
  102. {ybox-0.9.9 → ybox-0.9.10}/src/ybox/schema/migrate/0.9.5:0.9.6.sql +0 -0
  103. {ybox-0.9.9 → ybox-0.9.10}/src/ybox.egg-info/dependency_links.txt +0 -0
  104. {ybox-0.9.9 → ybox-0.9.10}/src/ybox.egg-info/entry_points.txt +0 -0
  105. {ybox-0.9.9 → ybox-0.9.10}/src/ybox.egg-info/requires.txt +0 -0
  106. {ybox-0.9.9 → ybox-0.9.10}/src/ybox.egg-info/top_level.txt +0 -0
  107. {ybox-0.9.9 → ybox-0.9.10}/tests/functional/__init__.py +0 -0
  108. {ybox-0.9.9 → ybox-0.9.10}/tests/resources/basic_no_shared.ini +0 -0
  109. {ybox-0.9.9 → ybox-0.9.10}/tests/resources/containers.json +0 -0
  110. {ybox-0.9.9 → ybox-0.9.10}/tests/resources/distro_minimal.ini +0 -0
  111. {ybox-0.9.9 → ybox-0.9.10}/tests/resources/packages.json +0 -0
  112. {ybox-0.9.9 → ybox-0.9.10}/tests/resources/repos.json +0 -0
  113. {ybox-0.9.9 → ybox-0.9.10}/tests/unit/__init__.py +0 -0
  114. {ybox-0.9.9 → ybox-0.9.10}/tests/unit/test_filelock.py +0 -0
  115. {ybox-0.9.9 → ybox-0.9.10}/tests/unit/util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ybox
3
- Version: 0.9.9
3
+ Version: 0.9.10
4
4
  Summary: Securely run Linux distribution inside a container
5
5
  Author-email: Sumedh Wale <sumwale@yahoo.com>, Vishal Rao <vishalrao@gmail.com>
6
6
  License: Copyright (c) 2024-2025 Sumedh Wale and contributors
@@ -35,6 +35,7 @@ Classifier: Programming Language :: Python :: 3.9
35
35
  Classifier: Programming Language :: Python :: 3.10
36
36
  Classifier: Programming Language :: Python :: 3.11
37
37
  Classifier: Programming Language :: Python :: 3.12
38
+ Classifier: Programming Language :: Python :: 3.13
38
39
  Requires-Python: >=3.9
39
40
  Description-Content-Type: text/markdown
40
41
  License-File: LICENSE
@@ -54,7 +55,17 @@ of the container including directories to be shared, logging etc.
54
55
 
55
56
  Special emphasis is given on security where users can choose to lock down
56
57
  or open up the container as required with reasonable defaults out of the
57
- box. There is no sharing of HOME or no privileged mode container.
58
+ box. There is no sharing of HOME or no privileged mode container. This sets
59
+ it apart from other similar solutions like distrobox/toolbx and the reason
60
+ for starting this project since those other solutions don't care about
61
+ security/sandboxing at all and share the entire HOME while running the
62
+ containers in privileged mode. The other problem with those solutions is that
63
+ the shared HOME means that the user's configuration dot files also get shared
64
+ and can cause all kinds of trouble where container apps can overwrite
65
+ with their own versions (especially for updated apps in the containers)
66
+ breaking the app in the host system. It is, however, possible to share the
67
+ entire HOME if user really wants but that needs to be explcitly configured
68
+ in the ini profile.
58
69
 
59
70
  Expected usage is for users to group similar applications in a container
60
71
  and separate out containers depending on different needs like higher/lower
@@ -144,10 +155,11 @@ require you to install in a custom virtual environment which can be done manuall
144
155
  fish: `python3 -m venv ybox-venv && source ybox-env/bin/activate.fish`)
145
156
  or automatically using `pipx`. Alternatively you can add `--break-system-packages`
146
157
  flag to the `pip` command above or add it globally for all future packages using
147
- `python3 -m pip config set global.break-system-packages true`. The alternative
148
- approach works well for `ybox` which has a very minimal set of dependencies but
149
- in the rare case you see any issues due to package conflicts, use `pipx` or
150
- manual virtual environment.
158
+ `python3 -m pip config set global.break-system-packages true`. This alternative
159
+ approach works well for `ybox` which has a very minimal set of dependencies which will
160
+ not conflict with system packages (rather work with whatever system version is installed),
161
+ but if you prefer keeping the installation separate then use `pipx` or
162
+ a manual virtual environment.
151
163
 
152
164
  Now you can run the `ybox-create` and other utilities that are normally installed
153
165
  in your `~/.local/bin` directory which should be in PATH for modern Linux distributions.
@@ -209,7 +221,9 @@ does not run properly as root, then you cannot run it when using docker unless y
209
221
  `sudo/su` to the host user in the container command. However, running as host user when running
210
222
  rootless docker will map to a different user ID in the host (as specified in `/etc/subuid` on the
211
223
  host) so files shared with the host, including devices like those in `/dev/dri`, will cause
212
- permission issues that can hinder or break the application.
224
+ permission issues that can hinder or break the application. Hence it is recommended to
225
+ just install podman (even if you already have docker installed) which works out of the
226
+ box in rootless mode in all tested distributions.
213
227
 
214
228
 
215
229
  ### Package management: install/uninstall/list/search/...
@@ -448,8 +462,8 @@ systemctl --user enable container-ybox-arch_apps.service
448
462
 
449
463
  Virtual environment setup have been provided for consistent development, test and build
450
464
  with multiple python versions. The minimum python version required is 3.9 and tests are
451
- run against all major python versions higher than that (i.e. 3.10, 3.11, 3.12 and others
452
- in future).
465
+ run against all major python versions higher than that (i.e. 3.10, 3.11, 3.12, 3.13 and
466
+ others in future).
453
467
 
454
468
  The setup uses pyenv with venv which can be used for development with IDEA/PyCharm/VSCode
455
469
  or in terminal, running tests against all supported python versions using `tox` etc.
@@ -476,14 +490,23 @@ Next you can install the required python versions and venv environment:
476
490
  pyenv/setup-venv.sh
477
491
  ```
478
492
 
479
- Finally, you can activate it in bash/zsh:
493
+ Finally, you can activate it.
494
+
495
+ bash:
496
+
497
+ ```sh
498
+ source pyenv/activate.bash
499
+ source .venv/bin/activate
500
+ ```
501
+
502
+ zsh:
480
503
 
481
504
  ```sh
482
- source pyenv/activate.sh
505
+ source pyenv/activate.zsh
483
506
  source .venv/bin/activate
484
507
  ```
485
508
 
486
- Or in fish shell:
509
+ fish:
487
510
 
488
511
  ```
489
512
  source pyenv/activate.fish
@@ -10,7 +10,17 @@ of the container including directories to be shared, logging etc.
10
10
 
11
11
  Special emphasis is given on security where users can choose to lock down
12
12
  or open up the container as required with reasonable defaults out of the
13
- box. There is no sharing of HOME or no privileged mode container.
13
+ box. There is no sharing of HOME or no privileged mode container. This sets
14
+ it apart from other similar solutions like distrobox/toolbx and the reason
15
+ for starting this project since those other solutions don't care about
16
+ security/sandboxing at all and share the entire HOME while running the
17
+ containers in privileged mode. The other problem with those solutions is that
18
+ the shared HOME means that the user's configuration dot files also get shared
19
+ and can cause all kinds of trouble where container apps can overwrite
20
+ with their own versions (especially for updated apps in the containers)
21
+ breaking the app in the host system. It is, however, possible to share the
22
+ entire HOME if user really wants but that needs to be explcitly configured
23
+ in the ini profile.
14
24
 
15
25
  Expected usage is for users to group similar applications in a container
16
26
  and separate out containers depending on different needs like higher/lower
@@ -100,10 +110,11 @@ require you to install in a custom virtual environment which can be done manuall
100
110
  fish: `python3 -m venv ybox-venv && source ybox-env/bin/activate.fish`)
101
111
  or automatically using `pipx`. Alternatively you can add `--break-system-packages`
102
112
  flag to the `pip` command above or add it globally for all future packages using
103
- `python3 -m pip config set global.break-system-packages true`. The alternative
104
- approach works well for `ybox` which has a very minimal set of dependencies but
105
- in the rare case you see any issues due to package conflicts, use `pipx` or
106
- manual virtual environment.
113
+ `python3 -m pip config set global.break-system-packages true`. This alternative
114
+ approach works well for `ybox` which has a very minimal set of dependencies which will
115
+ not conflict with system packages (rather work with whatever system version is installed),
116
+ but if you prefer keeping the installation separate then use `pipx` or
117
+ a manual virtual environment.
107
118
 
108
119
  Now you can run the `ybox-create` and other utilities that are normally installed
109
120
  in your `~/.local/bin` directory which should be in PATH for modern Linux distributions.
@@ -165,7 +176,9 @@ does not run properly as root, then you cannot run it when using docker unless y
165
176
  `sudo/su` to the host user in the container command. However, running as host user when running
166
177
  rootless docker will map to a different user ID in the host (as specified in `/etc/subuid` on the
167
178
  host) so files shared with the host, including devices like those in `/dev/dri`, will cause
168
- permission issues that can hinder or break the application.
179
+ permission issues that can hinder or break the application. Hence it is recommended to
180
+ just install podman (even if you already have docker installed) which works out of the
181
+ box in rootless mode in all tested distributions.
169
182
 
170
183
 
171
184
  ### Package management: install/uninstall/list/search/...
@@ -404,8 +417,8 @@ systemctl --user enable container-ybox-arch_apps.service
404
417
 
405
418
  Virtual environment setup have been provided for consistent development, test and build
406
419
  with multiple python versions. The minimum python version required is 3.9 and tests are
407
- run against all major python versions higher than that (i.e. 3.10, 3.11, 3.12 and others
408
- in future).
420
+ run against all major python versions higher than that (i.e. 3.10, 3.11, 3.12, 3.13 and
421
+ others in future).
409
422
 
410
423
  The setup uses pyenv with venv which can be used for development with IDEA/PyCharm/VSCode
411
424
  or in terminal, running tests against all supported python versions using `tox` etc.
@@ -432,14 +445,23 @@ Next you can install the required python versions and venv environment:
432
445
  pyenv/setup-venv.sh
433
446
  ```
434
447
 
435
- Finally, you can activate it in bash/zsh:
448
+ Finally, you can activate it.
449
+
450
+ bash:
451
+
452
+ ```sh
453
+ source pyenv/activate.bash
454
+ source .venv/bin/activate
455
+ ```
456
+
457
+ zsh:
436
458
 
437
459
  ```sh
438
- source pyenv/activate.sh
460
+ source pyenv/activate.zsh
439
461
  source .venv/bin/activate
440
462
  ```
441
463
 
442
- Or in fish shell:
464
+ fish:
443
465
 
444
466
  ```
445
467
  source pyenv/activate.fish
@@ -28,6 +28,7 @@ classifiers = [
28
28
  "Programming Language :: Python :: 3.10",
29
29
  "Programming Language :: Python :: 3.11",
30
30
  "Programming Language :: Python :: 3.12",
31
+ "Programming Language :: Python :: 3.13",
31
32
  ]
32
33
  keywords = ["Linux in container", "toolbox"]
33
34
 
@@ -1,2 +1,2 @@
1
1
  """`ybox` is a tool to easily manage linux distributions in containers"""
2
- __version__ = "0.9.9"
2
+ __version__ = "0.9.10"
@@ -10,6 +10,7 @@ import sys
10
10
  from enum import Enum
11
11
  from typing import Callable, Iterable, Optional, Union
12
12
 
13
+ from ybox import __version__ as product_version
13
14
  from ybox.config import Consts
14
15
 
15
16
  from .print import print_error, print_info, print_notice, print_warn
@@ -207,7 +208,7 @@ def run_command(cmd: Union[str, list[str]], capture_output: bool = False,
207
208
  sys.exit(result.returncode)
208
209
  else:
209
210
  return result.returncode
210
- if capture_output and result.stderr:
211
+ if capture_output and result.stderr and error_msg != "SKIP":
211
212
  print_warn(result.stderr.decode("utf-8"), file=sys.stderr)
212
213
  return result.stdout.decode("utf-8") if capture_output else result.returncode
213
214
 
@@ -221,6 +222,21 @@ def _print_subprocess_output(result: subprocess.CompletedProcess[bytes]) -> None
221
222
  print_warn(result.stderr.decode("utf-8"), file=sys.stderr)
222
223
 
223
224
 
225
+ def parser_version_check(parser: argparse.ArgumentParser, argv: list[str]) -> None:
226
+ """
227
+ Update command-line parser to add `--version` option to existing ones that will output the
228
+ ybox product version and exit if specified in the given list of arguments.
229
+
230
+ :param parser: instance of :class:`argparse.ArgumentParser` having the command-line parser
231
+ :param argv: the list of arguments to be parsed
232
+ """
233
+ parser.add_argument("--version", action="store_true", help="output ybox version")
234
+ # argv may have required positional arguments, hence check for --version separately
235
+ if "--version" in argv:
236
+ print(product_version)
237
+ sys.exit(0)
238
+
239
+
224
240
  def parse_opt_deps_args(argv: list[str]) -> argparse.Namespace:
225
241
  """
226
242
  Common command-line parser for `opt_deps` utilities (see [pkgmgr] section of distro.ini)
@@ -29,6 +29,8 @@ end
29
29
  complete -f -c ybox-create -s h -l help -d "show help"
30
30
  complete -c ybox-create -s n -l name -d "name of the ybox container" -r
31
31
  complete -f -c ybox-create -s F -l force-own-orphans -d "force ownership of orphans on shared root"
32
+ complete -f -c ybox-create -s C -l distribution-config -d "path to custom distribution configuration file"
33
+ complete -f -c ybox-create -l distribution-image -d "custom container image"
32
34
  complete -f -c ybox-create -s q -l quiet -d "skip interactive questions"
33
35
  complete -f -c ybox-create -n "not __fish_seen_subcommand_from (__fish_ybox_complete_distributions)" -a "(__fish_ybox_complete_distributions)"
34
36
 
@@ -10,8 +10,8 @@ current_user="$(id -un)"
10
10
  # install binaries for paru from paru-bin (paru takes too long to compile)
11
11
  PARU="paru --noconfirm"
12
12
  echo_color "$fg_cyan" "Installing AUR helper 'paru'" >> $status_file
13
- export HOME="$(eval echo "~$current_user")"
14
- cd ~
13
+ export HOME=$(getent passwd "$current_user" | cut -d: -f6)
14
+ cd "$HOME"
15
15
  rm -rf paru-bin
16
16
  git clone https://aur.archlinux.org/paru-bin.git
17
17
  cd paru-bin
@@ -6,6 +6,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
6
 
7
7
  source "$SCRIPT_DIR/entrypoint-common.sh"
8
8
 
9
+ export HOME=/root
9
10
  # pacman configuration
10
11
  PAC="pacman --noconfirm"
11
12
  echo_color "$fg_cyan" "Configuring pacman" >> $status_file
@@ -17,6 +17,8 @@ where:
17
17
  newlines in the description
18
18
  """
19
19
 
20
+ # TODO: SW: this is returning back installed packages too which should be skipped
21
+
20
22
  import gzip
21
23
  import os
22
24
  import re
@@ -11,7 +11,7 @@ where:
11
11
  and so on; resolution of level > 2 is not required since caller currently ignores those
12
12
  * <order>: this is a simple counter assigned to the dependencies where the value itself is of no
13
13
  significance but if multiple dependencies have the same value then it means that they
14
- are ORed dependencies and only one of them should normlly be selected for installation
14
+ are ORed dependencies and only one of them need to be selected for installation
15
15
  * <installed>: true if the dependency already installed and false otherwise
16
16
  * <description>: detailed description of the dependency; it can contain literal \n to indicate
17
17
  newlines in the description
@@ -69,6 +69,7 @@ class PkgDetail(Enum):
69
69
  OPTIONAL_DEP = 5
70
70
 
71
71
 
72
+ # noinspection PyUnusedLocal
72
73
  def process_next_item(line: str, parse_line: Callable[[str], tuple[PkgDetail, str]],
73
74
  parse_dep: Callable[[str], Iterable[tuple[str, str, Optional[str]]]],
74
75
  installed: Callable[[str], bool], max_level: int,
@@ -20,7 +20,8 @@
20
20
  # - YBOX_SYS_CONF_DIR: path to system configuration directory where configuration directory
21
21
  # shipped with ybox is installed (or the string form of
22
22
  # the directory if it is not on filesystem like an egg or similar)
23
- # - TARGET_HOME: set to the home directory of the container user
23
+ # - TARGET_HOME: set to the home directory of the container user as it exists on the host
24
+ # (i.e. the expanded value of the "home" key in the [base] section)
24
25
  # Additionally a special notation can be used for current date+time with this notation:
25
26
  # ${NOW:<fmt>}. The <fmt> uses the format supported by python strftime
26
27
  # (https://docs.python.org/3/library/datetime.html#datetime.datetime.strftime)
@@ -115,7 +116,7 @@ nvidia = off
115
116
  # works well on most Linux distros (https://wiki.archlinux.org/title/docker or
116
117
  # https://wiki.archlinux.org/title/podman), and the official NVIDIA docs:
117
118
  # https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
118
- # For example on ubuntu with podman, configure the apt repository from the previous link
119
+ # For example, on ubuntu with podman, configure the apt repository from the previous link
119
120
  # and install the package as noted there, then run
120
121
  # `sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml`.
121
122
  # This will need to be repeated if nvidia driver version is upgraded.
@@ -200,29 +201,40 @@ documents = $HOME/Documents:$TARGET_HOME/Documents:ro
200
201
  # section) to a directory that is mounted read-only.
201
202
  #
202
203
  # The value has two parts separated by "->" with the LHS of this being the source that
203
- # is to be copied while the RHS is the required relative path in the target directory.
204
- # On the target container the same is used to symlink from the target on RHS to source on LHS.
204
+ # is to be copied while the RHS is the required relative path in the container's home directory.
205
+ # Any spaces around "->" are excluded from the LHS and RHS names.
205
206
  # Source is skipped if it does not exist or not readable with a message on standard output.
206
207
  #
207
208
  # Typically this will contain shell, vim and other common configuration files.
208
209
  # These can be either files or directories and are skipped if they do not exist.
209
- # The keys here have no special significance other than the fact that they should be
210
- # unique and can be used to override in later files that include this one.
210
+ # The keys here should be unique and can be used to override in later files that include this one.
211
211
  #
212
- # Note: The files are symlinks in the container user area and are mounted on a read-only
213
- # mount by default, so if you need to change a file within a container then you will
214
- # need to first remove the symlink and make a copy of the file. This will remove the
212
+ # Two special suffixes can be used in the key names:
213
+ # 1) ":dir" : this suffix indicates that the source is a directory and entire directory structure
214
+ # should be replicated in the target with symlinks only for the individual files;
215
+ # this helps in cases where user needs to make a separate copy of a file inside
216
+ # the directory (using either ":copy" suffix or manually)
217
+ # 2) ":copy": this suffix indicates that the source should be copied to the target; if a
218
+ # file/directory to be copied lies inside another directory that is being linked,
219
+ # then it should be mentioned before this and marked with ":dir" so that directory
220
+ # structure is replicated in the target (see example of fish shell config below)
221
+ #
222
+ # Note: The files from the host are mounted read-only by default in the target container, so if
223
+ # you need to change a file within a container then you can use the ":copy" suffix in the key name
224
+ # or manually remove the symlink and make a copy of the file. This will remove the
215
225
  # direct sharing between the two which has to be done manually thereon if required.
216
226
  # The sharing behavior also depends on "config_hardlinks" as described in its comment above
217
227
  # in the [base] section.
218
228
  #
219
- # Note: The HOME environment variable here will be evaluated both in the host
220
- # session (for the source to be transferred) and inside the container session
221
- # (for the target). Do not use TARGET_HOME here which can be incorrect for the host session.
229
+ # Note: The LHS should typically have a path having $HOME while RHS will be relative to the
230
+ # target's home inside the container. Do not use $TARGET_HOME on RHS (or LHS for that matter)
231
+ # which is the target's home as on the host and not the one inside the container.
222
232
  [configs]
223
233
  bashrc = $HOME/.bashrc -> .bashrc
224
234
  starship = $HOME/.config/starship.toml -> .config/starship.toml
225
- fishrc = $HOME/.config/fish -> .config/fish
235
+ # replicate fish configuration directory with copy of fish_variables but symlinks for the rest
236
+ fish_conf:dir = $HOME/.config/fish -> .config/fish
237
+ fish_vars:copy = $HOME/.config/fish/fish_variables -> .config/fish/fish_variables
226
238
  omf = $HOME/.config/omf -> .config/omf
227
239
  omf_data = $HOME/.local/share/omf -> .local/share/omf
228
240
  zshrc = $HOME/.zshrc -> .zshrc
@@ -261,10 +273,11 @@ speechconf = $HOME/.config/speech-dispatcher -> .config/speech-dispatcher
261
273
  [env]
262
274
  TERM
263
275
  TERMINFO_DIRS = /usr/share/terminfo:/var/lib/terminfo
264
- XDG_CURRENT_DESKTOP
265
- XDG_SESSION_DESKTOP
276
+ # always pretend desktop to be GNOME since KDE/*DE apps required by xdg-* are not installed
277
+ XDG_CURRENT_DESKTOP = GNOME
278
+ XDG_SESSION_DESKTOP = GNOME
279
+ DESKTOP_SESSION = gnome
266
280
  XDG_SESSION_TYPE
267
- DESKTOP_SESSION
268
281
  GTK_IM_MODULE
269
282
  QT_IM_MODULE
270
283
  SDL_IM_MODULE
@@ -12,12 +12,6 @@ caps_add = SYS_PTRACE
12
12
  #projects = $HOME/projects:$TARGET_HOME/projects
13
13
  #pyenv = $HOME/.pyenv:$TARGET_HOME/.pyenv:ro
14
14
 
15
- [env]
16
- # always pretend desktop to be GNOME since KDE apps required by xdg-* are not installed
17
- XDG_CURRENT_DESKTOP = GNOME
18
- XDG_SESSION_DESKTOP = GNOME
19
- DESKTOP_SESSION = gnome
20
-
21
15
  [apps]
22
16
  # some packages for Arch Linux - uncomment and update for your distribution as required
23
17
  #ides = intellij-idea-community-edition-jre,visual-studio-code-bin,zed
@@ -8,6 +8,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
8
 
9
9
  source "$SCRIPT_DIR/entrypoint-common.sh"
10
10
 
11
+ export HOME=/root
11
12
  echo_color "$fg_cyan" "Copying prime-run, run-in-dir and run-user-bash-cmd" >> $status_file
12
13
  cp -a "$SCRIPT_DIR/prime-run" /usr/local/bin/prime-run
13
14
  cp -a "$SCRIPT_DIR/run-in-dir" /usr/local/bin/run-in-dir
@@ -13,9 +13,11 @@ mkdir -p "$user_home/.gnupg" && chmod 0700 "$user_home/.gnupg"
13
13
  echo "keyserver $DEFAULT_GPG_KEY_SERVER" > "$user_home/.gnupg/dirmngr.conf"
14
14
  rm -f "$user_home"/.gnupg/*/*.lock
15
15
 
16
- echo_color "$fg_cyan" "Enabling python pip installation for $current_user" >> $status_file
17
- mkdir -p "$user_home/.config/pip"
18
- cat > "$user_home/.config/pip/pip.conf" << EOF
16
+ if [ ! -e "$user_home/.config/pip/pip.conf" ]; then
17
+ echo_color "$fg_cyan" "Enabling python pip installation for $current_user" >> $status_file
18
+ mkdir -p "$user_home/.config/pip"
19
+ cat > "$user_home/.config/pip/pip.conf" << EOF
19
20
  [global]
20
21
  break-system-packages = true
21
22
  EOF
23
+ fi
@@ -22,7 +22,7 @@ echo -n > $status_file
22
22
  # the current user as well as the group of the normal user
23
23
  uid="$(id -u)"
24
24
  gid="$(id -g)"
25
- chown $uid:$YBOX_HOST_GID $status_file
25
+ chown $uid:${YBOX_HOST_GID:-$gid} $status_file
26
26
  chmod 0660 $status_file
27
27
  if [ "$uid" -eq 0 ]; then
28
28
  SUDO=""
@@ -47,16 +47,14 @@ function show_usage() {
47
47
  echo " -h show this help message and exit"
48
48
  }
49
49
 
50
- # link the configuration files in HOME to the target directory having the required files
51
- function link_config_files() {
50
+ # copy/link the configuration files in HOME to the target directory having the required files
51
+ function replicate_config_files() {
52
52
  # line is of the form <src> -> <dest>; pattern below matches this while trimming spaces
53
53
  echo_color "$fg_orange" "Linking configuration files from $config_dir to user's home" >> $status_file
54
- pattern='(.*[^[:space:]]+)[[:space:]]*->[[:space:]]*(.*)'
54
+ pattern='(COPY|LINK_DIR|LINK):(.*)'
55
55
  while read -r config; do
56
56
  if [[ "$config" =~ $pattern ]]; then
57
- home_file="${BASH_REMATCH[1]}"
58
- # expand env variables
59
- eval home_file="$home_file"
57
+ home_file="$HOME/${BASH_REMATCH[2]}"
60
58
  dest_file="$config_dir/${BASH_REMATCH[2]}"
61
59
  # only replace the file if it is already a link (assuming the link target may
62
60
  # have changed in the config_list file), or a directory containing links
@@ -80,7 +78,15 @@ function link_config_files() {
80
78
  mkdir -p "$home_filedir"
81
79
  fi
82
80
  if [ ! -e "$home_file" ]; then
83
- ln -s "$dest_file" "$home_file"
81
+ if [ "${BASH_REMATCH[1]}" = "COPY" ]; then
82
+ cp -r "$dest_file" "$home_file"
83
+ elif [ "${BASH_REMATCH[1]}" = "LINK_DIR" ]; then
84
+ # if dest_file is a directory, then replicate the directory structure in home and
85
+ # symlink individual files which is accomplished with "cp -sr"
86
+ cp -sr "$dest_file" "$home_file"
87
+ else # "${BASH_REMATCH[1]}" = "LINK"
88
+ ln -s "$dest_file" "$home_file"
89
+ fi
84
90
  fi
85
91
  fi
86
92
  else
@@ -180,7 +186,7 @@ run_dir=${XDG_RUNTIME_DIR:-/run/user/$uid}
180
186
  if [ -d $run_dir ]; then
181
187
  $SUDO chown $uid:$gid $run_dir 2>/dev/null || true
182
188
  fi
183
- if [ -n "$(ls $run_dir 2>/dev/null)" ]; then
189
+ if compgen -G "$run_dir/*" >/dev/null; then
184
190
  $SUDO chown $uid:$gid $run_dir/* 2>/dev/null || true
185
191
  fi
186
192
 
@@ -212,7 +218,7 @@ fi
212
218
 
213
219
  # process config files, application installs and invoke startup apps
214
220
  if [ -n "$config_list" ]; then
215
- link_config_files
221
+ replicate_config_files
216
222
  fi
217
223
  if [ -n "$app_list" ]; then
218
224
  install_apps
@@ -231,14 +237,17 @@ function cleanup() {
231
237
  # clear status file first just in case other operations do not finish before SIGKILL comes
232
238
  echo -n > $status_file
233
239
  # first send SIGTERM to all "docker exec" processes that will have parent PID as 0 or 1
240
+ kill_sent=0
234
241
  exec_pids="$(ps -e -o ppid=,pid= | \
235
242
  awk '{ if (($1 == 0 || $1 == 1) && $2 != 1 && $2 != '$childPID') print $2 }')"
236
243
  for pid in $exec_pids; do
237
- echo "Sending SIGTERM to $pid"
238
- kill -TERM $pid
244
+ if kill -TERM $pid 2>/dev/null; then
245
+ kill_sent=1
246
+ echo "Sent SIGTERM to $pid"
247
+ fi
239
248
  done
240
249
  # sleep a bit for $exec_pids to finish
241
- [ -n "$exec_pids" ] && sleep 3
250
+ [ $kill_sent -eq 1 ] && sleep 3
242
251
  # lastly kill the infinite tail process
243
252
  kill -TERM $childPID
244
253
  }
@@ -1,7 +1,5 @@
1
1
  #!/bin/sh
2
2
 
3
- set -e
4
-
5
3
  __NV_PRIME_RENDER_OFFLOAD=1
6
4
  __GLX_VENDOR_LIBRARY_NAME=nvidia
7
5
  __VK_LAYER_NV_optimus=NVIDIA_only
@@ -49,6 +49,7 @@ if [ -e "$nvidia_setup" ]; then
49
49
  flock -x -w 60 $lock_fd || /bin/true
50
50
  trap "flock -u $lock_fd || /bin/true" 0 1 2 3 4 5 6 7 8 10 11 12 13 14 15
51
51
  if ! is_nvidia_valid; then
52
+ # set umask for root execution to ensure that other users have read/execute permissions
52
53
  umask 022
53
54
  sudo /bin/bash "$nvidia_setup" || /bin/true
54
55
  fi
@@ -57,4 +58,7 @@ if [ -e "$nvidia_setup" ]; then
57
58
  fi
58
59
  fi
59
60
 
61
+ # reset to more conservative umask setting
62
+ umask 027
63
+
60
64
  exec "$@"
@@ -0,0 +1,30 @@
1
+ #!/bin/bash
2
+
3
+ # This script either runs a given command using bash directly, or if YBOX_HOST_UID environment
4
+ # variable is set to something other than the UID of the current user, then uses sudo to run
5
+ # the command as that UID (plus YBOX_HOST_GID as the GID). This latter case happens for rootless
6
+ # docker where the ybox container runs as the root user (due to absence of --userns=keep-id like
7
+ # in podman) but some commands need to be run as a normal user like Arch's paru/yay AUR helpers.
8
+
9
+ set -e
10
+
11
+ if [ "$#" -ne 1 ]; then
12
+ echo "Usage: $0 <full command to run as single argument like passed to '/bin/bash -c'>"
13
+ exit 1
14
+ fi
15
+
16
+ if [ "$(id -u)" -eq 0 -a -n "$YBOX_HOST_UID" ] && getent passwd $YBOX_HOST_UID > /dev/null; then
17
+ sudo -u "#$YBOX_HOST_UID" -g "#$YBOX_HOST_GID" /bin/bash -c "$1"
18
+ status=$?
19
+ if [ $status -ne 0 ]; then
20
+ echo "FAILED (exit code = $status) in sudo execution of: $1"
21
+ exit $status
22
+ fi
23
+ else
24
+ eval "$1"
25
+ status=$?
26
+ if [ $status -ne 0 ]; then
27
+ echo "FAILED (exit code = $status) in execution of: $1"
28
+ exit $status
29
+ fi
30
+ fi
@@ -0,0 +1,22 @@
1
+ # ybox-{name}.service
2
+ #
3
+ # Autogenerated by ybox-create {version} on {date}
4
+
5
+ [Unit]
6
+ Description={manager_name} ybox-{name}.service
7
+ Wants=network-online.target
8
+ After=network-online.target
9
+ {docker_requires}
10
+ [Service]
11
+ EnvironmentFile={env_file}
12
+ Type=forking
13
+ Restart=on-failure
14
+ TimeoutStopSec=70
15
+ # sleep to allow for initialization of the user's login/graphical environment
16
+ ExecStartPre=/usr/bin/sleep $SLEEP_SECS
17
+ ExecStart=/bin/sh -c 'ybox-control start {name}'
18
+ ExecStop=/bin/sh -c 'ybox-control stop -t 20 --ignore-stopped {name}'
19
+ ExecStopPost=/bin/sh -c 'ybox-control stop -t 20 --ignore-stopped {name}'
20
+ {pid_file}
21
+ [Install]
22
+ WantedBy=default.target
@@ -142,6 +142,9 @@ class Consts:
142
142
  Defines fixed file/path and other names used by ybox that are not configurable.
143
143
  """
144
144
 
145
+ # standard system executable paths
146
+ _SYS_BIN_DIRS = ("/usr/bin", "/bin", "/usr/sbin", "/sbin", "/usr/local/bin", "/usr/local/sbin")
147
+ # regex pattern to match all manual page directories
145
148
  _MAN_DIRS_PATTERN = re.compile(r"/usr(/local)?(/share)?/man(/[^/]*)?/man[0-9][a-zA-Z_]*")
146
149
 
147
150
  @staticmethod
@@ -216,13 +219,18 @@ class Consts:
216
219
  @staticmethod
217
220
  def container_bin_dirs() -> Iterable[str]:
218
221
  """directories on the container that has executables that may need to be wrapped"""
219
- return ("/usr/bin", "/usr/sbin", "/bin", "/sbin", "/usr/local/bin", "/usr/local/sbin")
222
+ return Consts._SYS_BIN_DIRS
220
223
 
221
224
  @staticmethod
222
225
  def container_man_dir_pattern() -> re.Pattern[str]:
223
226
  """directory regex pattern on the container having man-pages that may need to be linked"""
224
227
  return Consts._MAN_DIRS_PATTERN
225
228
 
229
+ @staticmethod
230
+ def sys_bin_dirs() -> Iterable[str]:
231
+ """standard directories to search for system installed executables"""
232
+ return Consts._SYS_BIN_DIRS
233
+
226
234
  @staticmethod
227
235
  def nvidia_target_base_dir() -> str:
228
236
  """base directory path where NVIDIA libs/data are linked in the container"""
@@ -8,14 +8,10 @@ from configparser import SectionProxy
8
8
  from ybox.cmd import PkgMgr, build_shell_command, run_command
9
9
  from ybox.config import StaticConfiguration
10
10
  from ybox.print import print_info
11
- from ybox.state import RuntimeConfiguration, YboxStateManagement
12
11
 
13
12
 
14
- # noinspection PyUnusedLocal
15
13
  def clean_cache(args: argparse.Namespace, pkgmgr: SectionProxy, docker_cmd: str,
16
- conf: StaticConfiguration, runtime_conf: RuntimeConfiguration,
17
- state: YboxStateManagement) -> int:
18
- # pylint: disable=unused-argument
14
+ conf: StaticConfiguration) -> int:
19
15
  """
20
16
  Clean package cache and related intermediate files.
21
17
 
@@ -23,8 +19,6 @@ def clean_cache(args: argparse.Namespace, pkgmgr: SectionProxy, docker_cmd: str,
23
19
  :param pkgmgr: the `[pkgmgr]` section from `distro.ini` configuration file of the distribution
24
20
  :param docker_cmd: the podman/docker executable to use
25
21
  :param conf: the :class:`StaticConfiguration` for the container
26
- :param runtime_conf: the `RuntimeConfiguration` of the container
27
- :param state: instance of `YboxStateManagement` having the state of all ybox containers
28
22
  :return: integer exit status of clean command where 0 represents success
29
23
  """
30
24
  print_info(f"Cleaning package cache in container '{conf.box_name}'")