fix(skills): db-load-git кириллические пути (#32) + img-grid валидация (#33)

#32: git diff/ls-files при дефолтном core.quotePath=true возвращают кириллицу
в octal-виде → объект с кириллическим именем не распознавался в partial-load.
Все git-вызовы теперь с `-c core.quotePath=false`. PY — в центральном run_git;
PS — унифицировал inline-вызовы в хелпер Invoke-GitLines (паритет с py). v1.11.

#33: img-grid падал ZeroDivisionError при -c 0 / некорректном -r. Добавлена
валидация (cols>0, rows>=0, auto-rows max(1,...)). Pillow задокументирован как
runtime-зависимость (README + python-porting-guide). overlay-grid.py получил
версионный заголовок (v1.1).

Тесты: runner error-кейсы db-dump-dt/db-load-dt/db-load-git (из PR #34).
img-grid runner-кейс не вводили (py-only + Pillow-зависимость) — #33 проверен вручную.

Closes #32, #33

Co-Authored-By: Korolev Pavel <korolev.vrn@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-30 18:33:10 +03:00
parent fb9783240e
commit 78b5b73fa7
12 changed files with 76 additions and 18 deletions
@@ -1,4 +1,4 @@
# db-load-git v1.10 — Load Git changes into 1C database
# db-load-git v1.11 — Load Git changes into 1C database
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<#
@@ -227,6 +227,15 @@ try {
}
# --- Get changed files from Git ---
# Все git-вызовы для сбора путей идут через один хелпер с -c core.quotePath=false,
# иначе кириллические пути возвращаются в octal-виде и не распознаются (зеркало run_git в .py).
function Invoke-GitLines {
param([string[]]$GitArgs)
$out = git -c core.quotePath=false @GitArgs 2>&1
if ($LASTEXITCODE -eq 0) { return $out }
return @()
}
$changedFiles = @()
$ConfigDir = (Resolve-Path $ConfigDir).Path.TrimEnd('\')
$configDirNormalized = $ConfigDir.Replace('\', '/')
@@ -236,29 +245,22 @@ try {
switch ($Source) {
"Staged" {
Write-Host "Getting staged changes..."
$raw = git diff --cached --name-only --relative 2>&1
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
$changedFiles += Invoke-GitLines -GitArgs @('diff', '--cached', '--name-only', '--relative')
}
"Unstaged" {
Write-Host "Getting unstaged changes..."
$raw = git diff --name-only --relative 2>&1
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
$raw = git ls-files --others --exclude-standard 2>&1
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
$changedFiles += Invoke-GitLines -GitArgs @('diff', '--name-only', '--relative')
$changedFiles += Invoke-GitLines -GitArgs @('ls-files', '--others', '--exclude-standard')
}
"Commit" {
Write-Host "Getting changes from $CommitRange..."
$raw = git diff --name-only --relative $CommitRange 2>&1
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
$changedFiles += Invoke-GitLines -GitArgs @('diff', '--name-only', '--relative', $CommitRange)
}
"All" {
Write-Host "Getting all uncommitted changes..."
$raw = git diff --cached --name-only --relative 2>&1
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
$raw = git diff --name-only --relative 2>&1
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
$raw = git ls-files --others --exclude-standard 2>&1
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
$changedFiles += Invoke-GitLines -GitArgs @('diff', '--cached', '--name-only', '--relative')
$changedFiles += Invoke-GitLines -GitArgs @('diff', '--name-only', '--relative')
$changedFiles += Invoke-GitLines -GitArgs @('ls-files', '--others', '--exclude-standard')
}
}
} finally {
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# db-load-git v1.10 — Load Git changes into 1C database
# db-load-git v1.11 — Load Git changes into 1C database
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -110,7 +110,7 @@ def get_object_xml_from_subfile(relative_path):
def run_git(config_dir, git_args):
"""Run a git command in config_dir and return output lines on success."""
result = subprocess.run(
["git"] + git_args,
["git", "-c", "core.quotePath=false"] + git_args,
capture_output=True,
text=True,
encoding="utf-8",
@@ -1,3 +1,6 @@
#!/usr/bin/env python3
# img-grid v1.1 — Overlay numbered grid on image
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
"""Overlay a numbered grid on an image to help determine column/row proportions.
Usage: python overlay-grid.py <image> [-c COLS] [-r ROWS] [-o OUTPUT]
@@ -29,6 +32,11 @@ def main():
parser.add_argument("-o", "--output", help="Output path (default: <name>-grid.<ext>)")
args = parser.parse_args()
if args.cols <= 0:
parser.error("--cols must be greater than 0")
if args.rows < 0:
parser.error("--rows must be greater than or equal to 0")
src = Image.open(args.image).convert("RGBA")
sw, sh = src.size
@@ -36,7 +44,7 @@ def main():
step_x = sw / cols
rows = args.rows
if rows == 0:
rows = round(sh / step_x)
rows = max(1, round(sh / step_x))
step_y = sh / rows
# Canvas with margins for labels
+1
View File
@@ -144,6 +144,7 @@ python scripts/switch.py --runtime powershell # вернуть на PowerShell
Дополнительные зависимости Python-рантайма:
- `lxml>=4.9.0` — для навыков, работающих с DOM (edit/validate/info)
- `Pillow>=10.0.0` — для `/img-grid` (чтение изображений и наложение сетки)
- `psutil>=5.9.0` — для web-навыков (управление Apache)
Параметры скриптов идентичны для обоих рантаймов — переключение меняет только интерпретатор в вызовах. Подробнее: [Python Porting Guide](docs/python-porting-guide.md).
+2
View File
@@ -109,10 +109,12 @@ Switch-параметры (`-NoValidate`) → `action='store_true'`.
- **Compile/init скрипты** (строковая сборка): только stdlib
- **DOM-скрипты** (edit/validate/info): `lxml` с `XMLParser(remove_blank_text=False)` для сохранения whitespace
- **img-grid**: `Pillow` для чтения PNG/JPEG и отрисовки сетки поверх изображения
- **Web-скрипты**: `psutil` для работы с процессами Apache
Зависимости:
- `lxml>=4.9.0` — ~25 DOM-скриптов
- `Pillow>=10.0.0``/img-grid`
- `psutil>=5.9.0` — 4 web-скрипта
## Работа с BOM (UTF-8)
@@ -0,0 +1,9 @@
{
"script": "db-dump-dt/scripts/db-dump-dt",
"setup": "none",
"args": [],
"snapshot": {
"root": "workDir",
"normalizeUuids": false
}
}
@@ -0,0 +1,4 @@
{
"name": "Ошибка: нет аргументов",
"expectError": true
}
@@ -0,0 +1,9 @@
{
"script": "db-load-dt/scripts/db-load-dt",
"setup": "none",
"args": [],
"snapshot": {
"root": "workDir",
"normalizeUuids": false
}
}
@@ -0,0 +1,4 @@
{
"name": "Ошибка: нет аргументов",
"expectError": true
}
@@ -0,0 +1,9 @@
{
"script": "db-load-git/scripts/db-load-git",
"setup": "none",
"args": [],
"snapshot": {
"root": "workDir",
"normalizeUuids": false
}
}
@@ -0,0 +1,5 @@
{
"name": "Ошибка: каталог конфигурации не найден",
"args_extra": ["-ConfigDir", "__missing_config_dir__", "-DryRun"],
"expectError": true
}
@@ -0,0 +1,5 @@
{
"name": "Ошибка: Commit без диапазона",
"args_extra": ["-ConfigDir", ".", "-Source", "Commit", "-DryRun"],
"expectError": true
}