symlinks.js (2374B)
1 'use strict'; 2 3 const path = require('path'); 4 const fs = require('fs-extra'); 5 const globby = require('globby'); 6 7 const { isWindows, formatDirsForMatcher, getSignatures, writeSignatures, cleanUp, onSuccess, onError, onProgress } = require('./utils'); 8 const { dirs, symlinkDirs, copyDirs, symlinkFiles, ignoreMask } = require('./config'); 9 const ROOT = path.resolve(__dirname, '..'); 10 11 12 //@TODO: change signature to getSymlinks(source, options, signatures) 13 // here and elsewhere 14 // 15 // run symlinks twice, once for files (with nodir: true) 16 // once for dirs 17 async function getSymlinks(source, options, signatures) { 18 const t1 = Date.now(); 19 const files = await globby(source, Object.assign({ cwd: ROOT }, options )); 20 const filesDonePreviously = []; 21 for (const [f, signature] of Object.entries(signatures)) { 22 if ('isSymlinked' in signature && signature.isSymlinked) { 23 try { 24 await fs.access(path.join('build', f), fs.constants.F_OK); 25 // file found in signatures and build/ dir, skip 26 filesDonePreviously.push(f); 27 } catch (_) { 28 // file not found, needs symlinking 29 } 30 } 31 } 32 33 const filesToProcess = files.filter(f => !filesDonePreviously.includes(f)); 34 const filesProcessedCount = filesToProcess.length; 35 36 var f; 37 while ((f = filesToProcess.pop()) != null) { 38 const dest = path.join('build', f); 39 try { 40 if (isWindows) { 41 await fs.copy(f, dest); 42 } else { 43 await fs.ensureSymlink(f, dest); 44 } 45 signatures[f] = { 46 isSymlinked: true 47 }; 48 onProgress(f, dest, 'ln'); 49 } catch (err) { 50 throw new Error(`Failed on ${f}: ${err}`); 51 } 52 } 53 54 const t2 = Date.now(); 55 56 return { 57 action: 'symlink', 58 count: filesProcessedCount, 59 totalCount: files.length, 60 processingTime: t2 - t1 61 }; 62 } 63 64 65 module.exports = getSymlinks; 66 67 if (require.main === module) { 68 (async () => { 69 try { 70 const source = symlinkFiles 71 .concat(dirs.map(d => `${d}/**`)) 72 .concat([`!${formatDirsForMatcher(dirs)}/**/*.js`]) 73 .concat([`!${formatDirsForMatcher(copyDirs)}/**`]); 74 75 const signatures = await getSignatures(); 76 onSuccess(await getSymlinks(source, { nodir: true, ignore: ignoreMask }, signatures)); 77 onSuccess(await getSymlinks(symlinkDirs, {}, signatures)); 78 onSuccess(await cleanUp(signatures)); 79 await writeSignatures(signatures); 80 } catch (err) { 81 process.exitCode = 1; 82 global.isError = true; 83 onError(err); 84 } 85 })(); 86 }