()
| 172 | } |
| 173 | |
| 174 | func installPostgreSQL() error { |
| 175 | log.Println("--- Installing PostgreSQL ---") |
| 176 | |
| 177 | // Install runtime dependencies needed by PostgreSQL extensions (e.g. |
| 178 | // uuid-ossp requires libossp-uuid16). |
| 179 | if err := installPgDeps(); err != nil { |
| 180 | return fmt.Errorf("installing postgresql dependencies: %w", err) |
| 181 | } |
| 182 | |
| 183 | // Check if already installed in our directory |
| 184 | if _, err := os.Stat(pgBin("postgres")); err == nil { |
| 185 | out, err := runOutput(pgBin("postgres"), "--version") |
| 186 | if err == nil { |
| 187 | log.Printf("postgresql is already installed: %s", strings.TrimSpace(out)) |
| 188 | log.Println("skipping postgresql installation") |
| 189 | return nil |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | platform := runtime.GOOS + "/" + runtime.GOARCH |
| 194 | bin, ok := pgBinaries[platform] |
| 195 | if !ok { |
| 196 | return fmt.Errorf("unsupported platform: %s (supported: %s)", platform, supportedPlatforms()) |
| 197 | } |
| 198 | |
| 199 | // Download to a temp file |
| 200 | tarball := filepath.Join(os.TempDir(), fmt.Sprintf("postgresql-%s.tar.gz", pgVersion)) |
| 201 | |
| 202 | if _, err := os.Stat(tarball); err != nil { |
| 203 | log.Printf("downloading PostgreSQL %s from %s", pgVersion, bin.URL) |
| 204 | if err := downloadFile(tarball, bin.URL); err != nil { |
| 205 | os.Remove(tarball) |
| 206 | return fmt.Errorf("downloading postgresql: %w", err) |
| 207 | } |
| 208 | } else { |
| 209 | log.Printf("postgresql tarball already downloaded at %s", tarball) |
| 210 | } |
| 211 | |
| 212 | // Verify SHA256 checksum |
| 213 | log.Printf("verifying SHA256 checksum") |
| 214 | actualHash, err := sha256File(tarball) |
| 215 | if err != nil { |
| 216 | return fmt.Errorf("computing sha256: %w", err) |
| 217 | } |
| 218 | if actualHash != bin.SHA256 { |
| 219 | os.Remove(tarball) |
| 220 | return fmt.Errorf("SHA256 mismatch: expected %s, got %s", bin.SHA256, actualHash) |
| 221 | } |
| 222 | log.Printf("SHA256 checksum verified: %s", actualHash) |
| 223 | |
| 224 | baseDir := pgBaseDir() |
| 225 | |
| 226 | // Create the base directory in the user cache |
| 227 | if err := os.MkdirAll(baseDir, 0o755); err != nil { |
| 228 | return fmt.Errorf("creating %s: %w", baseDir, err) |
| 229 | } |
| 230 | |
| 231 | // Extract the tarball - it contains a top-level directory like |
no test coverage detected