ggcode 1.0.7__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.
- ggcode-1.0.7/PKG-INFO +16 -0
- ggcode-1.0.7/README.md +4 -0
- ggcode-1.0.7/ggcode.egg-info/PKG-INFO +16 -0
- ggcode-1.0.7/ggcode.egg-info/SOURCES.txt +9 -0
- ggcode-1.0.7/ggcode.egg-info/dependency_links.txt +1 -0
- ggcode-1.0.7/ggcode.egg-info/entry_points.txt +2 -0
- ggcode-1.0.7/ggcode.egg-info/top_level.txt +1 -0
- ggcode-1.0.7/ggcode_release_installer/__init__.py +1 -0
- ggcode-1.0.7/ggcode_release_installer/cli.py +134 -0
- ggcode-1.0.7/pyproject.toml +23 -0
- ggcode-1.0.7/setup.cfg +4 -0
ggcode-1.0.7/PKG-INFO
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ggcode
|
|
3
|
+
Version: 1.0.7
|
|
4
|
+
Summary: Thin Python wrapper that installs the ggcode GitHub Release binary
|
|
5
|
+
Author: topcheer
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/topcheer/ggcode
|
|
8
|
+
Project-URL: Repository, https://github.com/topcheer/ggcode.git
|
|
9
|
+
Project-URL: Issues, https://github.com/topcheer/ggcode/issues
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# ggcode Python wrapper
|
|
14
|
+
|
|
15
|
+
This package installs a small Python launcher that downloads the matching `ggcode`
|
|
16
|
+
binary from GitHub Releases on first run and then executes it.
|
ggcode-1.0.7/README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ggcode
|
|
3
|
+
Version: 1.0.7
|
|
4
|
+
Summary: Thin Python wrapper that installs the ggcode GitHub Release binary
|
|
5
|
+
Author: topcheer
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/topcheer/ggcode
|
|
8
|
+
Project-URL: Repository, https://github.com/topcheer/ggcode.git
|
|
9
|
+
Project-URL: Issues, https://github.com/topcheer/ggcode/issues
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# ggcode Python wrapper
|
|
14
|
+
|
|
15
|
+
This package installs a small Python launcher that downloads the matching `ggcode`
|
|
16
|
+
binary from GitHub Releases on first run and then executes it.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ggcode_release_installer
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.7"
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import os
|
|
5
|
+
import platform
|
|
6
|
+
import shutil
|
|
7
|
+
import stat
|
|
8
|
+
import subprocess
|
|
9
|
+
import sys
|
|
10
|
+
import tarfile
|
|
11
|
+
import tempfile
|
|
12
|
+
import urllib.request
|
|
13
|
+
import zipfile
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from . import __version__
|
|
17
|
+
|
|
18
|
+
OWNER = "topcheer"
|
|
19
|
+
REPO = "ggcode"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def normalize_version() -> str:
|
|
23
|
+
selected = os.environ.get("GGCODE_INSTALL_VERSION", __version__).strip()
|
|
24
|
+
if not selected or selected == "latest" or selected.startswith("0.0.0"):
|
|
25
|
+
return "latest"
|
|
26
|
+
if selected.startswith("v"):
|
|
27
|
+
return selected
|
|
28
|
+
return f"v{selected}"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def resolve_target() -> tuple[str, str]:
|
|
32
|
+
platform = sys.platform
|
|
33
|
+
if platform.startswith("linux"):
|
|
34
|
+
goos = "linux"
|
|
35
|
+
elif platform == "darwin":
|
|
36
|
+
goos = "darwin"
|
|
37
|
+
elif platform in ("win32", "cygwin"):
|
|
38
|
+
goos = "windows"
|
|
39
|
+
else:
|
|
40
|
+
raise RuntimeError(f"Unsupported platform: {platform}")
|
|
41
|
+
|
|
42
|
+
machine = platform.machine().lower() or os.environ.get("PROCESSOR_ARCHITECTURE", "").lower()
|
|
43
|
+
if machine in ("x86_64", "amd64"):
|
|
44
|
+
arch = "x86_64"
|
|
45
|
+
elif machine in ("arm64", "aarch64"):
|
|
46
|
+
arch = "arm64"
|
|
47
|
+
else:
|
|
48
|
+
raise RuntimeError(f"Unsupported architecture: {machine or 'unknown'}")
|
|
49
|
+
return goos, arch
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def release_base(version: str) -> str:
|
|
53
|
+
if version == "latest":
|
|
54
|
+
return f"https://github.com/{OWNER}/{REPO}/releases/latest/download"
|
|
55
|
+
return f"https://github.com/{OWNER}/{REPO}/releases/download/{version}"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def cache_root() -> Path:
|
|
59
|
+
if os.name == "nt":
|
|
60
|
+
base = Path(os.environ.get("LOCALAPPDATA", tempfile.gettempdir()))
|
|
61
|
+
return base / "ggcode" / "python"
|
|
62
|
+
return Path.home() / ".cache" / "ggcode" / "python"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def download(url: str) -> bytes:
|
|
66
|
+
with urllib.request.urlopen(url) as response:
|
|
67
|
+
return response.read()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def parse_checksums(body: str) -> dict[str, str]:
|
|
71
|
+
checksums: dict[str, str] = {}
|
|
72
|
+
for raw_line in body.splitlines():
|
|
73
|
+
parts = raw_line.strip().split()
|
|
74
|
+
if len(parts) >= 2:
|
|
75
|
+
checksums[parts[-1]] = parts[0]
|
|
76
|
+
return checksums
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def ensure_installed() -> Path:
|
|
80
|
+
version = normalize_version()
|
|
81
|
+
goos, arch = resolve_target()
|
|
82
|
+
archive_ext = ".zip" if goos == "windows" else ".tar.gz"
|
|
83
|
+
archive_name = f"ggcode_{goos}_{arch}{archive_ext}"
|
|
84
|
+
binary_name = "ggcode.exe" if goos == "windows" else "ggcode"
|
|
85
|
+
install_dir = cache_root() / version / f"{goos}-{arch}"
|
|
86
|
+
binary_path = install_dir / binary_name
|
|
87
|
+
if binary_path.exists():
|
|
88
|
+
return binary_path
|
|
89
|
+
|
|
90
|
+
base = release_base(version)
|
|
91
|
+
archive = download(f"{base}/{archive_name}")
|
|
92
|
+
checksums = parse_checksums(download(f"{base}/checksums.txt").decode("utf-8"))
|
|
93
|
+
expected = checksums.get(archive_name)
|
|
94
|
+
if not expected:
|
|
95
|
+
raise RuntimeError(f"Checksum for {archive_name} not found")
|
|
96
|
+
actual = hashlib.sha256(archive).hexdigest()
|
|
97
|
+
if actual.lower() != expected.lower():
|
|
98
|
+
raise RuntimeError(f"Checksum mismatch for {archive_name}")
|
|
99
|
+
|
|
100
|
+
with tempfile.TemporaryDirectory(prefix="ggcode-py-") as temp_dir:
|
|
101
|
+
temp_root = Path(temp_dir)
|
|
102
|
+
archive_path = temp_root / archive_name
|
|
103
|
+
archive_path.write_bytes(archive)
|
|
104
|
+
extract_dir = temp_root / "extract"
|
|
105
|
+
extract_dir.mkdir(parents=True, exist_ok=True)
|
|
106
|
+
|
|
107
|
+
if archive_ext == ".zip":
|
|
108
|
+
with zipfile.ZipFile(archive_path) as zf:
|
|
109
|
+
zf.extractall(extract_dir)
|
|
110
|
+
else:
|
|
111
|
+
with tarfile.open(archive_path, "r:gz") as tf:
|
|
112
|
+
tf.extractall(extract_dir)
|
|
113
|
+
|
|
114
|
+
extracted = next((p for p in extract_dir.rglob(binary_name) if p.is_file()), None)
|
|
115
|
+
if extracted is None:
|
|
116
|
+
raise RuntimeError(f"Could not find {binary_name} in {archive_name}")
|
|
117
|
+
|
|
118
|
+
install_dir.mkdir(parents=True, exist_ok=True)
|
|
119
|
+
shutil.copy2(extracted, binary_path)
|
|
120
|
+
if os.name != "nt":
|
|
121
|
+
current_mode = binary_path.stat().st_mode
|
|
122
|
+
binary_path.chmod(current_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
|
123
|
+
|
|
124
|
+
return binary_path
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def main() -> int:
|
|
128
|
+
binary = ensure_installed()
|
|
129
|
+
result = subprocess.run([str(binary), *sys.argv[1:]])
|
|
130
|
+
return result.returncode
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
if __name__ == "__main__":
|
|
134
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ggcode"
|
|
7
|
+
version = "1.0.7"
|
|
8
|
+
description = "Thin Python wrapper that installs the ggcode GitHub Release binary"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "topcheer" }]
|
|
13
|
+
|
|
14
|
+
[project.urls]
|
|
15
|
+
Homepage = "https://github.com/topcheer/ggcode"
|
|
16
|
+
Repository = "https://github.com/topcheer/ggcode.git"
|
|
17
|
+
Issues = "https://github.com/topcheer/ggcode/issues"
|
|
18
|
+
|
|
19
|
+
[project.scripts]
|
|
20
|
+
ggcode = "ggcode_release_installer.cli:main"
|
|
21
|
+
|
|
22
|
+
[tool.setuptools]
|
|
23
|
+
packages = ["ggcode_release_installer"]
|
ggcode-1.0.7/setup.cfg
ADDED