multi-lang-build 0.2.5__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.
- multi_lang_build/__init__.py +64 -0
- multi_lang_build/cli.py +320 -0
- multi_lang_build/compiler/__init__.py +22 -0
- multi_lang_build/compiler/base.py +309 -0
- multi_lang_build/compiler/go.py +468 -0
- multi_lang_build/compiler/pnpm.py +481 -0
- multi_lang_build/compiler/python.py +539 -0
- multi_lang_build/mirror/__init__.py +21 -0
- multi_lang_build/mirror/cli.py +340 -0
- multi_lang_build/mirror/config.py +251 -0
- multi_lang_build/py.typed +2 -0
- multi_lang_build/register.py +412 -0
- multi_lang_build/types.py +43 -0
- multi_lang_build-0.2.5.dist-info/METADATA +402 -0
- multi_lang_build-0.2.5.dist-info/RECORD +18 -0
- multi_lang_build-0.2.5.dist-info/WHEEL +4 -0
- multi_lang_build-0.2.5.dist-info/entry_points.txt +7 -0
- multi_lang_build-0.2.5.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
"""Mirror configuration CLI for domestic acceleration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Literal
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_all_mirrors() -> dict:
|
|
14
|
+
"""Get all available mirrors with their configurations."""
|
|
15
|
+
from multi_lang_build.mirror.config import MIRROR_CONFIGS
|
|
16
|
+
|
|
17
|
+
mirrors = {}
|
|
18
|
+
for key, config in MIRROR_CONFIGS.items():
|
|
19
|
+
mirrors[key] = {
|
|
20
|
+
"name": config["name"],
|
|
21
|
+
"url": config["url"],
|
|
22
|
+
}
|
|
23
|
+
return mirrors
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def print_mirrors() -> None:
|
|
27
|
+
"""Print all available mirrors."""
|
|
28
|
+
mirrors = get_all_mirrors()
|
|
29
|
+
|
|
30
|
+
print("\nš¦ Available Mirrors:")
|
|
31
|
+
print("-" * 60)
|
|
32
|
+
|
|
33
|
+
# Group by category
|
|
34
|
+
categories = {
|
|
35
|
+
"js": ["npm", "pnpm", "yarn"],
|
|
36
|
+
"go": ["go", "go_qiniu", "go_vip"],
|
|
37
|
+
"python": ["pip", "pip_aliyun", "pip_douban", "pip_huawei", "python", "poetry"],
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
category_names = {
|
|
41
|
+
"js": "š JavaScript (npm/pnpm/yarn)",
|
|
42
|
+
"go": "š· Go",
|
|
43
|
+
"python": "š Python (pip/PyPI)",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
for cat_key, cat_mirrors in categories.items():
|
|
47
|
+
print(f"\n{category_names.get(cat_key, cat_key)}")
|
|
48
|
+
for mirror_key in cat_mirrors:
|
|
49
|
+
if mirror_key in mirrors:
|
|
50
|
+
config = mirrors[mirror_key]
|
|
51
|
+
print(f" ⢠{mirror_key:12} - {config['name']}")
|
|
52
|
+
print(f" {config['url']}")
|
|
53
|
+
|
|
54
|
+
print()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def configure_pip(mirror_key: str) -> bool:
|
|
58
|
+
"""Configure pip mirror using pip config command."""
|
|
59
|
+
from multi_lang_build.mirror.config import get_mirror_config
|
|
60
|
+
|
|
61
|
+
config = get_mirror_config(mirror_key)
|
|
62
|
+
if config is None:
|
|
63
|
+
print(f"ā Unknown pip mirror: {mirror_key}")
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
url = config["url"]
|
|
67
|
+
if not url.endswith("/simple") and not url.endswith("/simple/"):
|
|
68
|
+
url = f"{url}/simple"
|
|
69
|
+
|
|
70
|
+
# Try pip3 first, fallback to pip
|
|
71
|
+
pip_cmd = "pip3" if sys.platform != "win32" else "pip"
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
subprocess.run(
|
|
75
|
+
[pip_cmd, "config", "set", "global.index-url", url],
|
|
76
|
+
check=True,
|
|
77
|
+
)
|
|
78
|
+
print(f"ā
pip mirror set to: {url}")
|
|
79
|
+
return True
|
|
80
|
+
except subprocess.CalledProcessError as e:
|
|
81
|
+
print(f"ā Failed to set pip mirror: {e}")
|
|
82
|
+
return False
|
|
83
|
+
except FileNotFoundError:
|
|
84
|
+
# Try alternative
|
|
85
|
+
try:
|
|
86
|
+
alternative = "pip" if pip_cmd == "pip3" else "pip3"
|
|
87
|
+
subprocess.run(
|
|
88
|
+
[alternative, "config", "set", "global.index-url", url],
|
|
89
|
+
check=True,
|
|
90
|
+
)
|
|
91
|
+
print(f"ā
pip mirror set to: {url}")
|
|
92
|
+
return True
|
|
93
|
+
except Exception:
|
|
94
|
+
print("ā pip/pip3 not found")
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def configure_go(mirror_key: str) -> bool:
|
|
99
|
+
"""Configure Go proxy using go env -w."""
|
|
100
|
+
from multi_lang_build.mirror.config import get_mirror_config
|
|
101
|
+
|
|
102
|
+
config = get_mirror_config(mirror_key)
|
|
103
|
+
if config is None:
|
|
104
|
+
print(f"ā Unknown Go mirror: {mirror_key}")
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
# Get the GOPROXY value from environment variables
|
|
108
|
+
proxy_value = config["environment_variables"].get("GOPROXY", f"{config['url']},direct")
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
subprocess.run(
|
|
112
|
+
["go", "env", "-w", f"GOPROXY={proxy_value}"],
|
|
113
|
+
check=True,
|
|
114
|
+
)
|
|
115
|
+
print(f"ā
Go GOPROXY set to: {proxy_value}")
|
|
116
|
+
|
|
117
|
+
# Also set GOSUMDB if present
|
|
118
|
+
gosumdb = config["environment_variables"].get("GOSUMDB")
|
|
119
|
+
if gosumdb:
|
|
120
|
+
subprocess.run(
|
|
121
|
+
["go", "env", "-w", f"GOSUMDB={gosumdb}"],
|
|
122
|
+
check=True,
|
|
123
|
+
)
|
|
124
|
+
print(f"ā
Go GOSUMDB set to: {gosumdb}")
|
|
125
|
+
|
|
126
|
+
return True
|
|
127
|
+
except subprocess.CalledProcessError as e:
|
|
128
|
+
print(f"ā Failed to set Go mirror: {e}")
|
|
129
|
+
return False
|
|
130
|
+
except FileNotFoundError:
|
|
131
|
+
print("ā go not found")
|
|
132
|
+
return False
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def configure_npm(mirror_key: str) -> bool:
|
|
136
|
+
"""Configure npm/pnpm registry."""
|
|
137
|
+
from multi_lang_build.mirror.config import get_mirror_config
|
|
138
|
+
|
|
139
|
+
config = get_mirror_config(mirror_key)
|
|
140
|
+
if config is None:
|
|
141
|
+
print(f"ā Unknown npm mirror: {mirror_key}")
|
|
142
|
+
return False
|
|
143
|
+
|
|
144
|
+
url = config["url"]
|
|
145
|
+
|
|
146
|
+
try:
|
|
147
|
+
subprocess.run(
|
|
148
|
+
["npm", "config", "set", "registry", url],
|
|
149
|
+
check=True,
|
|
150
|
+
)
|
|
151
|
+
print(f"ā
npm registry set to: {url}")
|
|
152
|
+
|
|
153
|
+
# Also set for pnpm if available
|
|
154
|
+
try:
|
|
155
|
+
subprocess.run(
|
|
156
|
+
["pnpm", "config", "set", "registry", url],
|
|
157
|
+
check=True,
|
|
158
|
+
)
|
|
159
|
+
print(f"ā
pnpm registry set to: {url}")
|
|
160
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
161
|
+
pass
|
|
162
|
+
|
|
163
|
+
return True
|
|
164
|
+
except subprocess.CalledProcessError as e:
|
|
165
|
+
print(f"ā Failed to set npm registry: {e}")
|
|
166
|
+
return False
|
|
167
|
+
except FileNotFoundError:
|
|
168
|
+
print("ā npm not found")
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def get_current_config() -> dict:
|
|
173
|
+
"""Get current mirror configuration."""
|
|
174
|
+
config = {}
|
|
175
|
+
|
|
176
|
+
# Try pip3 first, fallback to pip
|
|
177
|
+
pip_cmd = "pip3" if sys.platform != "win32" else "pip"
|
|
178
|
+
|
|
179
|
+
try:
|
|
180
|
+
result = subprocess.run(
|
|
181
|
+
[pip_cmd, "config", "get", "global.index-url"],
|
|
182
|
+
capture_output=True,
|
|
183
|
+
text=True,
|
|
184
|
+
)
|
|
185
|
+
if result.returncode == 0 and result.stdout.strip():
|
|
186
|
+
config["pip"] = result.stdout.strip()
|
|
187
|
+
except Exception:
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
# Check Go
|
|
191
|
+
try:
|
|
192
|
+
result = subprocess.run(
|
|
193
|
+
["go", "env", "GOPROXY"],
|
|
194
|
+
capture_output=True,
|
|
195
|
+
text=True,
|
|
196
|
+
)
|
|
197
|
+
if result.returncode == 0:
|
|
198
|
+
config["go"] = result.stdout.strip()
|
|
199
|
+
except Exception:
|
|
200
|
+
pass
|
|
201
|
+
|
|
202
|
+
# Check npm
|
|
203
|
+
try:
|
|
204
|
+
result = subprocess.run(
|
|
205
|
+
["npm", "config", "get", "registry"],
|
|
206
|
+
capture_output=True,
|
|
207
|
+
text=True,
|
|
208
|
+
)
|
|
209
|
+
if result.returncode == 0:
|
|
210
|
+
config["npm"] = result.stdout.strip()
|
|
211
|
+
except Exception:
|
|
212
|
+
pass
|
|
213
|
+
|
|
214
|
+
return config
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def configure_mirror(mirror_type: str, mirror_key: str) -> bool:
|
|
218
|
+
"""Configure mirror for a specific package manager.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
mirror_type: Package manager type (pip, go, npm)
|
|
222
|
+
mirror_key: Mirror key to use
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
True if successful, False otherwise
|
|
226
|
+
"""
|
|
227
|
+
if mirror_type == "pip":
|
|
228
|
+
return configure_pip(mirror_key)
|
|
229
|
+
elif mirror_type == "go":
|
|
230
|
+
return configure_go(mirror_key)
|
|
231
|
+
elif mirror_type in ["npm", "pnpm"]:
|
|
232
|
+
return configure_npm(mirror_key)
|
|
233
|
+
else:
|
|
234
|
+
print(f"ā Unknown package manager: {mirror_type}")
|
|
235
|
+
return False
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def mirror_main():
|
|
239
|
+
"""Main entry point for mirror command."""
|
|
240
|
+
import argparse
|
|
241
|
+
|
|
242
|
+
parser = argparse.ArgumentParser(
|
|
243
|
+
description="Configure domestic mirror acceleration",
|
|
244
|
+
epilog="""
|
|
245
|
+
Examples:
|
|
246
|
+
%(prog)s list List all available mirrors
|
|
247
|
+
%(prog)s set pip Configure pip mirror (default)
|
|
248
|
+
%(prog)s set go Configure Go proxy
|
|
249
|
+
%(prog)s set npm Configure npm registry
|
|
250
|
+
%(prog)s show Show current configuration
|
|
251
|
+
""",
|
|
252
|
+
)
|
|
253
|
+
parser.add_argument(
|
|
254
|
+
"--version",
|
|
255
|
+
action="version",
|
|
256
|
+
version="%(prog)s 0.2.2",
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
subparsers = parser.add_subparsers(dest="command", help="Commands")
|
|
260
|
+
|
|
261
|
+
# list command
|
|
262
|
+
list_parser = subparsers.add_parser("list", help="List available mirrors")
|
|
263
|
+
list_parser.add_argument(
|
|
264
|
+
"--json",
|
|
265
|
+
action="store_true",
|
|
266
|
+
help="Output as JSON",
|
|
267
|
+
)
|
|
268
|
+
list_parser.add_argument(
|
|
269
|
+
"--type",
|
|
270
|
+
type=str,
|
|
271
|
+
choices=["pip", "go", "npm"],
|
|
272
|
+
help="Filter by type",
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
# set command
|
|
276
|
+
set_parser = subparsers.add_parser("set", help="Configure mirror")
|
|
277
|
+
set_parser.add_argument(
|
|
278
|
+
"type",
|
|
279
|
+
type=str,
|
|
280
|
+
default="pip",
|
|
281
|
+
nargs="?",
|
|
282
|
+
choices=["pip", "go", "npm", "pnpm"],
|
|
283
|
+
help="Package manager type (default: pip)",
|
|
284
|
+
)
|
|
285
|
+
set_parser.add_argument(
|
|
286
|
+
"mirror",
|
|
287
|
+
type=str,
|
|
288
|
+
nargs="?",
|
|
289
|
+
default="pip",
|
|
290
|
+
help="Mirror to use",
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
# show command
|
|
294
|
+
show_parser = subparsers.add_parser("show", help="Show current mirror configuration")
|
|
295
|
+
|
|
296
|
+
args = parser.parse_args()
|
|
297
|
+
|
|
298
|
+
if args.command == "list":
|
|
299
|
+
mirrors = get_all_mirrors()
|
|
300
|
+
if getattr(args, "json", False):
|
|
301
|
+
print(json.dumps(mirrors, indent=2, ensure_ascii=False))
|
|
302
|
+
else:
|
|
303
|
+
print_mirrors()
|
|
304
|
+
|
|
305
|
+
elif args.command == "set":
|
|
306
|
+
mirror_type = args.type
|
|
307
|
+
mirror_key = args.mirror
|
|
308
|
+
success = configure_mirror(mirror_type, mirror_key)
|
|
309
|
+
sys.exit(0 if success else 1)
|
|
310
|
+
|
|
311
|
+
elif args.command == "show":
|
|
312
|
+
config = get_current_config()
|
|
313
|
+
if config:
|
|
314
|
+
print("\nš¦ Current Mirror Configuration:")
|
|
315
|
+
print("-" * 40)
|
|
316
|
+
for key, value in config.items():
|
|
317
|
+
print(f" ⢠{key}: {value}")
|
|
318
|
+
print()
|
|
319
|
+
else:
|
|
320
|
+
print("\nš¦ No mirror configured")
|
|
321
|
+
print(" Run 'multi-lang-build mirror set <type> <mirror>' to configure")
|
|
322
|
+
print()
|
|
323
|
+
print_mirrors()
|
|
324
|
+
|
|
325
|
+
else:
|
|
326
|
+
# No subcommand, show help
|
|
327
|
+
parser.print_help()
|
|
328
|
+
print("\nš Commands:")
|
|
329
|
+
print(" list List all available mirrors")
|
|
330
|
+
print(" set <type> <name> Configure mirror (type: pip/go/npm)")
|
|
331
|
+
print(" show Show current configuration")
|
|
332
|
+
print("\nš Examples:")
|
|
333
|
+
print(" multi-lang-build mirror list")
|
|
334
|
+
print(" multi-lang-build mirror set pip")
|
|
335
|
+
print(" multi-lang-build mirror set go")
|
|
336
|
+
print(" multi-lang-build mirror set npm")
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
if __name__ == "__main__":
|
|
340
|
+
mirror_main()
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"""Mirror configuration for domestic acceleration."""
|
|
2
|
+
|
|
3
|
+
from typing import TypedDict, Literal
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# ============================================================================
|
|
8
|
+
# Constants for mainstream domestic mirrors
|
|
9
|
+
# ============================================================================
|
|
10
|
+
|
|
11
|
+
# NPM/PNPM mirrors
|
|
12
|
+
NPM_REGISTRY_NPMMIRROR: Literal["https://registry.npmmirror.com"] = "https://registry.npmmirror.com"
|
|
13
|
+
NPM_REGISTRY_TAOBAO: Literal["https://registry.npmmirror.com"] = "https://registry.npmmirror.com" # Taobao mirrors npmmirror
|
|
14
|
+
|
|
15
|
+
# Go mirrors (including Qiniu cloud)
|
|
16
|
+
GO_PROXY_GOPROXY_CN: Literal["https://goproxy.cn"] = "https://goproxy.cn"
|
|
17
|
+
GO_PROXY_GOPROXY_IO: Literal["https://goproxy.io"] = "https://goproxy.io"
|
|
18
|
+
GO_PROXY_GOVIP_CN: Literal["https://goproxy.vip.cn"] = "https://goproxy.vip.cn"
|
|
19
|
+
GO_PROXY_FASTGOPROXY: Literal["https://goproxy.cn,direct"] = "https://goproxy.cn,direct"
|
|
20
|
+
|
|
21
|
+
# Go sumdb mirrors
|
|
22
|
+
GO_SUMDB_GOLANG: Literal["sum.golang.org"] = "sum.golang.org"
|
|
23
|
+
GO_SUMDB_GOLANG_GOOGLE_CN: Literal["sum.golang.google.cn"] = "sum.golang.google.cn"
|
|
24
|
+
|
|
25
|
+
# PyPI/Pip mirrors
|
|
26
|
+
PYPI_MIRROR_TSINGHUA: Literal["https://pypi.tuna.tsinghua.edu.cn"] = "https://pypi.tuna.tsinghua.edu.cn"
|
|
27
|
+
PYPI_MIRROR_ALIYUN: Literal["https://mirrors.aliyun.com/pypi/simple"] = "https://mirrors.aliyun.com/pypi/simple"
|
|
28
|
+
PYPI_MIRROR_DOUBAN: Literal["https://pypi.doubanio.com/simple"] = "https://pypi.doubanio.com/simple"
|
|
29
|
+
PYPI_MIRROR_HUAWEI: Literal["https://repo.huaweicloud.com/repository/pypi/simple"] = "https://repo.huaweicloud.com/repository/pypi/simple"
|
|
30
|
+
PYPI_MIRROR_NETEASE: Literal["https://mirrors.163.com/pypi/simple"] = "https://mirrors.163.com/pypi/simple"
|
|
31
|
+
PYPI_MIRROR_SAU: Literal["https://pypi.sau.edu.cn/simple"] = "https://pypi.sau.edu.cn/simple"
|
|
32
|
+
|
|
33
|
+
# Poetry mirrors (uses same PyPI mirrors)
|
|
34
|
+
POETRY_REPO_TSINGHUA: Literal["https://pypi.tuna.tsinghua.edu.cn/simple"] = "https://pypi.tuna.tsinghua.edu.cn/simple"
|
|
35
|
+
POETRY_REPO_ALIYUN: Literal["https://mirrors.aliyun.com/pypi/simple"] = "https://mirrors.aliyun.com/pypi/simple"
|
|
36
|
+
|
|
37
|
+
# Default mirror selection
|
|
38
|
+
DEFAULT_GO_MIRROR: str = GO_PROXY_GOPROXY_CN
|
|
39
|
+
DEFAULT_PIP_MIRROR: str = PYPI_MIRROR_TSINGHUA
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class MirrorConfig(TypedDict):
|
|
43
|
+
"""Mirror configuration for package managers."""
|
|
44
|
+
name: str
|
|
45
|
+
url: str
|
|
46
|
+
environment_prefix: str
|
|
47
|
+
environment_variables: dict[str, str]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# Predefined mirror configurations for different package managers
|
|
51
|
+
MIRROR_CONFIGS: dict[str, MirrorConfig] = {
|
|
52
|
+
"npm": {
|
|
53
|
+
"name": "NPM China Mirror (npmmirror)",
|
|
54
|
+
"url": NPM_REGISTRY_NPMMIRROR,
|
|
55
|
+
"environment_prefix": "NPM",
|
|
56
|
+
"environment_variables": {
|
|
57
|
+
"NPM_CONFIG_REGISTRY": NPM_REGISTRY_NPMMIRROR,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
"pnpm": {
|
|
61
|
+
"name": "PNPM China Mirror (npmmirror)",
|
|
62
|
+
"url": NPM_REGISTRY_NPMMIRROR,
|
|
63
|
+
"environment_prefix": "PNPM",
|
|
64
|
+
"environment_variables": {
|
|
65
|
+
"PNPM_CONFIG_REGISTRY": NPM_REGISTRY_NPMMIRROR,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
"yarn": {
|
|
69
|
+
"name": "Yarn China Mirror (npmmirror)",
|
|
70
|
+
"url": NPM_REGISTRY_NPMMIRROR,
|
|
71
|
+
"environment_prefix": "YARN",
|
|
72
|
+
"environment_variables": {
|
|
73
|
+
"YARN_NPM_MIRROR": NPM_REGISTRY_NPMMIRROR,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
"go": {
|
|
77
|
+
"name": "Go China Mirror (goproxy.cn)",
|
|
78
|
+
"url": GO_PROXY_GOPROXY_CN,
|
|
79
|
+
"environment_prefix": "GOPROXY",
|
|
80
|
+
"environment_variables": {
|
|
81
|
+
"GOPROXY": f"{GO_PROXY_GOPROXY_CN},direct",
|
|
82
|
+
"GOSUMDB": GO_SUMDB_GOLANG_GOOGLE_CN,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
"go_qiniu": {
|
|
86
|
+
"name": "Go China Mirror (goproxy.io)",
|
|
87
|
+
"url": GO_PROXY_GOPROXY_IO,
|
|
88
|
+
"environment_prefix": "GOPROXY",
|
|
89
|
+
"environment_variables": {
|
|
90
|
+
"GOPROXY": f"{GO_PROXY_GOPROXY_IO},direct",
|
|
91
|
+
"GOSUMDB": GO_SUMDB_GOLANG_GOOGLE_CN,
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
"go_vip": {
|
|
95
|
+
"name": "Go China Mirror (goproxy.vip.cn)",
|
|
96
|
+
"url": GO_PROXY_GOVIP_CN,
|
|
97
|
+
"environment_prefix": "GOPROXY",
|
|
98
|
+
"environment_variables": {
|
|
99
|
+
"GOPROXY": f"{GO_PROXY_GOVIP_CN},direct",
|
|
100
|
+
"GOSUMDB": GO_SUMDB_GOLANG_GOOGLE_CN,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
"pip": {
|
|
104
|
+
"name": "Pip China Mirror (Tsinghua)",
|
|
105
|
+
"url": PYPI_MIRROR_TSINGHUA,
|
|
106
|
+
"environment_prefix": "PIP",
|
|
107
|
+
"environment_variables": {
|
|
108
|
+
"PIP_INDEX_URL": f"{PYPI_MIRROR_TSINGHUA}/simple",
|
|
109
|
+
"PIP_TRUSTED_HOST": "pypi.tuna.tsinghua.edu.cn",
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
"pip_aliyun": {
|
|
113
|
+
"name": "Pip China Mirror (Aliyun)",
|
|
114
|
+
"url": PYPI_MIRROR_ALIYUN,
|
|
115
|
+
"environment_prefix": "PIP",
|
|
116
|
+
"environment_variables": {
|
|
117
|
+
"PIP_INDEX_URL": f"{PYPI_MIRROR_ALIYUN}/simple",
|
|
118
|
+
"PIP_TRUSTED_HOST": "mirrors.aliyun.com",
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
"pip_douban": {
|
|
122
|
+
"name": "Pip China Mirror (Douban)",
|
|
123
|
+
"url": PYPI_MIRROR_DOUBAN,
|
|
124
|
+
"environment_prefix": "PIP",
|
|
125
|
+
"environment_variables": {
|
|
126
|
+
"PIP_INDEX_URL": f"{PYPI_MIRROR_DOUBAN}/simple",
|
|
127
|
+
"PIP_TRUSTED_HOST": "pypi.doubanio.com",
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
"pip_huawei": {
|
|
131
|
+
"name": "Pip China Mirror (Huawei)",
|
|
132
|
+
"url": PYPI_MIRROR_HUAWEI,
|
|
133
|
+
"environment_prefix": "PIP",
|
|
134
|
+
"environment_variables": {
|
|
135
|
+
"PIP_INDEX_URL": f"{PYPI_MIRROR_HUAWEI}/simple",
|
|
136
|
+
"PIP_TRUSTED_HOST": "repo.huaweicloud.com",
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
"python": {
|
|
140
|
+
"name": "PyPI China Mirror (Tsinghua)",
|
|
141
|
+
"url": PYPI_MIRROR_TSINGHUA,
|
|
142
|
+
"environment_prefix": "PIP",
|
|
143
|
+
"environment_variables": {
|
|
144
|
+
"PIP_INDEX_URL": f"{PYPI_MIRROR_TSINGHUA}/simple",
|
|
145
|
+
"PIP_TRUSTED_HOST": "pypi.tuna.tsinghua.edu.cn",
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
"poetry": {
|
|
149
|
+
"name": "Poetry China Mirror (Tsinghua)",
|
|
150
|
+
"url": PYPI_MIRROR_TSINGHUA,
|
|
151
|
+
"environment_prefix": "POETRY",
|
|
152
|
+
"environment_variables": {
|
|
153
|
+
"POETRY_REPOSITORIES_PYPI_URL": f"{POETRY_REPO_TSINGHUA}/simple",
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def get_mirror_config(package_manager: str) -> MirrorConfig | None:
|
|
160
|
+
"""Get mirror configuration for a specific package manager.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
package_manager: Name of the package manager (e.g., "npm", "go", "pip")
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
MirrorConfig if found, None otherwise.
|
|
167
|
+
"""
|
|
168
|
+
normalized_name = package_manager.lower().strip()
|
|
169
|
+
return MIRROR_CONFIGS.get(normalized_name)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def apply_mirror_environment(
|
|
173
|
+
package_manager: str,
|
|
174
|
+
environment: dict[str, str]
|
|
175
|
+
) -> dict[str, str]:
|
|
176
|
+
"""Apply mirror environment variables to the environment dict.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
package_manager: Name of the package manager
|
|
180
|
+
environment: Existing environment variables
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Updated environment with mirror variables added.
|
|
184
|
+
"""
|
|
185
|
+
mirror_config = get_mirror_config(package_manager)
|
|
186
|
+
if mirror_config is None:
|
|
187
|
+
return environment
|
|
188
|
+
|
|
189
|
+
mirror_vars = mirror_config.get("environment_variables", {})
|
|
190
|
+
updated_env = environment.copy()
|
|
191
|
+
updated_env.update(mirror_vars)
|
|
192
|
+
|
|
193
|
+
return updated_env
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def reset_mirror_environment(
|
|
197
|
+
package_manager: str,
|
|
198
|
+
environment: dict[str, str]
|
|
199
|
+
) -> dict[str, str]:
|
|
200
|
+
"""Remove mirror environment variables from the environment dict.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
package_manager: Name of the package manager
|
|
204
|
+
environment: Existing environment variables
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
Environment with mirror variables removed.
|
|
208
|
+
"""
|
|
209
|
+
mirror_config = get_mirror_config(package_manager)
|
|
210
|
+
if mirror_config is None:
|
|
211
|
+
return environment
|
|
212
|
+
|
|
213
|
+
mirror_vars = mirror_config.get("environment_variables", {})
|
|
214
|
+
updated_env = environment.copy()
|
|
215
|
+
|
|
216
|
+
for key in mirror_vars:
|
|
217
|
+
updated_env.pop(key, None)
|
|
218
|
+
|
|
219
|
+
return updated_env
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def get_all_mirror_names() -> list[str]:
|
|
223
|
+
"""Get list of all available mirror names.
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
List of package manager names with mirror support.
|
|
227
|
+
"""
|
|
228
|
+
return list(MIRROR_CONFIGS.keys())
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def validate_mirror_config(mirror_config: MirrorConfig) -> bool:
|
|
232
|
+
"""Validate a mirror configuration.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
mirror_config: Mirror configuration to validate
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
True if valid, False otherwise.
|
|
239
|
+
"""
|
|
240
|
+
required_fields = ["name", "url", "environment_prefix", "environment_variables"]
|
|
241
|
+
|
|
242
|
+
for field in required_fields:
|
|
243
|
+
if field not in mirror_config or not mirror_config[field]:
|
|
244
|
+
return False
|
|
245
|
+
|
|
246
|
+
# Validate URL format
|
|
247
|
+
url = mirror_config["url"]
|
|
248
|
+
if not (url.startswith("http://") or url.startswith("https://")):
|
|
249
|
+
return False
|
|
250
|
+
|
|
251
|
+
return True
|