File size: 8,486 Bytes
a72d1cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# Tablo2SQL-TR başlatıcı — Windows (PowerShell 5.1+)
# baslat.bat tarafından çağrılır:  baslat.bat [--kontrol | --kisayol | --sifirla | --port N | --tarayici-yok]
$ErrorActionPreference = 'Continue'
try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch {}
$OutputEncoding = [System.Text.Encoding]::UTF8
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12

$Root = Split-Path -Parent $PSScriptRoot
Set-Location $Root
$MinMinor = 10
$Wanted = '3.12'
$PyFull = '3.12.10'
$Venv = Join-Path $Root '.venv'
$VPy = Join-Path $Venv 'Scripts\python.exe'

function Ok($m)   { Write-Host '  [TAMAM] ' -ForegroundColor Green -NoNewline; Write-Host $m }
function Warn($m) { Write-Host '  [UYARI] ' -ForegroundColor Yellow -NoNewline; Write-Host $m }
function Err($m)  { Write-Host '  [HATA]  ' -ForegroundColor Red -NoNewline; Write-Host $m }
function Info($m) { Write-Host '  [BİLGİ] ' -ForegroundColor Cyan -NoNewline; Write-Host $m }
function Ask($q) {
    $a = Read-Host "  $q [E/h]"
    return ([string]::IsNullOrWhiteSpace($a) -or $a.Trim().ToLower().StartsWith('e') -or $a.Trim().ToLower().StartsWith('y'))
}
function Fail($code = 1) {
    Write-Host ''
    Read-Host '  Bir sorun oluştu. Pencereyi kapatmak için Enter''a basın' | Out-Null
    exit $code
}

Write-Host ''
Write-Host '  ═══ Tablo2SQL-TR başlatıcı (Windows) ═══' -ForegroundColor Blue

$Reset = $false
$PassArgs = @()
foreach ($a in $args) { if ($a -eq '--sifirla') { $Reset = $true } else { $PassArgs += $a } }

# ======================================================================= Python bul
function Test-Py([string]$exe) {
    if (-not $exe) { return $null }
    # Microsoft Store kısayolu (WindowsApps\python.exe) gerçek Python değildir: Store'u açar
    if ($exe -like '*\WindowsApps\*') { return $null }
    try {
        $v = & $exe -c "import sys; print('%d.%d|%s' % (sys.version_info[0], sys.version_info[1], sys.executable))" 2>$null
        if ($LASTEXITCODE -ne 0 -or -not $v) { return $null }
        $parts = $v.Trim().Split('|')
        $mm = $parts[0].Split('.')
        if ([int]$mm[0] -eq 3 -and [int]$mm[1] -ge $MinMinor) { return $parts[1] }
    } catch {}
    return $null
}

function Find-Python {
    # 1) py başlatıcısı (python.org kurulumuyla gelir)
    if (Get-Command py -ErrorAction SilentlyContinue) {
        foreach ($ver in @('3.13', '3.12', '3.11', '3.10')) {
            try {
                $p = & py "-$ver" -c "import sys; print(sys.executable)" 2>$null
                if ($LASTEXITCODE -eq 0 -and $p) { $r = Test-Py $p.Trim(); if ($r) { return $r } }
            } catch {}
        }
    }
    # 2) PATH üzerindeki python / python3
    foreach ($n in @('python', 'python3')) {
        foreach ($c in @(Get-Command $n -All -ErrorAction SilentlyContinue)) {
            $r = Test-Py $c.Source; if ($r) { return $r }
        }
    }
    # 3) Bilinen kurulum klasörleri (PATH henüz yenilenmemiş olabilir)
    $dirs = @("$env:LOCALAPPDATA\Programs\Python", "$env:ProgramFiles\Python*", "$env:ProgramFiles", "${env:ProgramFiles(x86)}")
    foreach ($d in $dirs) {
        foreach ($exe in @(Get-ChildItem -Path $d -Filter python.exe -Recurse -Depth 2 -ErrorAction SilentlyContinue |
                           Where-Object { $_.FullName -match 'Python3\d+' } | Sort-Object FullName -Descending)) {
            $r = Test-Py $exe.FullName; if ($r) { return $r }
        }
    }
    # 4) uv ile kurulmuş Python
    $uv = Get-Command uv -ErrorAction SilentlyContinue
    if ($uv) { try { $p = & uv python find $Wanted 2>$null; $r = Test-Py $p; if ($r) { return $r } } catch {} }
    return $null
}

function Install-Python {
    Warn "Python 3.$MinMinor veya daha yenisi bulunamadı."
    if (Get-Command winget -ErrorAction SilentlyContinue) {
        if (Ask "winget ile Python $Wanted kurulsun mu? (yönetici izni gerekmez)") {
            winget install -e --id "Python.Python.$Wanted" --scope user --silent --accept-package-agreements --accept-source-agreements
            if ($LASTEXITCODE -eq 0 -or (Find-Python)) { return $true }
            Warn 'winget kurulumu başarısız oldu; resmi kurulum dosyası denenecek.'
        }
    }
    if (Ask "Python $PyFull resmi kurulum dosyası python.org'dan indirilip sessizce kurulsun mu?") {
        $arch = if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { 'arm64' } elseif ([Environment]::Is64BitOperatingSystem) { 'amd64' } else { '' }
        $file = if ($arch) { "python-$PyFull-$arch.exe" } else { "python-$PyFull.exe" }
        $url = "https://www.python.org/ftp/python/$PyFull/$file"
        $dst = Join-Path $env:TEMP $file
        Info "İndiriliyor: $url"
        try {
            $ProgressPreference = 'SilentlyContinue'
            Invoke-WebRequest -Uri $url -OutFile $dst -UseBasicParsing
        } catch { Err "İndirme başarısız: $($_.Exception.Message)"; return $false }
        Info 'Kuruluyor (kullanıcı hesabına, PATH ve py başlatıcısıyla)…'
        $p = Start-Process -FilePath $dst -ArgumentList '/quiet', 'InstallAllUsers=0', 'PrependPath=1', 'Include_launcher=1', 'Include_test=0' -Wait -PassThru
        if ($p.ExitCode -eq 0) { return $true }
        Err "Kurulum dosyası $($p.ExitCode) koduyla bitti."
    }
    Err 'Python kurulmadı. Elle kurulum:'
    Write-Host "     1. https://www.python.org/downloads/windows/ adresinden Python $Wanted indirin"
    Write-Host '     2. Kurulumun ilk ekranında "Add python.exe to PATH" kutusunu işaretleyin'
    Write-Host '     3. Bu başlatıcıyı yeniden çalıştırın'
    try { Start-Process 'https://www.python.org/downloads/windows/' } catch {}
    return $false
}

# ======================================================================= ana akış
Write-Host ''
Write-Host '0) Ön koşullar' -ForegroundColor White
$Py = Find-Python
if (-not $Py) {
    if (-not (Install-Python)) { Fail }
    # yeni kurulan Python'un PATH'ini bu oturuma al
    $env:Path = [Environment]::GetEnvironmentVariable('Path', 'User') + ';' + [Environment]::GetEnvironmentVariable('Path', 'Machine')
    $Py = Find-Python
    if (-not $Py) { Err 'Kurulumdan sonra Python bulunamadı; pencereyi kapatıp başlatıcıyı yeniden çalıştırın.'; Fail }
}
$PyVer = & $Py -c "import platform; print(platform.python_version())"
Ok "Python: $Py ($PyVer)"

if ($PassArgs.Count -gt 0 -and $PassArgs[0] -eq '--kisayol') {
    & $Py (Join-Path $Root 'scripts\kisayol.py')
    if ($LASTEXITCODE -ne 0) { Fail } else { Read-Host '  Tamam. Kapatmak için Enter' | Out-Null; exit 0 }
}

# ---- sanal ortam
if ($Reset -and (Test-Path $Venv)) { Info 'Sanal ortam siliniyor…'; Remove-Item -Recurse -Force $Venv }
if ((Test-Path $Venv) -and -not (Test-Py $VPy)) {
    Warn 'Mevcut .venv bozuk (klasör taşınmış veya Python güncellenmiş olabilir); yeniden oluşturuluyor.'
    Remove-Item -Recurse -Force $Venv
}
if (-not (Test-Path $Venv)) {
    Info 'Sanal ortam oluşturuluyor (.venv)…'
    & $Py -m venv $Venv
    if ($LASTEXITCODE -ne 0 -or -not (Test-Path $VPy)) {
        Err 'Sanal ortam oluşturulamadı. Klasörün yazılabilir olduğundan emin olun (ör. Program Files dışında bir yere çıkarın).'
        Fail
    }
    Ok 'Sanal ortam hazır.'
} else { Ok 'Sanal ortam mevcut.' }

# ---- paketler (requirements.txt değiştiyse yeniden kur)
$HashFile = Join-Path $Venv '.req_hash'
$NewHash = (Get-FileHash -Algorithm SHA256 (Join-Path $Root 'requirements.txt')).Hash.ToLower()
$OldHash = if (Test-Path $HashFile) { (Get-Content $HashFile -Raw).Trim() } else { '' }
if ($OldHash -ne $NewHash) {
    Info 'Python paketleri kuruluyor (ilk kurulum birkaç dakika sürebilir)…'
    & $VPy -m pip install --disable-pip-version-check -q --upgrade pip 2>$null | Out-Null
    & $VPy -m pip install --disable-pip-version-check -r (Join-Path $Root 'requirements.txt')
    if ($LASTEXITCODE -ne 0) {
        Err 'Paket kurulumu başarısız. İnternet bağlantısını kontrol edin; sorun sürerse: baslat.bat --sifirla'
        Fail
    }
    Set-Content -Path $HashFile -Value $NewHash -Encoding ASCII
    Ok 'Paketler kuruldu.'
}

# ---- ortak başlatıcı
& $VPy (Join-Path $Root 'scripts\baslat.py') @PassArgs
if ($LASTEXITCODE -ne 0) { Fail $LASTEXITCODE }