blob: 9330e1837ed797638ccf89942434047bc9c1566a [file]
/**
* @license
* Copyright 2018 The Bazel Authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const fs = require('fs');
const path = require('path');
function mkdirp(p) {
if (!fs.existsSync(p)) {
mkdirp(path.dirname(p));
fs.mkdirSync(p);
}
}
function write(p, content, replacements) {
mkdirp(path.dirname(p));
replacements.forEach(r => {
const [regexp, newvalue] = r;
content = content.replace(regexp, newvalue);
});
fs.writeFileSync(p, content);
}
function unquoteArgs(s) {
return s.replace(/^'(.*)'$/, '$1');
}
function main(args) {
args = fs.readFileSync(args[0], {encoding: 'utf-8'}).split('\n').map(unquoteArgs);
const
[outDir, baseDir, srcsArg, binDir, genDir, depsArg, packagesArg, replacementsArg, packPath,
publishPath, stampFile] = args;
const replacements = [
// Strip content between BEGIN-INTERNAL / END-INTERNAL comments
[/(#|\/\/)\s+BEGIN-INTERNAL[\w\W]+END-INTERNAL/g, ''],
];
if (stampFile) {
// The stamp file is expected to look like
// BUILD_SCM_HASH 83c699db39cfd74526cdf9bebb75aa6f122908bb
// BUILD_SCM_LOCAL_CHANGES true
// BUILD_SCM_VERSION 6.0.0-beta.6+12.sha-83c699d.with-local-changes
// BUILD_TIMESTAMP 1520021990506
const versionTag = fs.readFileSync(stampFile, {encoding: 'utf-8'})
.split('\n')
.find(s => s.startsWith('BUILD_SCM_VERSION'));
// Don't assume BUILD_SCM_VERSION exists
if (versionTag) {
const version = versionTag.split(' ')[1].trim();
replacements.push([/0.0.0-PLACEHOLDER/g, version]);
}
}
const rawReplacements = JSON.parse(replacementsArg);
for (let key of Object.keys(rawReplacements)) {
replacements.push([new RegExp(key, 'g'), rawReplacements[key]])
}
// src like baseDir/my/path is just copied to outDir/my/path
for (src of srcsArg.split(',').filter(s => !!s)) {
const content = fs.readFileSync(src, {encoding: 'utf-8'});
const outPath = path.join(outDir, path.relative(baseDir, src));
write(outPath, content, replacements);
}
function outPath(f) {
let rootDir;
if (!path.relative(binDir, f).startsWith('..')) {
rootDir = binDir;
} else if (!path.relative(genDir, f).startsWith('..')) {
rootDir = genDir;
} else {
// It might be nice to enforce here that deps don't contain sources
// since those belong in srcs above.
// The `deps` attribute should typically be outputs of other rules.
// However, things like .d.ts sources of a ts_library or data attributes
// of ts_library will result in source files that appear in the deps
// so we have to allow this.
rootDir = '.';
}
return path.join(outDir, path.relative(path.join(rootDir, baseDir), f));
}
// deps like bazel-bin/baseDir/my/path is copied to outDir/my/path
for (dep of depsArg.split(',').filter(s => !!s)) {
const content = fs.readFileSync(dep, {encoding: 'utf-8'});
write(outPath(dep), content, replacements);
}
// package contents like bazel-bin/baseDir/my/directory/* is
// recursively copied to outDir/my/*
for (pkg of packagesArg.split(',').filter(s => !!s)) {
const outDir = outPath(path.dirname(pkg));
function copyRecursive(base, file) {
if (fs.lstatSync(path.join(base, file)).isDirectory()) {
const files = fs.readdirSync(path.join(base, file));
files.forEach(f => {
copyRecursive(base, path.join(file, f));
});
} else {
const content = fs.readFileSync(path.join(base, file), {encoding: 'utf-8'});
write(path.join(outDir, file), content, replacements);
}
}
fs.readdirSync(pkg).forEach(f => {
copyRecursive(pkg, f);
});
}
const npmTemplate =
fs.readFileSync(require.resolve('nodejs/run_npm.sh.template'), {encoding: 'utf-8'});
fs.writeFileSync(packPath, npmTemplate.replace('TMPL_args', `pack ${outDir}`));
fs.writeFileSync(publishPath, npmTemplate.replace('TMPL_args', `publish ${outDir}`));
}
if (require.main === module) {
process.exitCode = main(process.argv.slice(2));
}