| … | … | @@ -41,7 +41,7 @@ export function getArchivePath (archiveDir, repoName, format) { |
| 41 | 41 | * @param {string} format - 'tar.gz' or 'zip' |
| 42 | 42 | * @returns {Promise<{ path: string, size: number, format: string, commitHash: string }>} |
| 43 | 43 | */ |
| 44 | export async function generateArchive (bareRepoPath, repoName, archiveDir, format) { | |
| 44 | export async function generateArchive (bareRepoPath, repoName, archiveDir, format, opts = {}) { | |
| 45 | 45 | // 1. Validate format |
| 46 | 46 | if (!VALID_FORMATS.includes(format)) { |
| 47 | 47 | throw new Error(`Invalid archive format "${format}". Must be one of: ${VALID_FORMATS.join(', ')}`) |
| … | … | @@ -62,15 +62,23 @@ export async function generateArchive (bareRepoPath, repoName, archiveDir, forma |
| 62 | 62 | await fs.promises.mkdir(outDir, { recursive: true }) |
| 63 | 63 | |
| 64 | 64 | // 4. Run git archive |
| 65 | const outFile = path.join(outDir, `release.${format}`) | |
| 65 | const archSuffix = opts.arch ? `-${opts.arch}` : '' | |
| 66 | const outFile = path.join(outDir, `release${archSuffix}.${format}`) | |
| 66 | 67 | |
| 67 | await execGit(bareRepoPath, [ | |
| 68 | const archiveArgs = [ | |
| 68 | 69 | 'archive', |
| 69 | 70 | `--format=${format}`, |
| 70 | 71 | `--prefix=${repoName}/`, |
| 71 | 72 | '-o', outFile, |
| 72 | 73 | 'release' |
| 73 | ]) | |
| 74 | ] | |
| 75 | ||
| 76 | // Arch-specific: only include by-arch/{host}/ + root launcher files | |
| 77 | if (opts.arch) { | |
| 78 | archiveArgs.push('--', `by-arch/${opts.arch}/`, 'index.js', 'package.json', 'version.txt', 'daemon/') | |
| 79 | } | |
| 80 | ||
| 81 | await execGit(bareRepoPath, archiveArgs) | |
| 74 | 82 | |
| 75 | 83 | // 5. Get file size and return metadata |
| 76 | 84 | const stat = await fs.promises.stat(outFile) |
| … | … | @@ -571,9 +571,10 @@ async function appRemove (name, flags) { |
| 571 | 571 | * @param {string} repoName - The repository name |
| 572 | 572 | * @returns {string} Full archive URL |
| 573 | 573 | */ |
| 574 | export function buildArchiveUrl (serverUrl, repoName) { | |
| 574 | export function buildArchiveUrl (serverUrl, repoName, opts = {}) { | |
| 575 | 575 | const base = serverUrl.replace(/\/$/, '') |
| 576 | return `${base}/tabertron/${repoName}/archive/release.tar.gz` | |
| 576 | const arch = opts.arch || detectHost() | |
| 577 | return `${base}/tabertron/${repoName}/archive/release.tar.gz?arch=${arch}` | |
| 577 | 578 | } |
| 578 | 579 | |
| 579 | 580 | /** |
| … | … | @@ -81,10 +81,13 @@ async function handleArchiveDownload (req, res, server) { |
| 81 | 81 | } |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | // 4. Resolve archive path | |
| 84 | // 4. Resolve archive path (arch-specific if ?arch= query param) | |
| 85 | const arch = req.query ? req.query.arch : null | |
| 85 | 86 | const storagePath = path.resolve(storage || './pear-git-storage') |
| 86 | 87 | const archiveDir = path.join(storagePath, 'archives') |
| 87 | const archivePath = getArchivePath(archiveDir, repoName, format) | |
| 88 | const archSuffix = arch ? `-${arch}` : '' | |
| 89 | const archiveSubdir = path.join(archiveDir, repoName) | |
| 90 | const archivePath = path.join(archiveSubdir, `release${archSuffix}.${format}`) | |
| 88 | 91 | |
| 89 | 92 | // 5. Check if pre-built archive exists |
| 90 | 93 | let stat = null |
| … | … | @@ -101,9 +104,9 @@ async function handleArchiveDownload (req, res, server) { |
| 101 | 104 | } |
| 102 | 105 | |
| 103 | 106 | try { |
| 104 | const result = await generateArchive(repo.path, repoName, archiveDir, format) | |
| 107 | const result = await generateArchive(repo.path, repoName, archiveDir, format, { arch }) | |
| 105 | 108 | stat = fs.statSync(result.path) |
| 106 | console.log(`[Archive] Generated ${format} for ${repoName} (${stat.size} bytes)`) | |
| 109 | console.log(`[Archive] Generated ${format}${arch ? ' (' + arch + ')' : ''} for ${repoName} (${(stat.size / 1024 / 1024).toFixed(1)} MB)`) | |
| 107 | 110 | } catch (err) { |
| 108 | 111 | if (err.message.includes('has no release branch')) { |
| 109 | 112 | notFound(res, 'No release branch found. Deploy first to create one.') |