Fix Windows git commit ValueError: embedded null character.
Use git commit -F and strip NULs from argv/version strings (0.3.7). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -9,7 +9,8 @@ _VERSION_FILE = Path(__file__).resolve().parent.parent / "VERSION"
|
||||
|
||||
def _read_version() -> str:
|
||||
try:
|
||||
return _VERSION_FILE.read_text(encoding="utf-8").strip()
|
||||
text = _VERSION_FILE.read_text(encoding="utf-8-sig", errors="ignore")
|
||||
return text.replace("\0", "").strip() or "0.0.0"
|
||||
except OSError:
|
||||
return "0.0.0"
|
||||
|
||||
|
||||
@@ -76,6 +76,11 @@ def read_config_name(src_root: Path) -> str | None:
|
||||
return read_config_identity(src_root).name
|
||||
|
||||
|
||||
def _sanitize_text(s: str) -> str:
|
||||
"""Drop NULs (UTF-16 mis-reads / dirty dumps) that break Windows APIs."""
|
||||
return s.replace("\0", "").strip()
|
||||
|
||||
|
||||
def read_config_identity(src_root: Path) -> ConfigIdentity:
|
||||
"""Version, Name, Synonym (ru), Vendor from dump."""
|
||||
src_root = Path(src_root)
|
||||
@@ -84,7 +89,9 @@ def read_config_identity(src_root: Path) -> ConfigIdentity:
|
||||
version = "unknown"
|
||||
version_file = root / "VERSION"
|
||||
if version_file.is_file():
|
||||
text = version_file.read_text(encoding="utf-8-sig", errors="ignore").strip()
|
||||
text = _sanitize_text(
|
||||
version_file.read_text(encoding="utf-8-sig", errors="ignore")
|
||||
)
|
||||
if text:
|
||||
version = text.splitlines()[0].strip()
|
||||
|
||||
@@ -103,22 +110,22 @@ def read_config_identity(src_root: Path) -> ConfigIdentity:
|
||||
if version == "unknown":
|
||||
m = _VERSION_TAG.search(props)
|
||||
if m:
|
||||
version = m.group(1).strip()
|
||||
version = _sanitize_text(m.group(1)) or "unknown"
|
||||
|
||||
m = _NAME_TAG.search(props)
|
||||
if m:
|
||||
name = m.group(1).strip() or None
|
||||
name = _sanitize_text(m.group(1)) or None
|
||||
|
||||
m = _SYN_RE.search(props)
|
||||
if m:
|
||||
synonym = _xml_unescape(m.group(1).strip()) or None
|
||||
synonym = _sanitize_text(_xml_unescape(m.group(1))) or None
|
||||
|
||||
m = _VENDOR_TAG.search(props)
|
||||
if m:
|
||||
vendor = _xml_unescape(m.group(1).strip()) or None
|
||||
vendor = _sanitize_text(_xml_unescape(m.group(1))) or None
|
||||
|
||||
return ConfigIdentity(
|
||||
version=version or "unknown",
|
||||
version=_sanitize_text(version) or "unknown",
|
||||
name=name,
|
||||
synonym=synonym,
|
||||
vendor=vendor,
|
||||
|
||||
+41
-4
@@ -3,8 +3,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
from export1c_help.fscompat import copy_file, ensure_dir, remove_file
|
||||
@@ -18,21 +20,56 @@ class WikiPushError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
def _clean_arg(value: str | Path) -> str:
|
||||
"""Windows CreateProcess rejects argv/cwd strings that contain NUL."""
|
||||
s = os.fspath(value)
|
||||
if "\0" in s:
|
||||
s = s.replace("\0", "")
|
||||
return s
|
||||
|
||||
|
||||
def _run(cmd: list[str], *, cwd: Path) -> str:
|
||||
clean_cmd = [_clean_arg(a) for a in cmd]
|
||||
clean_cwd = _clean_arg(cwd.resolve())
|
||||
proc = subprocess.run(
|
||||
cmd,
|
||||
cwd=cwd,
|
||||
clean_cmd,
|
||||
cwd=clean_cwd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
errors="replace",
|
||||
check=False,
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
raise WikiPushError(
|
||||
f"$ {' '.join(cmd)}\n{proc.stdout}\n{proc.stderr}".strip()
|
||||
f"$ {' '.join(clean_cmd)}\n{proc.stdout}\n{proc.stderr}".strip()
|
||||
)
|
||||
return proc.stdout
|
||||
|
||||
|
||||
def _git_commit(work_dir: Path, message: str) -> None:
|
||||
"""Commit via ``-F`` so Windows never gets NUL/encoding issues in ``-m``."""
|
||||
text = _clean_arg(message).strip() or "export_1c_help: sync help"
|
||||
if not text.endswith("\n"):
|
||||
text += "\n"
|
||||
with tempfile.NamedTemporaryFile(
|
||||
mode="w",
|
||||
encoding="utf-8",
|
||||
newline="\n",
|
||||
suffix=".txt",
|
||||
delete=False,
|
||||
) as fh:
|
||||
fh.write(text)
|
||||
msg_path = fh.name
|
||||
try:
|
||||
_run(["git", "commit", "-F", msg_path], cwd=work_dir)
|
||||
finally:
|
||||
try:
|
||||
Path(msg_path).unlink()
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def prepare_wiki_clone(
|
||||
wiki_url: str,
|
||||
work_dir: Path,
|
||||
@@ -149,5 +186,5 @@ def push_wiki(
|
||||
if not status.strip():
|
||||
return
|
||||
|
||||
_run(["git", "commit", "-m", message], cwd=work_dir)
|
||||
_git_commit(work_dir, message)
|
||||
_run(["git", "push", "origin", f"HEAD:{branch}"], cwd=work_dir)
|
||||
|
||||
Reference in New Issue
Block a user