Files: 1eb144e388da5f1a3466703f56ac4ab591d700fc / lib / packer.js
4624 bytesRaw
1 | /* eslint-disable complexity */ |
2 | |
3 | import { |
4 | STORE_BLOB, STORE_CONTENT, STORE_LINKS, |
5 | STORE_STAT, isDotJS, isDotJSON |
6 | } from '../prelude/common.js'; |
7 | |
8 | import { log, wasReported } from './log.js'; |
9 | import assert from 'assert'; |
10 | import fs from 'fs-extra'; |
11 | import { version } from '../package.json'; |
12 | |
13 | const bootstrapText = fs.readFileSync( |
14 | require.resolve('../prelude/bootstrap.js'), 'utf8' |
15 | ).replace('%VERSION%', version); |
16 | |
17 | const commonText = fs.readFileSync( |
18 | require.resolve('../prelude/common.js'), 'utf8' |
19 | ); |
20 | |
21 | function itemsToText (items) { |
22 | const len = items.length; |
23 | return len.toString() + |
24 | (len % 10 === 1 ? ' item' : ' items'); |
25 | } |
26 | |
27 | function hasAnyStore (record) { |
28 | // discarded records like native addons |
29 | for (const store of [ STORE_BLOB, STORE_CONTENT, STORE_LINKS, STORE_STAT ]) { |
30 | if (record[store]) return true; |
31 | } |
32 | return false; |
33 | } |
34 | |
35 | export default function ({ records, entrypoint, bytecode, otherEntrypoints }) { |
36 | const stripes = []; |
37 | for (const snap in records) { |
38 | const record = records[snap]; |
39 | const { file, blobGroup } = record; |
40 | if (!hasAnyStore(record)) continue; |
41 | assert(record[STORE_STAT], 'packer: no STORE_STAT'); |
42 | |
43 | assert(record[STORE_BLOB] || record[STORE_CONTENT] || record[STORE_LINKS]); |
44 | |
45 | if (record[STORE_BLOB] && !bytecode) { |
46 | delete record[STORE_BLOB]; |
47 | if (!record[STORE_CONTENT]) { |
48 | // TODO make a test for it? |
49 | throw wasReported('--no-bytecode and no source breaks final executable', [ file, |
50 | 'Please run with "-d" and without "--no-bytecode" first, and make', |
51 | 'sure that debug log does not contain "was included as bytecode".' ]); |
52 | } |
53 | } |
54 | |
55 | for (const store of [ STORE_BLOB, STORE_CONTENT, STORE_LINKS, STORE_STAT ]) { |
56 | const value = record[store]; |
57 | if (!value) continue; |
58 | |
59 | if (store === STORE_BLOB || |
60 | store === STORE_CONTENT) { |
61 | if (record.body === undefined) { |
62 | stripes.push({ snap, store, file, blobGroup: blobGroup }); |
63 | } else |
64 | if (Buffer.isBuffer(record.body)) { |
65 | stripes.push({ snap, store, buffer: record.body }); |
66 | } else |
67 | if (typeof record.body === 'string') { |
68 | stripes.push({ snap, store, buffer: Buffer.from(record.body) }); |
69 | } else { |
70 | assert(false, 'packer: bad STORE_BLOB/STORE_CONTENT'); |
71 | } |
72 | } else |
73 | if (store === STORE_LINKS) { |
74 | if (Array.isArray(value)) { |
75 | const buffer = Buffer.from(JSON.stringify(value)); |
76 | stripes.push({ snap, store, buffer }); |
77 | } else { |
78 | assert(false, 'packer: bad STORE_LINKS'); |
79 | } |
80 | } else |
81 | if (store === STORE_STAT) { |
82 | if (typeof value === 'object') { |
83 | // reproducible |
84 | delete value.atime; |
85 | delete value.atimeMs; |
86 | delete value.mtime; |
87 | delete value.mtimeMs; |
88 | delete value.ctime; |
89 | delete value.ctimeMs; |
90 | delete value.birthtime; |
91 | delete value.birthtimeMs; |
92 | // non-date |
93 | delete value.blksize; |
94 | delete value.blocks; |
95 | delete value.dev; |
96 | delete value.gid; |
97 | delete value.ino; |
98 | delete value.nlink; |
99 | delete value.rdev; |
100 | delete value.uid; |
101 | if (!value.isFile()) value.size = 0; |
102 | // portable |
103 | const newStat = Object.assign({}, value); |
104 | newStat.isFileValue = value.isFile(); |
105 | newStat.isDirectoryValue = value.isDirectory(); |
106 | const buffer = Buffer.from(JSON.stringify(newStat)); |
107 | stripes.push({ snap, store, buffer }); |
108 | } else { |
109 | assert(false, 'packer: bad STORE_STAT'); |
110 | } |
111 | } else { |
112 | assert(false, 'packer: unknown store'); |
113 | } |
114 | } |
115 | |
116 | if (record[STORE_CONTENT]) { |
117 | const disclosed = isDotJS(file) || isDotJSON(file); |
118 | log.debug(disclosed ? 'The file was included as DISCLOSED code (with sources)' |
119 | : 'The file was included as asset content', file); |
120 | } else |
121 | if (record[STORE_BLOB]) { |
122 | log.debug('The file was included as bytecode (no sources)', file); |
123 | } else |
124 | if (record[STORE_LINKS]) { |
125 | const value = record[STORE_LINKS]; |
126 | log.debug('The directory files list was included (' + itemsToText(value) + ')', file); |
127 | } |
128 | } |
129 | |
130 | const prelude = |
131 | 'return (function (REQUIRE_COMMON, VIRTUAL_FILESYSTEM, DEFAULT_ENTRYPOINT) { ' + |
132 | bootstrapText + |
133 | '\n})(function (exports) {\n' + |
134 | commonText + |
135 | '\n},\n' + |
136 | '%VIRTUAL_FILESYSTEM%' + |
137 | '\n,\n' + |
138 | '%DEFAULT_ENTRYPOINT%' + |
139 | '\n);'; |
140 | |
141 | return { prelude, entrypoint, otherEntrypoints, stripes }; |
142 | } |
143 |
Built with git-ssb-web