<# 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