ruyi 0.45.0__tar.gz → 0.45.0a20251230__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.
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/PKG-INFO +1 -2
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/pyproject.toml +1 -2
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/__main__.py +4 -16
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/cli/cmd.py +5 -6
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/cli/config_cli.py +11 -14
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/cli/main.py +4 -14
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/cli/oobe.py +3 -7
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/cli/self_cli.py +34 -48
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/cli/user_input.py +12 -42
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/cli/version_cli.py +5 -11
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/config/__init__.py +2 -26
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/config/errors.py +7 -19
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/device/provision.py +55 -116
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/device/provision_cli.py +3 -6
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/log/__init__.py +5 -6
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/mux/runtime.py +6 -19
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/mux/venv/maker.py +35 -93
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/mux/venv/venv_cli.py +10 -13
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/pluginhost/plugin_cli.py +3 -4
- ruyi-0.45.0a20251230/ruyi/resource_bundle/__init__.py +20 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/resource_bundle/__main__.py +5 -6
- ruyi-0.45.0a20251230/ruyi/resource_bundle/data.py +26 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/admin_checksum.py +1 -4
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/admin_cli.py +6 -9
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/augmented_pkg.py +14 -15
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/checksum.py +2 -8
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/distfile.py +9 -33
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/entity.py +2 -12
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/entity_cli.py +12 -20
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/entity_provider.py +2 -11
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/fetcher.py +9 -38
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/install.py +42 -143
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/install_cli.py +15 -18
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/list.py +20 -27
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/list_cli.py +7 -12
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/news.py +11 -23
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/news_cli.py +7 -10
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/profile_cli.py +2 -8
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/repo.py +8 -22
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/unpack.py +8 -42
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/unpack_method.py +1 -5
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/update_cli.py +3 -8
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/telemetry/provider.py +29 -74
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/telemetry/telemetry_cli.py +8 -9
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/git.py +11 -18
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/prereqs.py +5 -10
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/ssl_patch.py +1 -2
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/version.py +3 -9
- ruyi-0.45.0/ruyi/i18n/__init__.py +0 -129
- ruyi-0.45.0/ruyi/resource_bundle/__init__.py +0 -34
- ruyi-0.45.0/ruyi/resource_bundle/data.py +0 -30
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/LICENSE-Apache.txt +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/README.md +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/__init__.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/cli/__init__.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/cli/builtin_commands.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/cli/completer.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/cli/completion.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/config/editor.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/config/news.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/config/schema.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/device/__init__.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/mux/__init__.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/mux/venv/__init__.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/mux/venv/emulator_cfg.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/mux/venv_cfg.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/pluginhost/__init__.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/pluginhost/api.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/pluginhost/ctx.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/pluginhost/paths.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/pluginhost/unsandboxed.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/py.typed +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/__init__.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/atom.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/canonical_dump.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/cli_completion.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/host.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/list_filter.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/msg.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/news_store.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/pkg_manifest.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/profile.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/protocols.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/ruyipkg/state.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/telemetry/__init__.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/telemetry/aggregate.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/telemetry/event.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/telemetry/scope.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/telemetry/store.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/__init__.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/ar.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/ci.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/frontmatter.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/global_mode.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/l10n.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/markdown.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/mounts.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/node_info.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/nuitka.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/porcelain.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/templating.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/toml.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/url.py +0 -0
- {ruyi-0.45.0 → ruyi-0.45.0a20251230}/ruyi/utils/xdg_basedir.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ruyi
|
|
3
|
-
Version: 0.45.
|
|
3
|
+
Version: 0.45.0a20251230
|
|
4
4
|
Summary: Package manager for RuyiSDK
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -224,7 +224,6 @@ Classifier: Topic :: System :: Software Distribution
|
|
|
224
224
|
Classifier: Typing :: Typed
|
|
225
225
|
Requires-Dist: argcomplete (>=2.0.0)
|
|
226
226
|
Requires-Dist: arpy
|
|
227
|
-
Requires-Dist: babel (>=2.8.0)
|
|
228
227
|
Requires-Dist: fastjsonschema (>=2.15.1)
|
|
229
228
|
Requires-Dist: jinja2 (>=3,<4)
|
|
230
229
|
Requires-Dist: pygit2 (>=1.6) ; python_version >= "3.11"
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ruyi"
|
|
7
|
-
version = "0.45.0"
|
|
7
|
+
version = "0.45.0-alpha.20251230"
|
|
8
8
|
description = "Package manager for RuyiSDK"
|
|
9
9
|
keywords = ["ruyi", "ruyisdk"]
|
|
10
10
|
license = { file = "LICENSE-Apache.txt" }
|
|
@@ -32,7 +32,6 @@ requires-python = ">=3.10"
|
|
|
32
32
|
dependencies = [
|
|
33
33
|
"argcomplete>=2.0.0",
|
|
34
34
|
"arpy",
|
|
35
|
-
"babel>=2.8.0",
|
|
36
35
|
"fastjsonschema>=2.15.1",
|
|
37
36
|
"jinja2 (>=3, <4)",
|
|
38
37
|
"pygit2 (>=1.6, <1.19); python_version<'3.11'",
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
-
import pathlib
|
|
5
4
|
import sys
|
|
6
5
|
|
|
7
6
|
import ruyi
|
|
8
|
-
from ruyi.i18n import _, ADAPTER
|
|
9
7
|
from ruyi.utils.ci import is_running_in_ci
|
|
10
8
|
from ruyi.utils.global_mode import (
|
|
11
9
|
EnvGlobalModeProvider,
|
|
@@ -43,8 +41,6 @@ def _is_allowed_to_run_as_root() -> bool:
|
|
|
43
41
|
|
|
44
42
|
def entrypoint() -> None:
|
|
45
43
|
gm = EnvGlobalModeProvider(os.environ, sys.argv)
|
|
46
|
-
ADAPTER.init_from_env(os.environ)
|
|
47
|
-
ADAPTER.hook()
|
|
48
44
|
|
|
49
45
|
# NOTE: import of `ruyi.log` takes ~90ms on my machine, so initialization
|
|
50
46
|
# of logging is deferred as late as possible
|
|
@@ -54,16 +50,11 @@ def entrypoint() -> None:
|
|
|
54
50
|
|
|
55
51
|
logger = RuyiConsoleLogger(gm)
|
|
56
52
|
|
|
57
|
-
logger.F(
|
|
53
|
+
logger.F("refusing to run as super user outside CI without explicit consent")
|
|
58
54
|
|
|
59
55
|
choices = ", ".join(f"'{x}'" for x in TRUTHY_ENV_VAR_VALUES)
|
|
60
56
|
logger.I(
|
|
61
|
-
|
|
62
|
-
"re-run with environment variable [yellow]{env_var}[/] set to one of [yellow]{choices}[/] to signify consent"
|
|
63
|
-
).format(
|
|
64
|
-
env_var=ENV_FORCE_ALLOW_ROOT,
|
|
65
|
-
choices=choices,
|
|
66
|
-
)
|
|
57
|
+
f"re-run with environment variable [yellow]{ENV_FORCE_ALLOW_ROOT}[/] set to one of [yellow]{choices}[/] to signify consent"
|
|
67
58
|
)
|
|
68
59
|
sys.exit(1)
|
|
69
60
|
|
|
@@ -72,7 +63,7 @@ def entrypoint() -> None:
|
|
|
72
63
|
|
|
73
64
|
logger = RuyiConsoleLogger(gm)
|
|
74
65
|
|
|
75
|
-
logger.F(
|
|
66
|
+
logger.F("no argv?")
|
|
76
67
|
sys.exit(1)
|
|
77
68
|
|
|
78
69
|
if gm.is_packaged and ruyi.__compiled__.standalone:
|
|
@@ -94,11 +85,8 @@ def entrypoint() -> None:
|
|
|
94
85
|
#
|
|
95
86
|
# we assume the one-file build if Nuitka is detected; sys.argv[0] does NOT
|
|
96
87
|
# work if it's just `ruyi` so we have to check our parent process in that case
|
|
88
|
+
self_exe = get_nuitka_self_exe() if gm.is_packaged else __file__
|
|
97
89
|
sys.argv[0] = get_argv0()
|
|
98
|
-
if gm.is_packaged:
|
|
99
|
-
self_exe = get_nuitka_self_exe()
|
|
100
|
-
else:
|
|
101
|
-
self_exe = str(pathlib.Path(sys.argv[0]).resolve())
|
|
102
90
|
gm.record_self_exe(sys.argv[0], __file__, self_exe)
|
|
103
91
|
|
|
104
92
|
from ruyi.config import GlobalConfig
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
from typing import Callable, IO, Protocol, TYPE_CHECKING
|
|
3
3
|
|
|
4
|
-
from ..i18n import _
|
|
5
4
|
from . import RUYI_ENTRYPOINT_NAME
|
|
6
5
|
|
|
7
6
|
if TYPE_CHECKING:
|
|
@@ -115,7 +114,7 @@ class BaseCommand:
|
|
|
115
114
|
return
|
|
116
115
|
|
|
117
116
|
sp = p.add_subparsers(
|
|
118
|
-
title=
|
|
117
|
+
title="subcommands",
|
|
119
118
|
required=cls.is_subcommand_required,
|
|
120
119
|
)
|
|
121
120
|
for subcmd_cls in cls.parsers:
|
|
@@ -159,7 +158,7 @@ class RootCommand(
|
|
|
159
158
|
has_subcommands=True,
|
|
160
159
|
has_main=True,
|
|
161
160
|
prog=RUYI_ENTRYPOINT_NAME,
|
|
162
|
-
description=
|
|
161
|
+
description="RuyiSDK Package Manager",
|
|
163
162
|
):
|
|
164
163
|
@classmethod
|
|
165
164
|
def configure_args(cls, gc: "GlobalConfig", p: "ArgumentParser") -> None:
|
|
@@ -171,12 +170,12 @@ class RootCommand(
|
|
|
171
170
|
action="store_const",
|
|
172
171
|
dest="func",
|
|
173
172
|
const=cli_version,
|
|
174
|
-
help=
|
|
173
|
+
help="Print version information",
|
|
175
174
|
)
|
|
176
175
|
p.add_argument(
|
|
177
176
|
"--porcelain",
|
|
178
177
|
action="store_true",
|
|
179
|
-
help=
|
|
178
|
+
help="Give the output in a machine-friendly format if applicable",
|
|
180
179
|
)
|
|
181
180
|
|
|
182
181
|
# https://github.com/python/cpython/issues/67037 prevents the registration
|
|
@@ -220,7 +219,7 @@ class AdminCommand(
|
|
|
220
219
|
has_subcommands=True,
|
|
221
220
|
# https://github.com/python/cpython/issues/67037
|
|
222
221
|
# help=argparse.SUPPRESS,
|
|
223
|
-
help=
|
|
222
|
+
help="(NOT FOR REGULAR USERS) Subcommands for managing Ruyi repos",
|
|
224
223
|
):
|
|
225
224
|
@classmethod
|
|
226
225
|
def configure_args(cls, gc: "GlobalConfig", p: "ArgumentParser") -> None:
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
from typing import TYPE_CHECKING
|
|
3
3
|
|
|
4
|
-
from ..i18n import _
|
|
5
4
|
from .cmd import RootCommand
|
|
6
5
|
|
|
7
6
|
if TYPE_CHECKING:
|
|
@@ -14,7 +13,7 @@ class ConfigCommand(
|
|
|
14
13
|
RootCommand,
|
|
15
14
|
cmd="config",
|
|
16
15
|
has_subcommands=True,
|
|
17
|
-
help=
|
|
16
|
+
help="Manage Ruyi's config options",
|
|
18
17
|
):
|
|
19
18
|
@classmethod
|
|
20
19
|
def configure_args(
|
|
@@ -28,7 +27,7 @@ class ConfigCommand(
|
|
|
28
27
|
class ConfigGetCommand(
|
|
29
28
|
ConfigCommand,
|
|
30
29
|
cmd="get",
|
|
31
|
-
help=
|
|
30
|
+
help="Query the value of a Ruyi config option",
|
|
32
31
|
):
|
|
33
32
|
@classmethod
|
|
34
33
|
def configure_args(
|
|
@@ -39,7 +38,7 @@ class ConfigGetCommand(
|
|
|
39
38
|
p.add_argument(
|
|
40
39
|
"key",
|
|
41
40
|
type=str,
|
|
42
|
-
help=
|
|
41
|
+
help="The Ruyi config option to query",
|
|
43
42
|
)
|
|
44
43
|
|
|
45
44
|
@classmethod
|
|
@@ -67,7 +66,7 @@ class ConfigGetCommand(
|
|
|
67
66
|
class ConfigSetCommand(
|
|
68
67
|
ConfigCommand,
|
|
69
68
|
cmd="set",
|
|
70
|
-
help=
|
|
69
|
+
help="Set the value of a Ruyi config option",
|
|
71
70
|
):
|
|
72
71
|
@classmethod
|
|
73
72
|
def configure_args(
|
|
@@ -78,12 +77,12 @@ class ConfigSetCommand(
|
|
|
78
77
|
p.add_argument(
|
|
79
78
|
"key",
|
|
80
79
|
type=str,
|
|
81
|
-
help=
|
|
80
|
+
help="The Ruyi config option to set",
|
|
82
81
|
)
|
|
83
82
|
p.add_argument(
|
|
84
83
|
"value",
|
|
85
84
|
type=str,
|
|
86
|
-
help=
|
|
85
|
+
help="The value to set the option to",
|
|
87
86
|
)
|
|
88
87
|
|
|
89
88
|
@classmethod
|
|
@@ -101,9 +100,7 @@ class ConfigSetCommand(
|
|
|
101
100
|
ed.set_value(key, pyval)
|
|
102
101
|
except ProtectedGlobalConfigError:
|
|
103
102
|
cfg.logger.F(
|
|
104
|
-
|
|
105
|
-
"the config [yellow]{key}[/] is protected and not meant to be overridden by users"
|
|
106
|
-
).format(key=key)
|
|
103
|
+
f"the config [yellow]{key}[/] is protected and not meant to be overridden by users",
|
|
107
104
|
)
|
|
108
105
|
return 2
|
|
109
106
|
|
|
@@ -115,7 +112,7 @@ class ConfigSetCommand(
|
|
|
115
112
|
class ConfigUnsetCommand(
|
|
116
113
|
ConfigCommand,
|
|
117
114
|
cmd="unset",
|
|
118
|
-
help=
|
|
115
|
+
help="Unset a Ruyi config option",
|
|
119
116
|
):
|
|
120
117
|
@classmethod
|
|
121
118
|
def configure_args(
|
|
@@ -126,7 +123,7 @@ class ConfigUnsetCommand(
|
|
|
126
123
|
p.add_argument(
|
|
127
124
|
"key",
|
|
128
125
|
type=str,
|
|
129
|
-
help=
|
|
126
|
+
help="The Ruyi config option to unset",
|
|
130
127
|
)
|
|
131
128
|
|
|
132
129
|
@classmethod
|
|
@@ -145,7 +142,7 @@ class ConfigUnsetCommand(
|
|
|
145
142
|
class ConfigRemoveSectionCommand(
|
|
146
143
|
ConfigCommand,
|
|
147
144
|
cmd="remove-section",
|
|
148
|
-
help=
|
|
145
|
+
help="Remove a section from the Ruyi config",
|
|
149
146
|
):
|
|
150
147
|
@classmethod
|
|
151
148
|
def configure_args(
|
|
@@ -156,7 +153,7 @@ class ConfigRemoveSectionCommand(
|
|
|
156
153
|
p.add_argument(
|
|
157
154
|
"section",
|
|
158
155
|
type=str,
|
|
159
|
-
help=
|
|
156
|
+
help="The section to remove",
|
|
160
157
|
)
|
|
161
158
|
|
|
162
159
|
@classmethod
|
|
@@ -4,7 +4,6 @@ import sys
|
|
|
4
4
|
from typing import Final, TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from ..config import GlobalConfig
|
|
7
|
-
from ..i18n import _
|
|
8
7
|
from ..telemetry.scope import TelemetryScope
|
|
9
8
|
from ..utils.global_mode import GlobalModeProvider
|
|
10
9
|
from ..version import RUYI_SEMVER
|
|
@@ -51,19 +50,10 @@ def main(gm: GlobalModeProvider, gc: GlobalConfig, argv: list[str]) -> int:
|
|
|
51
50
|
if not is_called_as_ruyi(gm.argv0):
|
|
52
51
|
if should_prompt_for_renaming(gm.argv0):
|
|
53
52
|
logger.F(
|
|
54
|
-
|
|
55
|
-
"the {ruyi_exe} executable must be named [green]'{expected_name}'[/] to work"
|
|
56
|
-
).format(
|
|
57
|
-
ruyi_exe=RUYI_ENTRYPOINT_NAME,
|
|
58
|
-
expected_name=RUYI_ENTRYPOINT_NAME,
|
|
59
|
-
)
|
|
53
|
+
f"the {RUYI_ENTRYPOINT_NAME} executable must be named [green]'{RUYI_ENTRYPOINT_NAME}'[/] to work"
|
|
60
54
|
)
|
|
61
|
-
logger.I(
|
|
62
|
-
|
|
63
|
-
current_name=gm.argv0,
|
|
64
|
-
)
|
|
65
|
-
)
|
|
66
|
-
logger.I(_("please rename the command file and retry"))
|
|
55
|
+
logger.I(f"it is now [yellow]'{gm.argv0}'[/]")
|
|
56
|
+
logger.I("please rename the command file and retry")
|
|
67
57
|
return 1
|
|
68
58
|
|
|
69
59
|
from ..mux.runtime import mux_main
|
|
@@ -125,7 +115,7 @@ def main(gm: GlobalModeProvider, gc: GlobalConfig, argv: list[str]) -> int:
|
|
|
125
115
|
try:
|
|
126
116
|
telemetry_key: str = args.tele_key
|
|
127
117
|
except AttributeError:
|
|
128
|
-
logger.F(
|
|
118
|
+
logger.F("internal error: CLI entrypoint was added without a telemetry key")
|
|
129
119
|
return 1
|
|
130
120
|
|
|
131
121
|
# Special-case the `--output-completion-script` argument; treat it as if
|
|
@@ -2,16 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
|
-
from typing import Callable,
|
|
6
|
-
|
|
7
|
-
from ..i18n import _, d_
|
|
5
|
+
from typing import Callable, TYPE_CHECKING
|
|
8
6
|
|
|
9
7
|
if TYPE_CHECKING:
|
|
10
8
|
from ..config import GlobalConfig
|
|
11
9
|
|
|
12
10
|
|
|
13
|
-
SHELL_AUTO_COMPLETION_TIP
|
|
14
|
-
"""
|
|
11
|
+
SHELL_AUTO_COMPLETION_TIP = """
|
|
15
12
|
[bold green]tip[/]: you can enable shell auto-completion for [yellow]ruyi[/] by adding the
|
|
16
13
|
following line to your [green]{shrc}[/], if you have not done so already:
|
|
17
14
|
|
|
@@ -21,7 +18,6 @@ You can do so by running the following command later:
|
|
|
21
18
|
|
|
22
19
|
[green]echo 'eval "$(ruyi --output-completion-script={shell})"' >> {shrc}[/]
|
|
23
20
|
"""
|
|
24
|
-
)
|
|
25
21
|
|
|
26
22
|
|
|
27
23
|
class OOBE:
|
|
@@ -78,7 +74,7 @@ class OOBE:
|
|
|
78
74
|
return
|
|
79
75
|
|
|
80
76
|
self._gc.logger.stdout(
|
|
81
|
-
|
|
77
|
+
SHELL_AUTO_COMPLETION_TIP.format(
|
|
82
78
|
shell=shell,
|
|
83
79
|
shrc=f"~/.{shell}rc",
|
|
84
80
|
)
|
|
@@ -4,16 +4,13 @@ import pathlib
|
|
|
4
4
|
import shutil
|
|
5
5
|
from typing import Final, TYPE_CHECKING
|
|
6
6
|
|
|
7
|
-
from ..i18n import _, d_
|
|
8
7
|
from .cmd import RootCommand
|
|
9
8
|
|
|
10
9
|
if TYPE_CHECKING:
|
|
11
10
|
from .completion import ArgumentParser
|
|
12
11
|
from .. import config
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
UNINSTALL_NOTICE: Final = d_(
|
|
16
|
-
"""
|
|
13
|
+
UNINSTALL_NOTICE: Final = """
|
|
17
14
|
[bold]Thanks for hacking with [yellow]Ruyi[/]![/]
|
|
18
15
|
|
|
19
16
|
This will uninstall [yellow]Ruyi[/] from your system, and optionally remove
|
|
@@ -24,7 +21,6 @@ Note that your [yellow]Ruyi[/] virtual environments [bold]will become unusable[/
|
|
|
24
21
|
[yellow]Ruyi[/] is uninstalled. You should take care of migrating or cleaning
|
|
25
22
|
them yourselves afterwards.
|
|
26
23
|
"""
|
|
27
|
-
)
|
|
28
24
|
|
|
29
25
|
|
|
30
26
|
# Self-management commands
|
|
@@ -32,7 +28,7 @@ class SelfCommand(
|
|
|
32
28
|
RootCommand,
|
|
33
29
|
cmd="self",
|
|
34
30
|
has_subcommands=True,
|
|
35
|
-
help=
|
|
31
|
+
help="Manage this Ruyi installation",
|
|
36
32
|
):
|
|
37
33
|
@classmethod
|
|
38
34
|
def configure_args(
|
|
@@ -46,7 +42,7 @@ class SelfCommand(
|
|
|
46
42
|
class SelfCleanCommand(
|
|
47
43
|
SelfCommand,
|
|
48
44
|
cmd="clean",
|
|
49
|
-
help=
|
|
45
|
+
help="Remove various Ruyi-managed data to reclaim storage",
|
|
50
46
|
):
|
|
51
47
|
@classmethod
|
|
52
48
|
def configure_args(
|
|
@@ -58,42 +54,42 @@ class SelfCleanCommand(
|
|
|
58
54
|
"--quiet",
|
|
59
55
|
"-q",
|
|
60
56
|
action="store_true",
|
|
61
|
-
help=
|
|
57
|
+
help="Do not print out the actions being performed",
|
|
62
58
|
)
|
|
63
59
|
p.add_argument(
|
|
64
60
|
"--all",
|
|
65
61
|
action="store_true",
|
|
66
|
-
help=
|
|
62
|
+
help="Remove all covered data",
|
|
67
63
|
)
|
|
68
64
|
p.add_argument(
|
|
69
65
|
"--distfiles",
|
|
70
66
|
action="store_true",
|
|
71
|
-
help=
|
|
67
|
+
help="Remove all downloaded distfiles if any",
|
|
72
68
|
)
|
|
73
69
|
p.add_argument(
|
|
74
70
|
"--installed-pkgs",
|
|
75
71
|
action="store_true",
|
|
76
|
-
help=
|
|
72
|
+
help="Remove all installed packages if any",
|
|
77
73
|
)
|
|
78
74
|
p.add_argument(
|
|
79
75
|
"--news-read-status",
|
|
80
76
|
action="store_true",
|
|
81
|
-
help=
|
|
77
|
+
help="Mark all news items as unread",
|
|
82
78
|
)
|
|
83
79
|
p.add_argument(
|
|
84
80
|
"--progcache",
|
|
85
81
|
action="store_true",
|
|
86
|
-
help=
|
|
82
|
+
help="Clear the Ruyi program cache",
|
|
87
83
|
)
|
|
88
84
|
p.add_argument(
|
|
89
85
|
"--repo",
|
|
90
86
|
action="store_true",
|
|
91
|
-
help=
|
|
87
|
+
help="Remove the Ruyi repo if located in Ruyi-managed cache directory",
|
|
92
88
|
)
|
|
93
89
|
p.add_argument(
|
|
94
90
|
"--telemetry",
|
|
95
91
|
action="store_true",
|
|
96
|
-
help=
|
|
92
|
+
help="Remove all telemetry data recorded if any",
|
|
97
93
|
)
|
|
98
94
|
|
|
99
95
|
@classmethod
|
|
@@ -126,11 +122,9 @@ class SelfCleanCommand(
|
|
|
126
122
|
telemetry,
|
|
127
123
|
]
|
|
128
124
|
):
|
|
129
|
-
logger.F(
|
|
125
|
+
logger.F("no data specified for cleaning")
|
|
130
126
|
logger.I(
|
|
131
|
-
|
|
132
|
-
"please check [yellow]ruyi self clean --help[/] for a list of cleanable data"
|
|
133
|
-
)
|
|
127
|
+
"please check [yellow]ruyi self clean --help[/] for a list of cleanable data"
|
|
134
128
|
)
|
|
135
129
|
return 1
|
|
136
130
|
|
|
@@ -155,7 +149,7 @@ class SelfCleanCommand(
|
|
|
155
149
|
class SelfUninstallCommand(
|
|
156
150
|
SelfCommand,
|
|
157
151
|
cmd="uninstall",
|
|
158
|
-
help=
|
|
152
|
+
help="Uninstall Ruyi",
|
|
159
153
|
):
|
|
160
154
|
@classmethod
|
|
161
155
|
def configure_args(
|
|
@@ -166,15 +160,13 @@ class SelfUninstallCommand(
|
|
|
166
160
|
p.add_argument(
|
|
167
161
|
"--purge",
|
|
168
162
|
action="store_true",
|
|
169
|
-
help=
|
|
163
|
+
help="Remove all installed packages and Ruyi-managed remote repo data",
|
|
170
164
|
)
|
|
171
165
|
p.add_argument(
|
|
172
166
|
"-y",
|
|
173
167
|
action="store_true",
|
|
174
168
|
dest="consent",
|
|
175
|
-
help=
|
|
176
|
-
"Give consent for uninstallation on CLI; do not ask for confirmation"
|
|
177
|
-
),
|
|
169
|
+
help="Give consent for uninstallation on CLI; do not ask for confirmation",
|
|
178
170
|
)
|
|
179
171
|
|
|
180
172
|
@classmethod
|
|
@@ -188,28 +180,24 @@ class SelfUninstallCommand(
|
|
|
188
180
|
|
|
189
181
|
if cfg.is_installation_externally_managed:
|
|
190
182
|
logger.F(
|
|
191
|
-
|
|
192
|
-
"this [yellow]ruyi[/] is externally managed, for example, by the system package manager, and cannot be uninstalled this way"
|
|
193
|
-
)
|
|
183
|
+
"this [yellow]ruyi[/] is externally managed, for example, by the system package manager, and cannot be uninstalled this way"
|
|
194
184
|
)
|
|
195
|
-
logger.I(
|
|
185
|
+
logger.I("please uninstall via the external manager instead")
|
|
196
186
|
return 1
|
|
197
187
|
|
|
198
188
|
if not cfg.is_packaged:
|
|
199
189
|
logger.F(
|
|
200
|
-
|
|
201
|
-
"this [yellow]ruyi[/] is not in standalone form, and cannot be uninstalled this way"
|
|
202
|
-
)
|
|
190
|
+
"this [yellow]ruyi[/] is not in standalone form, and cannot be uninstalled this way"
|
|
203
191
|
)
|
|
204
192
|
return 1
|
|
205
193
|
|
|
206
194
|
if not consent:
|
|
207
|
-
logger.stdout(
|
|
208
|
-
if not user_input.ask_for_yesno_confirmation(logger,
|
|
209
|
-
logger.I(
|
|
195
|
+
logger.stdout(UNINSTALL_NOTICE)
|
|
196
|
+
if not user_input.ask_for_yesno_confirmation(logger, "Continue?"):
|
|
197
|
+
logger.I("aborting uninstallation")
|
|
210
198
|
return 0
|
|
211
199
|
else:
|
|
212
|
-
logger.I(
|
|
200
|
+
logger.I("uninstallation consent given over CLI, proceeding")
|
|
213
201
|
|
|
214
202
|
_do_reset(
|
|
215
203
|
cfg,
|
|
@@ -220,7 +208,7 @@ class SelfUninstallCommand(
|
|
|
220
208
|
self_binary=True,
|
|
221
209
|
)
|
|
222
210
|
|
|
223
|
-
logger.I(
|
|
211
|
+
logger.I("[yellow]ruyi[/] is uninstalled")
|
|
224
212
|
|
|
225
213
|
return 0
|
|
226
214
|
|
|
@@ -247,7 +235,7 @@ def _do_reset(
|
|
|
247
235
|
logger.I(s)
|
|
248
236
|
|
|
249
237
|
if installed_pkgs:
|
|
250
|
-
status(
|
|
238
|
+
status("removing installed packages")
|
|
251
239
|
shutil.rmtree(cfg.data_root, True)
|
|
252
240
|
cfg.ruyipkg_global_state.purge_installation_info()
|
|
253
241
|
|
|
@@ -256,28 +244,28 @@ def _do_reset(
|
|
|
256
244
|
cfg.telemetry.discard_events(True)
|
|
257
245
|
|
|
258
246
|
if all_state:
|
|
259
|
-
status(
|
|
247
|
+
status("removing state data")
|
|
260
248
|
shutil.rmtree(cfg.state_root, True)
|
|
261
249
|
else:
|
|
262
250
|
if news_read_status:
|
|
263
|
-
status(
|
|
251
|
+
status("removing read status of news items")
|
|
264
252
|
cfg.news_read_status.remove()
|
|
265
253
|
|
|
266
254
|
if telemetry:
|
|
267
|
-
status(
|
|
255
|
+
status("removing all telemetry data")
|
|
268
256
|
shutil.rmtree(cfg.telemetry_root, True)
|
|
269
257
|
|
|
270
258
|
if all_cache:
|
|
271
|
-
status(
|
|
259
|
+
status("removing cached data")
|
|
272
260
|
shutil.rmtree(cfg.cache_root, True)
|
|
273
261
|
else:
|
|
274
262
|
if distfiles:
|
|
275
|
-
status(
|
|
263
|
+
status("removing downloaded distfiles")
|
|
276
264
|
# TODO: deduplicate the path derivation
|
|
277
265
|
shutil.rmtree(os.path.join(cfg.cache_root, "distfiles"), True)
|
|
278
266
|
|
|
279
267
|
if progcache:
|
|
280
|
-
status(
|
|
268
|
+
status("clearing the Ruyi program cache")
|
|
281
269
|
# TODO: deduplicate the path derivation
|
|
282
270
|
shutil.rmtree(os.path.join(cfg.cache_root, "progcache"), True)
|
|
283
271
|
|
|
@@ -295,16 +283,14 @@ def _do_reset(
|
|
|
295
283
|
|
|
296
284
|
if not repo_is_below_cache_root:
|
|
297
285
|
logger.W(
|
|
298
|
-
|
|
299
|
-
"not removing the Ruyi repo: it is outside of the Ruyi cache directory"
|
|
300
|
-
)
|
|
286
|
+
"not removing the Ruyi repo: it is outside of the Ruyi cache directory"
|
|
301
287
|
)
|
|
302
288
|
else:
|
|
303
|
-
status(
|
|
289
|
+
status("removing the Ruyi repo")
|
|
304
290
|
shutil.rmtree(repo_dir, True)
|
|
305
291
|
|
|
306
292
|
if self_binary:
|
|
307
|
-
status(
|
|
293
|
+
status("removing the ruyi binary")
|
|
308
294
|
try:
|
|
309
295
|
os.unlink(cfg.self_exe)
|
|
310
296
|
except FileNotFoundError:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import os.path
|
|
2
2
|
|
|
3
|
-
from ..i18n import _
|
|
4
3
|
from ..log import RuyiLogger
|
|
5
4
|
|
|
6
5
|
|
|
@@ -11,7 +10,7 @@ def pause_before_continuing(
|
|
|
11
10
|
|
|
12
11
|
EOFError should be handled by the caller."""
|
|
13
12
|
|
|
14
|
-
logger.stdout(
|
|
13
|
+
logger.stdout("Press [green]<ENTER>[/] to continue: ", end="")
|
|
15
14
|
input()
|
|
16
15
|
|
|
17
16
|
|
|
@@ -27,11 +26,9 @@ def ask_for_yesno_confirmation(
|
|
|
27
26
|
logger.stdout(f"{prompt} {choices_help} ", end="")
|
|
28
27
|
user_input = input()
|
|
29
28
|
except EOFError:
|
|
30
|
-
yesno =
|
|
29
|
+
yesno = "YES" if default else "NO"
|
|
31
30
|
logger.W(
|
|
32
|
-
|
|
33
|
-
"EOF while reading user input, assuming the default choice {yesno}"
|
|
34
|
-
).format(yesno=yesno)
|
|
31
|
+
f"EOF while reading user input, assuming the default choice {yesno}"
|
|
35
32
|
)
|
|
36
33
|
return default
|
|
37
34
|
|
|
@@ -42,12 +39,8 @@ def ask_for_yesno_confirmation(
|
|
|
42
39
|
if user_input in {"N", "n", "no"}:
|
|
43
40
|
return False
|
|
44
41
|
else:
|
|
45
|
-
logger.stdout(
|
|
46
|
-
|
|
47
|
-
user_input=user_input
|
|
48
|
-
)
|
|
49
|
-
)
|
|
50
|
-
logger.stdout(_("Accepted choices: Y/y/yes for YES, N/n/no for NO."))
|
|
42
|
+
logger.stdout(f"Unrecognized input [yellow]'{user_input}'[/].")
|
|
43
|
+
logger.stdout("Accepted choices: Y/y/yes for YES, N/n/no for NO.")
|
|
51
44
|
|
|
52
45
|
|
|
53
46
|
def ask_for_kv_choice(
|
|
@@ -88,19 +81,12 @@ def ask_for_choice(
|
|
|
88
81
|
if default_idx is not None:
|
|
89
82
|
if not (0 <= default_idx < nr_choices):
|
|
90
83
|
raise ValueError(f"Default choice index {default_idx} out of range")
|
|
91
|
-
choices_help =
|
|
92
|
-
nr_choices=nr_choices,
|
|
93
|
-
default=default_idx + 1,
|
|
94
|
-
)
|
|
84
|
+
choices_help = f"(1-{nr_choices}, default {default_idx + 1})"
|
|
95
85
|
else:
|
|
96
|
-
choices_help =
|
|
86
|
+
choices_help = f"(1-{nr_choices})"
|
|
97
87
|
while True:
|
|
98
88
|
try:
|
|
99
|
-
user_input = input(
|
|
100
|
-
_("Choice? {choices_help} ").format(
|
|
101
|
-
choices_help=choices_help,
|
|
102
|
-
)
|
|
103
|
-
)
|
|
89
|
+
user_input = input(f"Choice? {choices_help} ")
|
|
104
90
|
except EOFError:
|
|
105
91
|
raise ValueError("EOF while reading user choice")
|
|
106
92
|
|
|
@@ -110,34 +96,18 @@ def ask_for_choice(
|
|
|
110
96
|
try:
|
|
111
97
|
choice_int = int(user_input)
|
|
112
98
|
except ValueError:
|
|
99
|
+
logger.stdout(f"Unrecognized input [yellow]'{user_input}'[/].")
|
|
113
100
|
logger.stdout(
|
|
114
|
-
|
|
115
|
-
user_input=user_input,
|
|
116
|
-
)
|
|
117
|
-
)
|
|
118
|
-
logger.stdout(
|
|
119
|
-
_(
|
|
120
|
-
"Accepted choices: an integer number from 1 to {nr_choices} inclusive."
|
|
121
|
-
).format(
|
|
122
|
-
nr_choices=nr_choices,
|
|
123
|
-
)
|
|
101
|
+
f"Accepted choices: an integer number from 1 to {nr_choices} inclusive."
|
|
124
102
|
)
|
|
125
103
|
continue
|
|
126
104
|
|
|
127
105
|
if 1 <= choice_int <= nr_choices:
|
|
128
106
|
return choice_int - 1
|
|
129
107
|
|
|
108
|
+
logger.stdout(f"Out-of-range input [yellow]'{user_input}'[/].")
|
|
130
109
|
logger.stdout(
|
|
131
|
-
|
|
132
|
-
user_input=user_input,
|
|
133
|
-
)
|
|
134
|
-
)
|
|
135
|
-
logger.stdout(
|
|
136
|
-
_(
|
|
137
|
-
"Accepted choices: an integer number from 1 to {nr_choices} inclusive."
|
|
138
|
-
).format(
|
|
139
|
-
nr_choices=nr_choices,
|
|
140
|
-
)
|
|
110
|
+
f"Accepted choices: an integer number from 1 to {nr_choices} inclusive."
|
|
141
111
|
)
|
|
142
112
|
|
|
143
113
|
|