param( [string]$RepoUrl = "https://github.com/Dejavu75/sh_export_office.git", [string]$Branch = "main", [string]$BasePath = ".", [string]$FolderName = "sh_Export_Office", [string]$ProjectSubfolder = "ch10-exp", [switch]$ForzarReclone, [switch]$NoPreguntarRuta ) $ErrorActionPreference = "Stop" function Test-CommandExists { param([string]$Name) return $null -ne (Get-Command $Name -ErrorAction SilentlyContinue) } function Test-WingetDisponible { return $null -ne (Get-Command winget -ErrorAction SilentlyContinue) } function Instalar-ConWinget { param( [string]$PackageId, [string]$DisplayName ) if (!(Test-WingetDisponible)) { throw "No se encontró winget. No puedo instalar $DisplayName automáticamente." } Write-Host "" Write-Host "Instalando $DisplayName ..." -ForegroundColor Yellow winget install --id $PackageId -e --source winget --accept-package-agreements --accept-source-agreements if ($LASTEXITCODE -ne 0) { throw "Falló la instalación de $DisplayName con winget." } } function Asegurar-Git { if (Test-CommandExists "git") { Write-Host "Git ya está instalado." -ForegroundColor Green return } Write-Host "Git no está instalado." -ForegroundColor Yellow Instalar-ConWinget -PackageId "Git.Git" -DisplayName "Git" if (!(Test-CommandExists "git")) { if (Test-Path "C:\Program Files\Git\cmd\git.exe") { $env:Path += ";C:\Program Files\Git\cmd" } } if (!(Test-CommandExists "git")) { throw "Git parece instalado, pero todavía no quedó disponible en PATH. Cerrá y abrí PowerShell de nuevo." } Write-Host "Git instalado correctamente." -ForegroundColor Green } function Test-DockerComposeDisponible { try { & docker compose version | Out-Null return $true } catch { return $false } } function Asegurar-Docker { $dockerOk = Test-CommandExists "docker" $composeOk = $false if ($dockerOk) { $composeOk = Test-DockerComposeDisponible } if ($dockerOk -and $composeOk) { Write-Host "Docker y Docker Compose ya están disponibles." -ForegroundColor Green return } Write-Host "Docker o Docker Compose no están disponibles." -ForegroundColor Yellow Instalar-ConWinget -PackageId "Docker.DockerDesktop" -DisplayName "Docker Desktop" $dockerPath1 = "C:\Program Files\Docker\Docker\resources\bin" $dockerPath2 = "$env:ProgramFiles\Docker\Docker\resources\bin" if (Test-Path $dockerPath1) { $env:Path += ";$dockerPath1" } if (($dockerPath2 -ne $dockerPath1) -and (Test-Path $dockerPath2)) { $env:Path += ";$dockerPath2" } if (!(Test-CommandExists "docker")) { throw "Docker Desktop parece instalado, pero docker no quedó disponible en PATH todavía. Capaz necesitás cerrar sesión o abrir Docker Desktop una vez." } Write-Host "Docker instalado. Puede que necesites abrir Docker Desktop antes de continuar." -ForegroundColor Yellow } function Es-ComentarioOBlanco { param([string]$Linea) if ($null -eq $Linea) { return $true } if ($Linea.Trim() -eq "") { return $true } if ($Linea.Trim().StartsWith("#")) { return $true } return $false } function Leer-EnvArchivo { param([string]$Path) $lineas = Get-Content -LiteralPath $Path -Encoding UTF8 $items = @() foreach ($linea in $lineas) { if (Es-ComentarioOBlanco $linea) { $items += [pscustomobject]@{ Tipo = "raw" Linea = $linea Key = $null Value = $null } continue } $idx = $linea.IndexOf("=") if ($idx -lt 0) { $items += [pscustomobject]@{ Tipo = "raw" Linea = $linea Key = $null Value = $null } continue } $key = $linea.Substring(0, $idx).Trim() $value = $linea.Substring($idx + 1) $items += [pscustomobject]@{ Tipo = "env" Linea = $null Key = $key Value = $value } } return $items } function Guardar-EnvArchivo { param( [string]$Path, [array]$Items ) $salida = New-Object System.Collections.Generic.List[string] foreach ($item in $Items) { if ($item.Tipo -eq "raw") { $salida.Add([string]$item.Linea) } else { $salida.Add("$($item.Key)=$($item.Value)") } } [System.IO.File]::WriteAllLines($Path, $salida, [System.Text.UTF8Encoding]::new($false)) } function Pedir-Valor { param( [string]$Nombre, [string]$ValorActual ) $nuevo = Read-Host "$Nombre [$ValorActual]" if ([string]::IsNullOrWhiteSpace($nuevo)) { return $ValorActual } return $nuevo } function Resolver-BasePath { param( [string]$BasePathParam, [bool]$Preguntar ) $base = $BasePathParam if ($Preguntar) { $actual = (Get-Location).Path $ingresado = Read-Host "Ruta base para descargar el repo [$actual]" if ([string]::IsNullOrWhiteSpace($ingresado)) { $base = "." } else { $base = $ingresado } } $rutaResuelta = [System.IO.Path]::GetFullPath((Join-Path (Get-Location) $base)) return $rutaResuelta } $preguntarRuta = $true if ($PSBoundParameters.ContainsKey("BasePath")) { $preguntarRuta = $false } if ($NoPreguntarRuta) { $preguntarRuta = $false } $BasePathResolved = Resolver-BasePath -BasePathParam $BasePath -Preguntar $preguntarRuta $RepoPath = Join-Path $BasePathResolved $FolderName $ProjectPath = Join-Path $RepoPath $ProjectSubfolder $DefaultEnvPath = Join-Path $ProjectPath "default.env" $EnvPath = Join-Path $ProjectPath ".env" $ComposePath = Join-Path $ProjectPath "docker-compose.yml" Write-Host "" Write-Host "=== Setup CH10-EXP ===" -ForegroundColor Cyan Write-Host "RepoUrl : $RepoUrl" Write-Host "Branch : $Branch" Write-Host "BasePath : $BasePathResolved" Write-Host "RepoPath : $RepoPath" Write-Host "ProjectPath : $ProjectPath" Write-Host "" Asegurar-Git Asegurar-Docker if (!(Test-Path -LiteralPath $BasePathResolved)) { New-Item -ItemType Directory -Path $BasePathResolved -Force | Out-Null } if ($ForzarReclone -and (Test-Path -LiteralPath $RepoPath)) { Write-Host "Eliminando carpeta existente por -ForzarReclone..." -ForegroundColor Yellow Remove-Item -LiteralPath $RepoPath -Recurse -Force } if (!(Test-Path -LiteralPath $RepoPath)) { Write-Host "Clonando repositorio..." -ForegroundColor Green git clone --branch $Branch $RepoUrl $RepoPath if ($LASTEXITCODE -ne 0) { throw "Falló git clone." } } else { Write-Host "La carpeta ya existe. Actualizando repo..." -ForegroundColor Yellow Push-Location $RepoPath try { git fetch origin if ($LASTEXITCODE -ne 0) { throw "Falló git fetch." } git checkout $Branch if ($LASTEXITCODE -ne 0) { throw "Falló git checkout." } git pull origin $Branch if ($LASTEXITCODE -ne 0) { throw "Falló git pull." } } finally { Pop-Location } } if (!(Test-Path -LiteralPath $ProjectPath)) { throw "No existe la subcarpeta del proyecto: $ProjectPath" } if (!(Test-Path -LiteralPath $DefaultEnvPath)) { throw "No existe default.env en: $DefaultEnvPath" } if (!(Test-Path -LiteralPath $ComposePath)) { throw "No existe docker-compose.yml en: $ComposePath" } Write-Host "" Write-Host "Preparando archivo .env..." -ForegroundColor Cyan if (Test-Path -LiteralPath $EnvPath) { Write-Host "Ya existe .env. Se va a usar ese archivo como base." -ForegroundColor Yellow } else { Copy-Item -LiteralPath $DefaultEnvPath -Destination $EnvPath -Force Write-Host "Copiado default.env a .env" -ForegroundColor Green } $items = Leer-EnvArchivo -Path $EnvPath Write-Host "" Write-Host "=== Configuración de variables ===" -ForegroundColor Cyan Write-Host "Enter deja el valor actual." Write-Host "" foreach ($item in $items) { if ($item.Tipo -ne "env") { continue } $item.Value = Pedir-Valor -Nombre $item.Key -ValorActual $item.Value } Guardar-EnvArchivo -Path $EnvPath -Items $items Write-Host "" Write-Host "Archivo .env guardado." -ForegroundColor Green Push-Location $ProjectPath try { Write-Host "" Write-Host "Ejecutando docker compose up -d ..." -ForegroundColor Green docker compose up -d if ($LASTEXITCODE -ne 0) { throw "Falló docker compose up -d." } } finally { Pop-Location } Write-Host "" Write-Host "Todo listo." -ForegroundColor Cyan Write-Host "Proyecto: $ProjectPath" Write-Host ""