ruyi 0.44.0b20251219__py3-none-any.whl → 0.45.0__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.
- ruyi/__main__.py +16 -4
- ruyi/cli/cmd.py +6 -5
- ruyi/cli/config_cli.py +14 -11
- ruyi/cli/main.py +14 -4
- ruyi/cli/oobe.py +7 -3
- ruyi/cli/self_cli.py +48 -34
- ruyi/cli/user_input.py +42 -12
- ruyi/cli/version_cli.py +11 -5
- ruyi/config/__init__.py +26 -2
- ruyi/config/errors.py +19 -7
- ruyi/device/provision.py +116 -55
- ruyi/device/provision_cli.py +6 -3
- ruyi/i18n/__init__.py +129 -0
- ruyi/log/__init__.py +6 -5
- ruyi/mux/runtime.py +19 -6
- ruyi/mux/venv/maker.py +93 -35
- ruyi/mux/venv/venv_cli.py +13 -10
- ruyi/pluginhost/plugin_cli.py +4 -3
- ruyi/resource_bundle/__init__.py +22 -8
- ruyi/resource_bundle/__main__.py +6 -5
- ruyi/resource_bundle/data.py +13 -9
- ruyi/ruyipkg/admin_checksum.py +4 -1
- ruyi/ruyipkg/admin_cli.py +9 -6
- ruyi/ruyipkg/augmented_pkg.py +15 -14
- ruyi/ruyipkg/checksum.py +8 -2
- ruyi/ruyipkg/distfile.py +33 -9
- ruyi/ruyipkg/entity.py +12 -2
- ruyi/ruyipkg/entity_cli.py +20 -12
- ruyi/ruyipkg/entity_provider.py +11 -2
- ruyi/ruyipkg/fetcher.py +38 -9
- ruyi/ruyipkg/install.py +143 -42
- ruyi/ruyipkg/install_cli.py +18 -15
- ruyi/ruyipkg/list.py +27 -20
- ruyi/ruyipkg/list_cli.py +12 -7
- ruyi/ruyipkg/news.py +23 -11
- ruyi/ruyipkg/news_cli.py +10 -7
- ruyi/ruyipkg/profile_cli.py +8 -2
- ruyi/ruyipkg/repo.py +22 -8
- ruyi/ruyipkg/unpack.py +42 -8
- ruyi/ruyipkg/unpack_method.py +5 -1
- ruyi/ruyipkg/update_cli.py +8 -3
- ruyi/telemetry/provider.py +74 -29
- ruyi/telemetry/telemetry_cli.py +9 -8
- ruyi/utils/git.py +18 -11
- ruyi/utils/prereqs.py +10 -5
- ruyi/utils/ssl_patch.py +2 -1
- ruyi/version.py +9 -3
- {ruyi-0.44.0b20251219.dist-info → ruyi-0.45.0.dist-info}/METADATA +2 -1
- ruyi-0.45.0.dist-info/RECORD +103 -0
- {ruyi-0.44.0b20251219.dist-info → ruyi-0.45.0.dist-info}/WHEEL +1 -1
- ruyi-0.44.0b20251219.dist-info/RECORD +0 -102
- {ruyi-0.44.0b20251219.dist-info → ruyi-0.45.0.dist-info}/entry_points.txt +0 -0
- {ruyi-0.44.0b20251219.dist-info → ruyi-0.45.0.dist-info}/licenses/LICENSE-Apache.txt +0 -0
ruyi/ruyipkg/fetcher.py
CHANGED
|
@@ -7,6 +7,7 @@ from typing import Any, Final
|
|
|
7
7
|
import requests
|
|
8
8
|
from rich import progress
|
|
9
9
|
|
|
10
|
+
from ..i18n import _
|
|
10
11
|
from ..log import RuyiLogger
|
|
11
12
|
|
|
12
13
|
ENV_OVERRIDE_FETCHER: Final = "RUYI_OVERRIDE_FETCHER"
|
|
@@ -40,19 +41,31 @@ class BaseFetcher:
|
|
|
40
41
|
) -> bool:
|
|
41
42
|
for t in range(retries):
|
|
42
43
|
if t > 0:
|
|
43
|
-
self._logger.I(
|
|
44
|
+
self._logger.I(
|
|
45
|
+
_("retrying download ({current} of {total} times)").format(
|
|
46
|
+
current=t + 1,
|
|
47
|
+
total=retries,
|
|
48
|
+
)
|
|
49
|
+
)
|
|
44
50
|
if self.fetch_one(url, dest, resume):
|
|
45
51
|
return True
|
|
46
52
|
return False
|
|
47
53
|
|
|
48
54
|
def fetch(self, *, resume: bool = False, retries: int = 3) -> None:
|
|
49
55
|
for url in self.urls:
|
|
50
|
-
self._logger.I(
|
|
56
|
+
self._logger.I(
|
|
57
|
+
_("downloading {url} to {dest}").format(
|
|
58
|
+
url=url,
|
|
59
|
+
dest=self.dest,
|
|
60
|
+
)
|
|
61
|
+
)
|
|
51
62
|
if self.fetch_one_with_retry(url, self.dest, resume, retries):
|
|
52
63
|
return
|
|
53
64
|
# all URLs have been tried and all have failed
|
|
54
65
|
raise RuntimeError(
|
|
55
|
-
|
|
66
|
+
_("failed to fetch '{dest}': all source URLs have failed").format(
|
|
67
|
+
dest=self.dest,
|
|
68
|
+
)
|
|
56
69
|
)
|
|
57
70
|
|
|
58
71
|
@classmethod
|
|
@@ -78,7 +91,7 @@ def get_usable_fetcher_cls(logger: RuyiLogger) -> type[BaseFetcher]:
|
|
|
78
91
|
|
|
79
92
|
if _fetcher_cache_populated:
|
|
80
93
|
if _cached_usable_fetcher_class is None:
|
|
81
|
-
raise RuntimeError("no fetcher is available on the system")
|
|
94
|
+
raise RuntimeError(_("no fetcher is available on the system"))
|
|
82
95
|
return _cached_usable_fetcher_class
|
|
83
96
|
|
|
84
97
|
_fetcher_cache_populated = True
|
|
@@ -88,10 +101,16 @@ def get_usable_fetcher_cls(logger: RuyiLogger) -> type[BaseFetcher]:
|
|
|
88
101
|
|
|
89
102
|
cls = KNOWN_FETCHERS.get(override_name)
|
|
90
103
|
if cls is None:
|
|
91
|
-
raise RuntimeError(
|
|
104
|
+
raise RuntimeError(
|
|
105
|
+
_("unknown fetcher '{name}'").format(
|
|
106
|
+
name=override_name,
|
|
107
|
+
)
|
|
108
|
+
)
|
|
92
109
|
if not cls.is_available(logger):
|
|
93
110
|
raise RuntimeError(
|
|
94
|
-
|
|
111
|
+
_("the requested fetcher '{name}' is unavailable on the system").format(
|
|
112
|
+
name=override_name,
|
|
113
|
+
)
|
|
95
114
|
)
|
|
96
115
|
_cached_usable_fetcher_class = cls
|
|
97
116
|
return cls
|
|
@@ -103,7 +122,7 @@ def get_usable_fetcher_cls(logger: RuyiLogger) -> type[BaseFetcher]:
|
|
|
103
122
|
_cached_usable_fetcher_class = cls
|
|
104
123
|
return cls
|
|
105
124
|
|
|
106
|
-
raise RuntimeError("no fetcher is available on the system")
|
|
125
|
+
raise RuntimeError(_("no fetcher is available on the system"))
|
|
107
126
|
|
|
108
127
|
|
|
109
128
|
class CurlFetcher(BaseFetcher):
|
|
@@ -152,7 +171,12 @@ class CurlFetcher(BaseFetcher):
|
|
|
152
171
|
retcode = subprocess.call(argv)
|
|
153
172
|
if retcode != 0:
|
|
154
173
|
self._logger.W(
|
|
155
|
-
|
|
174
|
+
_(
|
|
175
|
+
"failed to fetch distfile: command '{cmd}' returned {retcode}"
|
|
176
|
+
).format(
|
|
177
|
+
cmd=" ".join(argv),
|
|
178
|
+
retcode=retcode,
|
|
179
|
+
)
|
|
156
180
|
)
|
|
157
181
|
return False
|
|
158
182
|
|
|
@@ -190,7 +214,12 @@ class WgetFetcher(BaseFetcher):
|
|
|
190
214
|
retcode = subprocess.call(argv)
|
|
191
215
|
if retcode != 0:
|
|
192
216
|
self._logger.W(
|
|
193
|
-
|
|
217
|
+
_(
|
|
218
|
+
"failed to fetch distfile: command '{cmd}' returned {retcode}"
|
|
219
|
+
).format(
|
|
220
|
+
cmd=" ".join(argv),
|
|
221
|
+
retcode=retcode,
|
|
222
|
+
)
|
|
194
223
|
)
|
|
195
224
|
return False
|
|
196
225
|
|
ruyi/ruyipkg/install.py
CHANGED
|
@@ -8,6 +8,7 @@ from ruyi.ruyipkg.state import BoundInstallationStateStore
|
|
|
8
8
|
|
|
9
9
|
from ..cli.user_input import ask_for_yesno_confirmation
|
|
10
10
|
from ..config import GlobalConfig
|
|
11
|
+
from ..i18n import _
|
|
11
12
|
from ..telemetry.scope import TelemetryScope
|
|
12
13
|
from .atom import Atom
|
|
13
14
|
from .distfile import Distfile
|
|
@@ -43,12 +44,16 @@ def do_extract_atoms(
|
|
|
43
44
|
a = Atom.parse(a_str)
|
|
44
45
|
pm = a.match_in_repo(mr, cfg.include_prereleases)
|
|
45
46
|
if pm is None:
|
|
46
|
-
logger.F(
|
|
47
|
+
logger.F(
|
|
48
|
+
_("atom {atom} matches no package in the repository").format(
|
|
49
|
+
atom=a_str,
|
|
50
|
+
)
|
|
51
|
+
)
|
|
47
52
|
return 1
|
|
48
53
|
|
|
49
54
|
sv = pm.service_level
|
|
50
55
|
if sv.has_known_issues:
|
|
51
|
-
logger.W("package has known issue(s)")
|
|
56
|
+
logger.W(_("package has known issue(s)"))
|
|
52
57
|
for s in sv.render_known_issues(pm.repo.messages, cfg.lang_code):
|
|
53
58
|
logger.I(s)
|
|
54
59
|
|
|
@@ -97,12 +102,20 @@ def _do_extract_pkg(
|
|
|
97
102
|
bm = pm.binary_metadata
|
|
98
103
|
sm = pm.source_metadata
|
|
99
104
|
if bm is None and sm is None:
|
|
100
|
-
logger.F(
|
|
105
|
+
logger.F(
|
|
106
|
+
_("don't know how to extract package [green]{pkg}[/]").format(
|
|
107
|
+
pkg=pkg_name,
|
|
108
|
+
)
|
|
109
|
+
)
|
|
101
110
|
return 2
|
|
102
111
|
|
|
103
112
|
if bm is not None and sm is not None:
|
|
104
113
|
logger.F(
|
|
105
|
-
|
|
114
|
+
_(
|
|
115
|
+
"cannot handle package [green]{pkg}[/]: package is both binary and source"
|
|
116
|
+
).format(
|
|
117
|
+
pkg=pkg_name,
|
|
118
|
+
)
|
|
106
119
|
)
|
|
107
120
|
return 2
|
|
108
121
|
|
|
@@ -114,7 +127,10 @@ def _do_extract_pkg(
|
|
|
114
127
|
|
|
115
128
|
if not distfiles_for_host:
|
|
116
129
|
logger.F(
|
|
117
|
-
|
|
130
|
+
_("package [green]{pkg}[/] declares no distfile for host {host}").format(
|
|
131
|
+
pkg=pkg_name,
|
|
132
|
+
host=canonicalized_host,
|
|
133
|
+
)
|
|
118
134
|
)
|
|
119
135
|
return 2
|
|
120
136
|
|
|
@@ -130,13 +146,21 @@ def _do_extract_pkg(
|
|
|
130
146
|
logger.D("skipping extraction because [yellow]--fetch-only[/] is given")
|
|
131
147
|
continue
|
|
132
148
|
|
|
133
|
-
logger.I(
|
|
149
|
+
logger.I(
|
|
150
|
+
_("extracting [green]{distfile}[/] for package [green]{pkg}[/]").format(
|
|
151
|
+
distfile=df_name,
|
|
152
|
+
pkg=pkg_name,
|
|
153
|
+
)
|
|
154
|
+
)
|
|
134
155
|
# unpack into destination
|
|
135
156
|
df.unpack(dest_dir, logger)
|
|
136
157
|
|
|
137
158
|
if not fetch_only:
|
|
138
159
|
logger.I(
|
|
139
|
-
|
|
160
|
+
_("package [green]{pkg}[/] has been extracted to {dest_dir}").format(
|
|
161
|
+
pkg=pkg_name,
|
|
162
|
+
dest_dir=dest_dir,
|
|
163
|
+
)
|
|
140
164
|
)
|
|
141
165
|
|
|
142
166
|
return 0
|
|
@@ -158,13 +182,15 @@ def do_install_atoms(
|
|
|
158
182
|
a = Atom.parse(a_str)
|
|
159
183
|
pm = a.match_in_repo(mr, config.include_prereleases)
|
|
160
184
|
if pm is None:
|
|
161
|
-
logger.F(
|
|
185
|
+
logger.F(
|
|
186
|
+
_("atom {atom} matches no package in the repository").format(atom=a_str)
|
|
187
|
+
)
|
|
162
188
|
return 1
|
|
163
189
|
pkg_name = pm.name_for_installation
|
|
164
190
|
|
|
165
191
|
sv = pm.service_level
|
|
166
192
|
if sv.has_known_issues:
|
|
167
|
-
logger.W("package has known issue(s)")
|
|
193
|
+
logger.W(_("package has known issue(s)"))
|
|
168
194
|
for s in sv.render_known_issues(pm.repo.messages, config.lang_code):
|
|
169
195
|
logger.I(s)
|
|
170
196
|
|
|
@@ -213,7 +239,11 @@ def do_install_atoms(
|
|
|
213
239
|
return ret
|
|
214
240
|
continue
|
|
215
241
|
|
|
216
|
-
logger.F(
|
|
242
|
+
logger.F(
|
|
243
|
+
_("don't know how to handle non-binary package [green]{pkg}[/]").format(
|
|
244
|
+
pkg=pkg_name,
|
|
245
|
+
)
|
|
246
|
+
)
|
|
217
247
|
return 2
|
|
218
248
|
|
|
219
249
|
return 0
|
|
@@ -249,11 +279,17 @@ def _do_install_binary_pkg(
|
|
|
249
279
|
|
|
250
280
|
if is_installed:
|
|
251
281
|
if not reinstall:
|
|
252
|
-
logger.I(
|
|
282
|
+
logger.I(
|
|
283
|
+
_("skipping already installed package [green]{pkg}[/]").format(
|
|
284
|
+
pkg=pkg_name,
|
|
285
|
+
)
|
|
286
|
+
)
|
|
253
287
|
return 0
|
|
254
288
|
|
|
255
289
|
logger.W(
|
|
256
|
-
|
|
290
|
+
_(
|
|
291
|
+
"package [green]{pkg}[/] seems already installed; purging and re-installing due to [yellow]--reinstall[/]"
|
|
292
|
+
).format(pkg=pkg_name)
|
|
257
293
|
)
|
|
258
294
|
# Remove from state tracking before purging
|
|
259
295
|
rgs.remove_installation(
|
|
@@ -290,7 +326,12 @@ def _do_install_binary_pkg(
|
|
|
290
326
|
install_path=install_root,
|
|
291
327
|
)
|
|
292
328
|
|
|
293
|
-
logger.I(
|
|
329
|
+
logger.I(
|
|
330
|
+
_("package [green]{pkg}[/] installed to [yellow]{install_root}[/]").format(
|
|
331
|
+
pkg=pkg_name,
|
|
332
|
+
install_root=install_root,
|
|
333
|
+
)
|
|
334
|
+
)
|
|
294
335
|
return 0
|
|
295
336
|
|
|
296
337
|
|
|
@@ -312,7 +353,10 @@ def _do_install_binary_pkg_to(
|
|
|
312
353
|
distfiles_for_host = bm.get_distfile_names_for_host(str(canonicalized_host))
|
|
313
354
|
if not distfiles_for_host:
|
|
314
355
|
logger.F(
|
|
315
|
-
|
|
356
|
+
_("package [green]{pkg}[/] declares no binary for host {host}").format(
|
|
357
|
+
pkg=pkg_name,
|
|
358
|
+
host=canonicalized_host,
|
|
359
|
+
)
|
|
316
360
|
)
|
|
317
361
|
return 2
|
|
318
362
|
|
|
@@ -323,10 +367,17 @@ def _do_install_binary_pkg_to(
|
|
|
323
367
|
df.ensure(logger)
|
|
324
368
|
|
|
325
369
|
if fetch_only:
|
|
326
|
-
logger.D(
|
|
370
|
+
logger.D(
|
|
371
|
+
_("skipping installation because [yellow]--fetch-only[/] is given")
|
|
372
|
+
)
|
|
327
373
|
continue
|
|
328
374
|
|
|
329
|
-
logger.I(
|
|
375
|
+
logger.I(
|
|
376
|
+
_("extracting [green]{distfile}[/] for package [green]{pkg}[/]").format(
|
|
377
|
+
distfile=df_name,
|
|
378
|
+
pkg=pkg_name,
|
|
379
|
+
)
|
|
380
|
+
)
|
|
330
381
|
df.unpack(install_root, logger)
|
|
331
382
|
|
|
332
383
|
return 0
|
|
@@ -361,11 +412,17 @@ def _do_install_blob_pkg(
|
|
|
361
412
|
|
|
362
413
|
if is_installed:
|
|
363
414
|
if not reinstall:
|
|
364
|
-
logger.I(
|
|
415
|
+
logger.I(
|
|
416
|
+
_("skipping already installed package [green]{pkg}[/]").format(
|
|
417
|
+
pkg=pkg_name,
|
|
418
|
+
)
|
|
419
|
+
)
|
|
365
420
|
return 0
|
|
366
421
|
|
|
367
422
|
logger.W(
|
|
368
|
-
|
|
423
|
+
_(
|
|
424
|
+
"package [green]{pkg}[/] seems already installed; purging and re-installing due to [yellow]--reinstall[/]"
|
|
425
|
+
).format(pkg=pkg_name)
|
|
369
426
|
)
|
|
370
427
|
# Remove from state tracking before purging
|
|
371
428
|
rgs.remove_installation(
|
|
@@ -401,7 +458,12 @@ def _do_install_blob_pkg(
|
|
|
401
458
|
install_path=install_root,
|
|
402
459
|
)
|
|
403
460
|
|
|
404
|
-
logger.I(
|
|
461
|
+
logger.I(
|
|
462
|
+
_("package [green]{pkg}[/] installed to [yellow]{install_root}[/]").format(
|
|
463
|
+
pkg=pkg_name,
|
|
464
|
+
install_root=install_root,
|
|
465
|
+
)
|
|
466
|
+
)
|
|
405
467
|
return 0
|
|
406
468
|
|
|
407
469
|
|
|
@@ -420,7 +482,9 @@ def _do_install_blob_pkg_to(
|
|
|
420
482
|
dfs = pm.distfiles
|
|
421
483
|
distfile_names = bm.get_distfile_names()
|
|
422
484
|
if not distfile_names:
|
|
423
|
-
logger.F(
|
|
485
|
+
logger.F(
|
|
486
|
+
_("package [green]{pkg}[/] declares no blob distfile").format(pkg=pkg_name)
|
|
487
|
+
)
|
|
424
488
|
return 2
|
|
425
489
|
|
|
426
490
|
for df_name in distfile_names:
|
|
@@ -430,10 +494,17 @@ def _do_install_blob_pkg_to(
|
|
|
430
494
|
df.ensure(logger)
|
|
431
495
|
|
|
432
496
|
if fetch_only:
|
|
433
|
-
logger.D(
|
|
497
|
+
logger.D(
|
|
498
|
+
_("skipping installation because [yellow]--fetch-only[/] is given")
|
|
499
|
+
)
|
|
434
500
|
continue
|
|
435
501
|
|
|
436
|
-
logger.I(
|
|
502
|
+
logger.I(
|
|
503
|
+
_("extracting [green]{distfile}[/] for package [green]{pkg}[/]").format(
|
|
504
|
+
distfile=df_name,
|
|
505
|
+
pkg=pkg_name,
|
|
506
|
+
)
|
|
507
|
+
)
|
|
437
508
|
df.unpack_or_symlink(install_root, logger)
|
|
438
509
|
|
|
439
510
|
return 0
|
|
@@ -457,21 +528,31 @@ def do_uninstall_atoms(
|
|
|
457
528
|
a = Atom.parse(a_str)
|
|
458
529
|
pm = a.match_in_repo(bis, config.include_prereleases)
|
|
459
530
|
if pm is None:
|
|
460
|
-
logger.F(
|
|
531
|
+
logger.F(
|
|
532
|
+
_("atom [yellow]{atom}[/] is non-existent or not installed").format(
|
|
533
|
+
atom=a_str,
|
|
534
|
+
)
|
|
535
|
+
)
|
|
461
536
|
return 1
|
|
462
537
|
pms_to_uninstall.append((a_str, pm))
|
|
463
538
|
|
|
464
539
|
if not pms_to_uninstall:
|
|
465
|
-
logger.I("no packages to uninstall")
|
|
540
|
+
logger.I(_("no packages to uninstall"))
|
|
466
541
|
return 0
|
|
467
542
|
|
|
468
|
-
logger.I("the following packages will be uninstalled:")
|
|
469
|
-
for
|
|
470
|
-
logger.I(
|
|
543
|
+
logger.I(_("the following packages will be uninstalled:"))
|
|
544
|
+
for _unused, pm in pms_to_uninstall:
|
|
545
|
+
logger.I(
|
|
546
|
+
_(" - [green]{category}/{name}[/] ({version})").format(
|
|
547
|
+
category=pm.category,
|
|
548
|
+
name=pm.name,
|
|
549
|
+
version=pm.ver,
|
|
550
|
+
)
|
|
551
|
+
)
|
|
471
552
|
|
|
472
553
|
if not assume_yes:
|
|
473
|
-
if not ask_for_yesno_confirmation(logger, "Proceed?", default=False):
|
|
474
|
-
logger.I("uninstallation aborted")
|
|
554
|
+
if not ask_for_yesno_confirmation(logger, _("Proceed?"), default=False):
|
|
555
|
+
logger.I(_("uninstallation aborted"))
|
|
475
556
|
return 0
|
|
476
557
|
|
|
477
558
|
for a_str, pm in pms_to_uninstall:
|
|
@@ -504,7 +585,11 @@ def do_uninstall_atoms(
|
|
|
504
585
|
return ret
|
|
505
586
|
continue
|
|
506
587
|
|
|
507
|
-
logger.F(
|
|
588
|
+
logger.F(
|
|
589
|
+
_("don't know how to handle non-binary package [green]{pkg}[/]").format(
|
|
590
|
+
pkg=pkg_name,
|
|
591
|
+
)
|
|
592
|
+
)
|
|
508
593
|
return 2
|
|
509
594
|
|
|
510
595
|
return 0
|
|
@@ -534,21 +619,29 @@ def _do_uninstall_binary_pkg(
|
|
|
534
619
|
# Check directory existence if the PM state says the package is not installed
|
|
535
620
|
if not is_installed:
|
|
536
621
|
if not os.path.exists(install_root):
|
|
537
|
-
logger.I(
|
|
622
|
+
logger.I(
|
|
623
|
+
_("skipping not-installed package [green]{pkg}[/]").format(
|
|
624
|
+
pkg=pkg_name,
|
|
625
|
+
)
|
|
626
|
+
)
|
|
538
627
|
return 0
|
|
539
628
|
|
|
540
629
|
# There may be potentially user-generated data in the directory,
|
|
541
630
|
# let's be safe and fail the process.
|
|
542
631
|
logger.F(
|
|
543
|
-
|
|
632
|
+
_(
|
|
633
|
+
"package [green]{pkg}[/] is not tracked as installed, but its directory [yellow]{install_root}[/] exists."
|
|
634
|
+
).format(pkg=pkg_name, install_root=install_root)
|
|
544
635
|
)
|
|
545
|
-
logger.I("Please remove it manually if you are sure it's safe to do so.")
|
|
636
|
+
logger.I(_("Please remove it manually if you are sure it's safe to do so."))
|
|
546
637
|
logger.I(
|
|
547
|
-
|
|
638
|
+
_(
|
|
639
|
+
"If you believe this is a bug, please file an issue at [yellow]https://github.com/ruyisdk/ruyi/issues[/]."
|
|
640
|
+
)
|
|
548
641
|
)
|
|
549
642
|
return 1
|
|
550
643
|
|
|
551
|
-
logger.I(
|
|
644
|
+
logger.I(_("uninstalling package [green]{pkg}[/]").format(pkg=pkg_name))
|
|
552
645
|
if is_installed:
|
|
553
646
|
rgs.remove_installation(
|
|
554
647
|
pm.repo_id,
|
|
@@ -561,7 +654,7 @@ def _do_uninstall_binary_pkg(
|
|
|
561
654
|
if os.path.exists(install_root):
|
|
562
655
|
shutil.rmtree(install_root)
|
|
563
656
|
|
|
564
|
-
logger.I(
|
|
657
|
+
logger.I(_("package [green]{pkg}[/] uninstalled").format(pkg=pkg_name))
|
|
565
658
|
return 0
|
|
566
659
|
|
|
567
660
|
|
|
@@ -588,21 +681,29 @@ def _do_uninstall_blob_pkg(
|
|
|
588
681
|
# Check directory existence if the PM state says the package is not installed
|
|
589
682
|
if not is_installed:
|
|
590
683
|
if not os.path.exists(install_root):
|
|
591
|
-
logger.I(
|
|
684
|
+
logger.I(
|
|
685
|
+
_("skipping not-installed package [green]{pkg}[/]").format(
|
|
686
|
+
pkg=pkg_name,
|
|
687
|
+
)
|
|
688
|
+
)
|
|
592
689
|
return 0
|
|
593
690
|
|
|
594
691
|
# There may be potentially user-generated data in the directory,
|
|
595
692
|
# let's be safe and fail the process.
|
|
596
693
|
logger.F(
|
|
597
|
-
|
|
694
|
+
_(
|
|
695
|
+
"package [green]{pkg}[/] is not tracked as installed, but its directory [yellow]{install_root}[/] exists."
|
|
696
|
+
).format(pkg=pkg_name, install_root=install_root)
|
|
598
697
|
)
|
|
599
|
-
logger.I("Please remove it manually if you are sure it's safe to do so.")
|
|
698
|
+
logger.I(_("Please remove it manually if you are sure it's safe to do so."))
|
|
600
699
|
logger.I(
|
|
601
|
-
|
|
700
|
+
_(
|
|
701
|
+
"If you believe this is a bug, please file an issue at [yellow]https://github.com/ruyisdk/ruyi/issues[/]."
|
|
702
|
+
)
|
|
602
703
|
)
|
|
603
704
|
return 1
|
|
604
705
|
|
|
605
|
-
logger.I(
|
|
706
|
+
logger.I(_("uninstalling package [green]{pkg}[/]").format(pkg=pkg_name))
|
|
606
707
|
if is_installed:
|
|
607
708
|
rgs.remove_installation(
|
|
608
709
|
pm.repo_id,
|
|
@@ -615,5 +716,5 @@ def _do_uninstall_blob_pkg(
|
|
|
615
716
|
if os.path.exists(install_root):
|
|
616
717
|
shutil.rmtree(install_root)
|
|
617
718
|
|
|
618
|
-
logger.I(
|
|
719
|
+
logger.I(_("package [green]{pkg}[/] uninstalled").format(pkg=pkg_name))
|
|
619
720
|
return 0
|
ruyi/ruyipkg/install_cli.py
CHANGED
|
@@ -3,6 +3,7 @@ import pathlib
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from ..cli.cmd import RootCommand
|
|
6
|
+
from ..i18n import _
|
|
6
7
|
from .cli_completion import package_completer_builder
|
|
7
8
|
from .host import get_native_host
|
|
8
9
|
|
|
@@ -14,7 +15,7 @@ if TYPE_CHECKING:
|
|
|
14
15
|
class ExtractCommand(
|
|
15
16
|
RootCommand,
|
|
16
17
|
cmd="extract",
|
|
17
|
-
help="Fetch package(s) then extract to current directory",
|
|
18
|
+
help=_("Fetch package(s) then extract to current directory"),
|
|
18
19
|
):
|
|
19
20
|
@classmethod
|
|
20
21
|
def configure_args(cls, gc: "GlobalConfig", p: "ArgumentParser") -> None:
|
|
@@ -22,7 +23,7 @@ class ExtractCommand(
|
|
|
22
23
|
"atom",
|
|
23
24
|
type=str,
|
|
24
25
|
nargs="+",
|
|
25
|
-
help="Specifier (atom) of the package(s) to extract",
|
|
26
|
+
help=_("Specifier (atom) of the package(s) to extract"),
|
|
26
27
|
)
|
|
27
28
|
if gc.is_cli_autocomplete:
|
|
28
29
|
a.completer = package_completer_builder(gc)
|
|
@@ -33,24 +34,26 @@ class ExtractCommand(
|
|
|
33
34
|
type=str,
|
|
34
35
|
metavar="DESTDIR",
|
|
35
36
|
default=".",
|
|
36
|
-
help="Destination directory to extract to (default: current directory)",
|
|
37
|
+
help=_("Destination directory to extract to (default: current directory)"),
|
|
37
38
|
)
|
|
38
39
|
p.add_argument(
|
|
39
40
|
"--extract-without-subdir",
|
|
40
41
|
action="store_true",
|
|
41
|
-
help=
|
|
42
|
+
help=_(
|
|
43
|
+
"Extract files directly into DESTDIR instead of package-named subdirectories"
|
|
44
|
+
),
|
|
42
45
|
)
|
|
43
46
|
p.add_argument(
|
|
44
47
|
"-f",
|
|
45
48
|
"--fetch-only",
|
|
46
49
|
action="store_true",
|
|
47
|
-
help="Fetch distribution files only without installing",
|
|
50
|
+
help=_("Fetch distribution files only without installing"),
|
|
48
51
|
)
|
|
49
52
|
p.add_argument(
|
|
50
53
|
"--host",
|
|
51
54
|
type=str,
|
|
52
55
|
default=get_native_host(),
|
|
53
|
-
help="Override the host architecture (normally not needed)",
|
|
56
|
+
help=_("Override the host architecture (normally not needed)"),
|
|
54
57
|
)
|
|
55
58
|
|
|
56
59
|
@classmethod
|
|
@@ -81,7 +84,7 @@ class InstallCommand(
|
|
|
81
84
|
RootCommand,
|
|
82
85
|
cmd="install",
|
|
83
86
|
aliases=["i"],
|
|
84
|
-
help="Install package from configured repository",
|
|
87
|
+
help=_("Install package from configured repository"),
|
|
85
88
|
):
|
|
86
89
|
@classmethod
|
|
87
90
|
def configure_args(cls, gc: "GlobalConfig", p: "ArgumentParser") -> None:
|
|
@@ -89,7 +92,7 @@ class InstallCommand(
|
|
|
89
92
|
"atom",
|
|
90
93
|
type=str,
|
|
91
94
|
nargs="+",
|
|
92
|
-
help="Specifier (atom) of the package to install",
|
|
95
|
+
help=_("Specifier (atom) of the package to install"),
|
|
93
96
|
)
|
|
94
97
|
if gc.is_cli_autocomplete:
|
|
95
98
|
a.completer = package_completer_builder(gc)
|
|
@@ -98,18 +101,18 @@ class InstallCommand(
|
|
|
98
101
|
"-f",
|
|
99
102
|
"--fetch-only",
|
|
100
103
|
action="store_true",
|
|
101
|
-
help="Fetch distribution files only without installing",
|
|
104
|
+
help=_("Fetch distribution files only without installing"),
|
|
102
105
|
)
|
|
103
106
|
p.add_argument(
|
|
104
107
|
"--host",
|
|
105
108
|
type=str,
|
|
106
109
|
default=get_native_host(),
|
|
107
|
-
help="Override the host architecture (normally not needed)",
|
|
110
|
+
help=_("Override the host architecture (normally not needed)"),
|
|
108
111
|
)
|
|
109
112
|
p.add_argument(
|
|
110
113
|
"--reinstall",
|
|
111
114
|
action="store_true",
|
|
112
|
-
help="Force re-installation of already installed packages",
|
|
115
|
+
help=_("Force re-installation of already installed packages"),
|
|
113
116
|
)
|
|
114
117
|
|
|
115
118
|
@classmethod
|
|
@@ -136,7 +139,7 @@ class UninstallCommand(
|
|
|
136
139
|
RootCommand,
|
|
137
140
|
cmd="uninstall",
|
|
138
141
|
aliases=["remove", "rm"],
|
|
139
|
-
help="Uninstall installed packages",
|
|
142
|
+
help=_("Uninstall installed packages"),
|
|
140
143
|
):
|
|
141
144
|
@classmethod
|
|
142
145
|
def configure_args(cls, gc: "GlobalConfig", p: argparse.ArgumentParser) -> None:
|
|
@@ -144,20 +147,20 @@ class UninstallCommand(
|
|
|
144
147
|
"atom",
|
|
145
148
|
type=str,
|
|
146
149
|
nargs="+",
|
|
147
|
-
help="Specifier (atom) of the package to uninstall",
|
|
150
|
+
help=_("Specifier (atom) of the package to uninstall"),
|
|
148
151
|
)
|
|
149
152
|
p.add_argument(
|
|
150
153
|
"--host",
|
|
151
154
|
type=str,
|
|
152
155
|
default=get_native_host(),
|
|
153
|
-
help="Override the host architecture (normally not needed)",
|
|
156
|
+
help=_("Override the host architecture (normally not needed)"),
|
|
154
157
|
)
|
|
155
158
|
p.add_argument(
|
|
156
159
|
"-y",
|
|
157
160
|
"--yes",
|
|
158
161
|
action="store_true",
|
|
159
162
|
dest="assume_yes",
|
|
160
|
-
help="Assume yes to all prompts",
|
|
163
|
+
help=_("Assume yes to all prompts"),
|
|
161
164
|
)
|
|
162
165
|
|
|
163
166
|
@classmethod
|