blob: fd5fc5c951d1442e3c7c08e51cde4009c7065798 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import childProcess from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import url from 'node:url';
// JSON files under .vscode/ synced by this script
const VSCODE_SETTINGS_TO_MERGE = [
{ settingsFile: 'settings.json' },
{ settingsFile: 'tasks.json', mergeField: 'tasks', byField: 'label' },
{
settingsFile: 'launch.json',
mergeField: 'configurations',
byField: 'name',
},
];
// If the user has opted out of updates, return and do nothing.
if (Boolean(process.env['SKIP_VSCODE_SETTINGS_SYNC'])) {
process.exit(0);
}
for (const { settingsFile, mergeField, byField } of VSCODE_SETTINGS_TO_MERGE) {
const vscodeSettingsLocation = path.resolve(
path.join(process.cwd(), '.vscode', settingsFile),
);
const devtoolsSettingsLocation = path.resolve(
path.join(process.cwd(), '.vscode', 'devtools-workspace-' + settingsFile),
);
// If there are no settings to copy and paste, skip.
if (!fs.existsSync(devtoolsSettingsLocation)) {
continue;
}
try {
const devtoolsSettings = (
await import(url.pathToFileURL(devtoolsSettingsLocation).href, {
with: { type: 'json' },
})
).default;
let preExistingSettings = {};
if (fs.existsSync(vscodeSettingsLocation)) {
preExistingSettings = (
await import(url.pathToFileURL(vscodeSettingsLocation).href, {
with: { type: 'json' },
})
).default;
}
const updatedSettings = {
...devtoolsSettings,
// Any setting specified by the engineer will always take precedence over the defaults
...preExistingSettings,
};
// TODO: We found that this never work so patch it now
// so gclient sync updates it.
// Later we should remove and allow user to keep their
// preference.
if (updatedSettings['eslint.runtime']) {
const nodePath = childProcess
.execSync(
path.join(
import.meta.dirname,
'..',
'..',
'third_party',
'node',
'node_path.py',
),
)
.toString('utf-8')
.trim();
updatedSettings['eslint.runtime'] = nodePath;
}
if (
mergeField &&
byField &&
preExistingSettings[mergeField] &&
devtoolsSettings[mergeField]
) {
// We need to merge two lists in a field. The list items have a unique
// id specified by byField. If an entry is found in devtoolsSettings we
// assume it should be updated when the devtools settings file is updated,
// otherwise we keep the preexisting setting.
const mergedList = [...devtoolsSettings[mergeField]];
const doNotDuplicate = new Set(mergedList.map(item => item[byField]));
for (const item of preExistingSettings[mergeField]) {
if (!doNotDuplicate.has(item[byField])) {
mergedList.push(item);
}
}
updatedSettings[mergeField] = mergedList;
}
fs.writeFileSync(
vscodeSettingsLocation,
JSON.stringify(updatedSettings, null, 2),
);
} catch (err) {
console.warn('Unable to update VSCode settings - skipping');
console.warn(err.stack);
}
}