|
| 1 | +#!/usr/bin/env node |
| 2 | + |
| 3 | +const fs = require('fs'); |
| 4 | +const util = require('util'); |
| 5 | +const path = require('path'); |
| 6 | +const {spawn} = require('child_process'); |
| 7 | +const browserPaths = require('playwright/lib/install/browserPaths.js'); |
| 8 | + |
| 9 | +(async () => { |
| 10 | + const allBrowsersPath = browserPaths.browsersPath(); |
| 11 | + const {stdout} = await runCommand('find', [allBrowsersPath, '-executable', '-type', 'f']); |
| 12 | + const lddPaths = stdout.split('\n').map(f => f.trim()).filter(filePath => !filePath.toLowerCase().endsWith('.sh')); |
| 13 | + const allMissingDeps = await Promise.all(lddPaths.map(lddPath => missingFileDependencies(lddPath))); |
| 14 | + const missingDeps = new Set(); |
| 15 | + for (const deps of allMissingDeps) { |
| 16 | + for (const dep of deps) |
| 17 | + missingDeps.add(dep); |
| 18 | + } |
| 19 | + console.log(`==== MISSING DEPENDENCIES: ${missingDeps.size} ====`); |
| 20 | + console.log([...missingDeps].sort().join('\n')); |
| 21 | + |
| 22 | + console.log('{'); |
| 23 | + for (const dep of missingDeps) { |
| 24 | + const packages = await findPackages(dep); |
| 25 | + if (packages.length === 0) |
| 26 | + console.log(` // UNRESOLVED: ${dep} `); |
| 27 | + else if (packages.length === 1) |
| 28 | + console.log(` "${dep}": "${packages[0]}",`); |
| 29 | + else |
| 30 | + console.log(` "${dep}": ${JSON.stringify(packages)},`); |
| 31 | + } |
| 32 | + console.log('}'); |
| 33 | +})(); |
| 34 | + |
| 35 | +async function findPackages(libraryName) { |
| 36 | + const {stdout} = await runCommand('apt-file', ['search', libraryName]); |
| 37 | + if (!stdout.trim()) |
| 38 | + return []; |
| 39 | + const libs = stdout.trim().split('\n').map(line => line.split(':')[0]); |
| 40 | + return [...new Set(libs)]; |
| 41 | +} |
| 42 | + |
| 43 | +async function fileDependencies(filePath) { |
| 44 | + const {stdout} = await lddAsync(filePath); |
| 45 | + const deps = stdout.split('\n').map(line => { |
| 46 | + line = line.trim(); |
| 47 | + const missing = line.includes('not found'); |
| 48 | + const name = line.split('=>')[0].trim(); |
| 49 | + return {name, missing}; |
| 50 | + }); |
| 51 | + return deps; |
| 52 | +} |
| 53 | + |
| 54 | +async function missingFileDependencies(filePath) { |
| 55 | + const deps = await fileDependencies(filePath); |
| 56 | + return deps.filter(dep => dep.missing).map(dep => dep.name); |
| 57 | +} |
| 58 | + |
| 59 | +async function lddAsync(filePath) { |
| 60 | + return await runCommand('ldd', [filePath], { |
| 61 | + cwd: path.dirname(filePath), |
| 62 | + env: { |
| 63 | + ...process.env, |
| 64 | + LD_LIBRARY_PATH: path.dirname(filePath), |
| 65 | + }, |
| 66 | + }); |
| 67 | +} |
| 68 | + |
| 69 | +function runCommand(command, args, options = {}) { |
| 70 | + const childProcess = spawn(command, args, options); |
| 71 | + |
| 72 | + return new Promise((resolve) => { |
| 73 | + let stdout = ''; |
| 74 | + let stderr = ''; |
| 75 | + childProcess.stdout.on('data', data => stdout += data); |
| 76 | + childProcess.stderr.on('data', data => stderr += data); |
| 77 | + childProcess.on('close', (code) => { |
| 78 | + resolve({stdout, stderr, code}); |
| 79 | + }); |
| 80 | + }); |
| 81 | +} |
0 commit comments