1
0
mirror of https://github.com/tishchenkovv/git-hook-1c.git synced 2026-04-26 20:42:50 +02:00
Files
2025-07-01 09:57:47 +03:00

387 lines
12 KiB
PowerShell

<#
Git Hook Pre-commit
Автор: Тищенко В.В.
Версия: 1.0
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$files
)
Add-Type -AssemblyName System.Windows.Forms
function Show-Message {
param(
[Parameter(Mandatory = $true)]
[string]$text,
[string]$caption = "Information",
[string]$icon = "Information"
)
$iconEnum = [System.Windows.Forms.MessageBoxIcon]::$icon
$buttonEnum = [System.Windows.Forms.MessageBoxButtons]::OK
[System.Windows.Forms.MessageBox]::Show($text, $caption, $buttonEnum, $iconEnum)
}
function Test-Settings {
param(
[Parameter(Mandatory = $true)]
[hashtable]$settings
)
$skipKeys = @("user", "password", "path_bsl", "files")
$errors = @()
foreach ($item in $settings.GetEnumerator()) {
$key = $item.Key
$value = $item.Value
if ($skipKeys -contains $key) {
continue
}
if ($null -eq $value -or [string]::IsNullOrWhiteSpace($value)) {
$errors += "$($key): empty"
}
}
if ($errors.Count -gt 0) {
$msg = "Пропущен параметр в settings:`n" + ($errors -join "`n")
Show-Message -text $msg -caption "Settings validation error" -icon "Error"
exit 1
}
}
function Stop-1c {
param(
[Parameter(Mandatory = $true)]
[string]$base
)
$matchingProcesses = Get-CimInstance Win32_Process |
Where-Object {
$_.Name -eq "1cv8.exe" -and $_.CommandLine -match [regex]::Escape($base)
}
foreach ($proc in $matchingProcesses) {
try {
Stop-Process -Id $proc.ProcessId -Force
} catch {
Write-Warning "Не удалось завершить процесс с PID $($proc.ProcessId): $_"
exit 1
}
}
}
function Test-Syntax {
param(
[hashtable]$settings
)
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$logPath = Join-Path $settings["root"] "syntax_check_$timestamp.log"
$authByUser = $settings["AuthOS"]
$userSpecified = -not ($settings["user"] -eq "")
$infobase = ($settings["base"] -split "\\")[1]
Stop-1c -base $infobase
$args = if (-not $authByUser -and $userSpecified) {
@(
"DESIGNER",
"/DisableStartupDialogs",
"/S", $settings["base"],
"/N", $settings["user"],
"/P", $settings["password"],
"/CheckConfig", "-ConfigLogIntegrity", "-Server", "-ExternalConnectionServer",
"-UnreferenceProcedures", "-HandlersExistence", "-EmptyHandlers",
"/Out", "`"$logPath`""
)
} else {
@(
"DESIGNER",
"/DisableStartupDialogs",
"/S", $settings["base"],
"/CheckConfig", "-ConfigLogIntegrity", "-Server", "-ExternalConnectionServer",
"-UnreferenceProcedures", "-HandlersExistence", "-EmptyHandlers",
"/Out", "`"$logPath`""
)
}
Write-Host "Запущен синтакис чек 1с..."
Write-Host "$($settings["platform"]) $($args -join ' ')"
$proc = Start-Process -FilePath $settings["platform"] -ArgumentList $args -PassThru
$timeout = 2700
$sw = [System.Diagnostics.Stopwatch]::StartNew()
while (-not $proc.HasExited) {
Start-Sleep -Seconds 2
if ($sw.Elapsed.TotalSeconds -ge $timeout) {
Write-Warning "1C процесс завис. Попытка завершения процесса..."
try {
$proc.Kill()
Write-Error "Процесс уничтожен 1с $timeout сек."
} catch {
Write-Error "Не удалось завершить процесс 1с: $_"
exit 1
}
}
}
$sw.Stop()
$msg = "Заершен процесс синтаксис проверки $([math]::Round($sw.Elapsed.TotalSeconds, 1)) сек."
Write-Host $msg
if (Test-Path $logPath -PathType Leaf) {
$lines = Get-Content $logPath -Encoding UTF8
$filtered = $lines | Where-Object { $_ -notmatch 'Не обнаружено ссылок на процедуру: "Подключаемый_' -and $_ -notmatch 'Не обнаружено ссылок на функцию: "Подключаемый_' }
Set-Content -Path $logPath $filtered -Encoding UTF8
if (@(Get-Content -Path $logPath).Count -gt 0) {
Show-Message -text "Найдены ошибки в конфигурации" -caption "Syntax-check 1c"
Invoke-Item $logPath
} else {
Show-Message -text "Ошибок не найдено. OK" -caption "Syntax-check 1c"
}
} else {
Show-Message -text "Не найден файл" -caption "Syntax-check 1c" -icon "Error"
}
}
function Test-BSL {
param(
[hashtable]$operation,
[hashtable]$settings_1c
)
$bslFile = Join-Path $settings_1c.root "bsl-json.json"
if (Test-Path $bslFile) {
Remove-Item $bslFile -Force
}
$files = $operation.files
if ($files.Count -eq 0) {
Write-Host "Нет файлов для проверки"
exit 0
}
$pathBSL = $operation.path_bsl
if (!(Test-Path $pathBSL)) {
$msg = "Не найден BSL 1c"
Write-Host $msg
Show-Message -text $msg -caption "BSL" -icon "Error"
exit 1
}
$folder = New-Item -Name "input" -Path $settings_1c.root -ItemType Directory
$filesRepo = @{}
$count = 1
foreach ($file in $files) {
$nameFile = @($count, "bsl") -join "."
$tempPath = Join-Path $folder $nameFile
Copy-Item -Path $file -Destination $tempPath
$filesRepo[$nameFile] = $file
$count++
}
$args = @(
"-jar",
$pathBSL,
"-a",
"-s", $folder,
"-o", $settings_1c.root,
"-r", "json"
)
Start-Process java -ArgumentList $args -Wait -NoNewWindow
$pathDiag = Join-Path $settings_1c.root "bsl-json.json"
$errorList = @()
if (Test-Path $pathDiag) {
$diag = Get-Content $pathDiag -Raw -Encoding UTF8 | ConvertFrom-Json
foreach ($fileinfo in $diag.fileinfos) {
$cleanPath = $fileinfo.path -replace "^file:///", ""
$nameFile = (Get-Item -Path $cleanPath).Name
$originalFile = $filesRepo[$nameFile]
foreach ($result in $fileinfo.diagnostics) {
$errorList += New-Object psobject -Property @{
File = $originalFile
Type_Error = $result.severity
LineNumber = $result.range.start.line + 1
Message = $result.message
}
}
}
$tempCsvPath = Join-Path $env:TEMP "bsl_diag_temp.csv"
$errorList | Export-Csv -Path $tempCsvPath -Encoding UTF8 -NoTypeInformation
$vbsPath = Join-Path $env:TEMP "launch_gridview.vbs"
$vbsContent = @'
Dim shell
Set shell = CreateObject("WScript.Shell")
shell.Run "powershell -WindowStyle Hidden -NoProfile -Command ""Import-Csv -Path '" & WScript.Arguments(0) & "' | Out-GridView -Title 'Diagnostic code with BSL Server 1c'; Remove-Item -Path '" & WScript.Arguments(0) & "' -Force; Start-Sleep -Seconds 3600""", 0, False
'@
Set-Content -Path $vbsPath -Value $vbsContent -Encoding ASCII
Start-Process "wscript.exe" -ArgumentList @("`"$vbsPath`"", "`"$tempCsvPath`"") -WindowStyle Hidden
Start-Sleep -Milliseconds 500
Remove-Item -Path $vbsPath -Force
Remove-Item -Path $pathDiag -Force
Write-Host "Удаление файла: " $pathDiag
}
if (Test-Path $folder) {
Remove-Item $folder -Recurse -Force
}
}
function Test-Configuration {
param(
[hashtable]$settings_1c,
[hashtable]$operation
)
$logFiles = Get-ChildItem -Path $settings_1c["root"] | Where-Object { $_.Extension -eq ".log" }
foreach ($file in $logFiles) {
try {
Remove-Item -Path $file.FullName -Force
Write-Host "Удалено: $($file.FullName)"
} catch {
Write-Warning "Не удалось удалить: $($file.FullName)"
}
}
$testSyntax = $operation.check_syntax
$testBSL = $operation.check_bsl
$pathBSL = $operation.path_bsl
if ($testSyntax) {
$result = $true
if (-not $operation.check_syntax_auto) {
$dialogResult = [System.Windows.Forms.MessageBox]::Show(
"Запустить проврерку syntax check 1c?",
"Check Syntax",
[System.Windows.Forms.MessageBoxButtons]::YesNo,
[System.Windows.Forms.MessageBoxIcon]::Question
)
$result = ($dialogResult -eq [System.Windows.Forms.DialogResult]::Yes)
}
if ($result) {
Test-Syntax -settings $settings_1c
}
}
if ($testBSL -and -not [string]::IsNullOrWhiteSpace($pathBSL)) {
$result = $true
if (-not $operation.check_bsl_auto) {
$dialogResult = [System.Windows.Forms.MessageBox]::Show(
"Сделать проверку c помощью BSL Server 1c?",
"Check BSL",
[System.Windows.Forms.MessageBoxButtons]::YesNo,
[System.Windows.Forms.MessageBoxIcon]::Question
)
$result = ($dialogResult -eq [System.Windows.Forms.DialogResult]::Yes)
}
if ($result) {
Test-BSL -operation $operation -settings_1c $settings_1c
}
}
}
if ([string]::IsNullOrWhiteSpace($files)) {
Write-Host "❗ Получена пустая строка. Прерывание."
exit 0
}
$filesArray = $files -split '\s+'
$filesArray = $filesArray | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
Write-Host "Список полученных файлов:"
$filesArray | ForEach-Object { Write-Host "$_" }
$filesList = @()
foreach ($file in $filesArray) {
$item = Get-Item $file -ErrorAction SilentlyContinue
if ($item -and $item.Extension -eq ".bsl") {
$filesList += $file
}
}
Write-Host "Файлы с расширением .bsl:"
$filesList | ForEach-Object { Write-Host " + $_" }
$root = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
$jsonPath = Join-Path $root "config_hooks.json"
if (!(Test-Path $jsonPath)) {
$msg = "Settings file not found: config_hooks.json"
Write-Host $msg -ForegroundColor Red
Show-Message $msg "Settings" "Warning"
exit 1
}
$hook = Get-Content $jsonPath -Raw | ConvertFrom-Json
if (-not $hook.settings.pre_commit.use_precommit) {
Write-Host "Pre-commit hook отключен"
exit 0
}
$pathBSL = ""
if (-not [string]::IsNullOrWhiteSpace($hook.settings.pre_commit.path_bsl)) {
$pathBSL = $hook.settings.pre_commit.path_bsl
} else {
$bsl = Get-ChildItem -Path $root -Filter *.jar -File | Select-Object -First 1
if ($null -ne $bsl -and (Test-Path $bsl.FullName)) {
$pathBSL = $bsl.FullName
}
}
$operation = @{
use_precommit = $hook.settings.pre_commit.use_precommit
check_syntax = $hook.settings.pre_commit.check_syntax
check_syntax_auto = $hook.settings.pre_commit.check_syntax_auto
check_bsl = $hook.settings.pre_commit.check_bsl
path_bsl = $pathBSL
files = $filesList
}
Test-Settings -settings $operation
$src = if ([string]::IsNullOrWhiteSpace($hook.settings_1c.src)) {
Join-Path $root "src"
} else {
$hook.settings_1c.src
}
$settings_1c = @{
base = $hook.settings_1c.base
AuthOS = $hook.settings_1c.AuthOS
user = $hook.settings_1c.user
password = $hook.settings_1c.password
platform = $hook.settings_1c.platform
root = $root
src = $src
}
Test-Settings -settings $settings_1c
Test-Configuration -settings $settings_1c -operation $operation