Skip to content

Commit 406dcb5

Browse files
fix(builtin): properly parse status file value containing spaces (#2615)
Based on Bazel's documentation, values provided through the workspace_status_command can contain whitespace on the same line the key is defined on: > The key names can be anything but they may only use upper case letters and underscores. The > first space after the key name separates it from the value. The value is the rest of the line > (including additional whitespaces). The `parseStatusFile` utility function is updated to rely on a regex for performing this parsing to match the described behavior.
1 parent 2ded6f9 commit 406dcb5

File tree

5 files changed

+164
-53
lines changed

5 files changed

+164
-53
lines changed

internal/pkg_npm/packager.js

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,32 @@ function unquoteArgs(s) {
6161
}
6262

6363
/**
64-
* The status files are expected to look like
65-
* BUILD_SCM_HASH 83c699db39cfd74526cdf9bebb75aa6f122908bb
66-
* BUILD_SCM_LOCAL_CHANGES true
67-
* STABLE_BUILD_SCM_VERSION 6.0.0-beta.6+12.sha-83c699d.with-local-changes
68-
* BUILD_TIMESTAMP 1520021990506
69-
*
70-
* @param {string} p the path to the status file
71-
* @returns a two-dimensional array of key/value pairs
72-
*/
64+
* The status files are expected to look like
65+
* BUILD_SCM_HASH 83c699db39cfd74526cdf9bebb75aa6f122908bb
66+
* BUILD_SCM_LOCAL_CHANGES true
67+
* STABLE_BUILD_SCM_VERSION 6.0.0-beta.6+12.sha-83c699d.with-local-changes
68+
* BUILD_TIMESTAMP 1520021990506
69+
*
70+
* Parsing regex is created based on Bazel's documentation describing the status file schema:
71+
* The key names can be anything but they may only use upper case letters and underscores. The
72+
* first space after the key name separates it from the value. The value is the rest of the line
73+
* (including additional whitespaces).
74+
*
75+
* @param {string} p the path to the status file
76+
* @returns a two-dimensional array of key/value pairs
77+
*/
7378
function parseStatusFile(p) {
7479
if (!p) return [];
75-
return fs.readFileSync(p, {encoding: 'utf-8'})
76-
.split('\n')
77-
.filter(t => !!t)
78-
.map(t => t.split(' '));
80+
const results = {};
81+
const statusFile = fs.readFileSync(p, {encoding: 'utf-8'});
82+
for (const match of `\n${statusFile}`.matchAll(/^([A-Z_]+) (.*)/gm)) {
83+
// Lines which go unmatched define an index value of `0` and should be skipped.
84+
if (match.index === 0) {
85+
continue;
86+
}
87+
results[match[1]] = match[2];
88+
}
89+
return results;
7990
}
8091

8192
function main(args) {
@@ -95,15 +106,16 @@ function main(args) {
95106
// Replace statuses last so that earlier substitutions can add
96107
// status-related placeholders
97108
if (volatileFile || infoFile) {
98-
const statusEntries = parseStatusFile(volatileFile)
99-
statusEntries.push(...parseStatusFile(infoFile))
109+
const statuses = {
110+
...parseStatusFile(volatileFile),
111+
...parseStatusFile(infoFile),
112+
};
100113
// Looks like {'BUILD_SCM_VERSION': 'v1.2.3'}
101-
const statuses = new Map(statusEntries)
102114
for (let idx = 0; idx < substitutions.length; idx++) {
103115
const match = substitutions[idx][1].match(/\{(.*)\}/);
104116
if (!match) continue;
105117
const statusKey = match[1];
106-
let statusValue = statuses.get(statusKey);
118+
let statusValue = statuses[statusKey];
107119
if (statusValue) {
108120
// npm versions must be numeric, so if the VCS tag starts with leading 'v', strip it
109121
// See https://github.com/bazelbuild/rules_nodejs/pull/1591

internal/pkg_web/assembler.js

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,33 @@ function unquoteArgs(s) {
3434
return s.replace(/^'(.*)'$/, '$1');
3535
}
3636

37-
function getBazelStatusMappings(statusFilePath) {
38-
if (!statusFilePath) return {};
39-
const stampFileLines = fs.readFileSync(statusFilePath, {encoding: 'utf-8'}).trim().split('\n');
40-
const stampMap = {};
41-
for (const line of stampFileLines) {
42-
const [key, value] = line.split(' ');
43-
stampMap[key] = value;
37+
/**
38+
* The status files are expected to look like
39+
* BUILD_SCM_HASH 83c699db39cfd74526cdf9bebb75aa6f122908bb
40+
* BUILD_SCM_LOCAL_CHANGES true
41+
* STABLE_BUILD_SCM_VERSION 6.0.0-beta.6+12.sha-83c699d.with-local-changes
42+
* BUILD_TIMESTAMP 1520021990506
43+
*
44+
* Parsing regex is created based on Bazel's documentation describing the status file schema:
45+
* The key names can be anything but they may only use upper case letters and underscores. The
46+
* first space after the key name separates it from the value. The value is the rest of the line
47+
* (including additional whitespaces).
48+
*
49+
* @param {string} p the path to the status file
50+
* @returns a two-dimensional array of key/value pairs
51+
*/
52+
function parseStatusFile(p) {
53+
if (!p) return [];
54+
const results = {};
55+
const statusFile = fs.readFileSync(p, {encoding: 'utf-8'});
56+
for (const match of `\n${statusFile}`.matchAll(/^([A-Z_]+) (.*)/gm)) {
57+
// Lines which go unmatched define an index value of `0` and should be skipped.
58+
if (match.index === 0) {
59+
continue;
60+
}
61+
results[match[1]] = match[2];
4462
}
45-
return stampMap;
63+
return results;
4664
}
4765

4866
function normalizeSubstitutions(substitutionsArg, stampMap) {
@@ -74,8 +92,8 @@ function main(params) {
7492
const rawSubstitutions = params.shift().replace(/^'(.*)'$/, '$1');
7593

7694
const stampMap = {
77-
...getBazelStatusMappings(volatileFilePath),
78-
...getBazelStatusMappings(stableFilePath),
95+
...parseStatusFile(volatileFilePath),
96+
...parseStatusFile(stableFilePath),
7997
};
8098

8199
const normalizedSubstitutions = normalizeSubstitutions(rawSubstitutions, stampMap)

packages/rollup/install.md

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,43 @@ To use these files, you write JS code in your `rollup.config.js` to read from th
9999
Each line is a space-separated key/value pair.
100100

101101
```javascript
102+
/**
103+
* The status files are expected to look like
104+
* BUILD_SCM_HASH 83c699db39cfd74526cdf9bebb75aa6f122908bb
105+
* BUILD_SCM_LOCAL_CHANGES true
106+
* STABLE_BUILD_SCM_VERSION 6.0.0-beta.6+12.sha-83c699d.with-local-changes
107+
* BUILD_TIMESTAMP 1520021990506
108+
*
109+
* Parsing regex is created based on Bazel's documentation describing the status file schema:
110+
* The key names can be anything but they may only use upper case letters and underscores. The
111+
* first space after the key name separates it from the value. The value is the rest of the line
112+
* (including additional whitespaces).
113+
*
114+
* @param {string} p the path to the status file
115+
* @returns a two-dimensional array of key/value pairs
116+
*/
117+
function parseStatusFile(p) {
118+
if (!p) return [];
119+
const results = {};
120+
const statusFile = require('fs').readFileSync(p, {encoding: 'utf-8'});
121+
for (const match of `\n${statusFile}`.matchAll(/^([A-Z_]+) (.*)/gm)) {
122+
// Lines which go unmatched define an index value of `0` and should be skipped.
123+
if (match.index === 0) {
124+
continue;
125+
}
126+
results[match[1]] = match[2];
127+
}
128+
return results;
129+
}
130+
131+
const statuses = parseStatusFile(bazel_version_file);
102132
// Parse the stamp file produced by Bazel from the version control system
103133
let version = '<unknown>';
104-
if (bazel_info_file) {
105-
const versionTag = require('fs')
106-
.readFileSync(bazel_info_file, {encoding: 'utf-8'})
107-
.split('\n')
108-
.find(s => s.startsWith('STABLE_GIT_COMMIT'));
109-
if (versionTag) {
110-
version = 'v' + versionTag.split(' ')[1].trim();
134+
// Don't assume BUILD_SCM_VERSION exists
135+
if (statuses['BUILD_SCM_VERSION']) {
136+
version = 'v' + statuses['BUILD_SCM_VERSION'];
137+
if (DEBUG) {
138+
version += '_debug';
111139
}
112140
}
113141
```

packages/rollup/test/integration/rollup.config.js

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,44 @@ import commonjs from '@rollup/plugin-commonjs';
22
import json from '@rollup/plugin-json';
33
import nodeResolve from '@rollup/plugin-node-resolve';
44

5+
/**
6+
* The status files are expected to look like
7+
* BUILD_SCM_HASH 83c699db39cfd74526cdf9bebb75aa6f122908bb
8+
* BUILD_SCM_LOCAL_CHANGES true
9+
* STABLE_BUILD_SCM_VERSION 6.0.0-beta.6+12.sha-83c699d.with-local-changes
10+
* BUILD_TIMESTAMP 1520021990506
11+
*
12+
* Parsing regex is created based on Bazel's documentation describing the status file schema:
13+
* The key names can be anything but they may only use upper case letters and underscores. The
14+
* first space after the key name separates it from the value. The value is the rest of the line
15+
* (including additional whitespaces).
16+
*
17+
* @param {string} p the path to the status file
18+
* @returns a two-dimensional array of key/value pairs
19+
*/
20+
function parseStatusFile(p) {
21+
if (!p) return [];
22+
const results = {};
23+
const statusFile = require('fs').readFileSync(p, {encoding: 'utf-8'});
24+
for (const match of `\n${statusFile}`.matchAll(/^([A-Z_]+) (.*)/gm)) {
25+
// Lines which go unmatched define an index value of `0` and should be skipped.
26+
if (match.index === 0) {
27+
continue;
28+
}
29+
results[match[1]] = match[2];
30+
}
31+
return results;
32+
}
33+
534
// Parse the stamp file produced by Bazel from the version control system
635
let version = '<unknown>';
7-
if (bazel_version_file) {
8-
const versionTag = require('fs')
9-
.readFileSync(bazel_version_file, {encoding: 'utf-8'})
10-
.split('\n')
11-
.find(s => s.startsWith('BUILD_SCM_VERSION'));
12-
// Don't assume BUILD_SCM_VERSION exists
13-
if (versionTag) {
14-
version = 'v' + versionTag.split(' ')[1].trim();
36+
37+
const statuses = parseStatusFile(bazel_version_file);
38+
// Don't assume BUILD_SCM_VERSION exists
39+
if (statuses['BUILD_SCM_VERSION']) {
40+
version = 'v' + statuses['BUILD_SCM_VERSION'];
41+
if (DEBUG) {
42+
version += '_debug';
1543
}
1644
}
1745

packages/rollup/test/version_stamp/rollup.config.js

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,43 @@
1+
/**
2+
* The status files are expected to look like
3+
* BUILD_SCM_HASH 83c699db39cfd74526cdf9bebb75aa6f122908bb
4+
* BUILD_SCM_LOCAL_CHANGES true
5+
* STABLE_BUILD_SCM_VERSION 6.0.0-beta.6+12.sha-83c699d.with-local-changes
6+
* BUILD_TIMESTAMP 1520021990506
7+
*
8+
* Parsing regex is created based on Bazel's documentation describing the status file schema:
9+
* The key names can be anything but they may only use upper case letters and underscores. The
10+
* first space after the key name separates it from the value. The value is the rest of the line
11+
* (including additional whitespaces).
12+
*
13+
* @param {string} p the path to the status file
14+
* @returns a two-dimensional array of key/value pairs
15+
*/
16+
function parseStatusFile(p) {
17+
if (!p) return [];
18+
const results = {};
19+
const statusFile = require('fs').readFileSync(p, {encoding: 'utf-8'});
20+
for (const match of `\n${statusFile}`.matchAll(/^([A-Z_]+) (.*)/gm)) {
21+
// Lines which go unmatched define an index value of `0` and should be skipped.
22+
if (match.index === 0) {
23+
continue;
24+
}
25+
results[match[1]] = match[2];
26+
}
27+
return results;
28+
}
29+
130
const DEBUG = process.env['COMPILATION_MODE'] === 'dbg';
231

332
// Parse the stamp file produced by Bazel from the version control system
433
let version = '<unknown>';
5-
if (bazel_version_file) {
6-
const versionTag = require('fs')
7-
.readFileSync(bazel_version_file, {encoding: 'utf-8'})
8-
.split('\n')
9-
.find(s => s.startsWith('BUILD_SCM_VERSION'));
10-
// Don't assume BUILD_SCM_VERSION exists
11-
if (versionTag) {
12-
version = 'v' + versionTag.split(' ')[1].trim();
13-
if (DEBUG) {
14-
version += '_debug';
15-
}
34+
35+
const statuses = parseStatusFile(bazel_version_file);
36+
// Don't assume BUILD_SCM_VERSION exists
37+
if (statuses['BUILD_SCM_VERSION']) {
38+
version = 'v' + statuses['BUILD_SCM_VERSION'];
39+
if (DEBUG) {
40+
version += '_debug';
1641
}
1742
}
1843

0 commit comments

Comments
 (0)