UNPKG

@google/clasp

Version:

Develop Apps Script Projects locally

56 lines (55 loc) 3.08 kB
import { Command } from 'commander'; import fs from 'fs/promises'; import inquirer from 'inquirer'; import { intl } from '../intl.js'; import { isInteractive, withSpinner } from './utils.js'; export const command = new Command('pull') .description('Fetch a remote project') .option('--versionNumber <version>', 'The version number of the project to retrieve.') .option('-d, --deleteUnusedFiles ', 'Delete local files that are not in the remote project. Use with caution.') .option('-f, --force', 'Forcibly delete local files that are not in the remote project without prompting.') .action(async function (options) { const clasp = this.opts().clasp; const versionNumber = options.versionNumber; const forceDelete = options.force; let spinnerMsg = intl.formatMessage({ id: "dh7Bw6", defaultMessage: [{ type: 0, value: "Checking local files..." }] }); const localFiles = await clasp.files.collectLocalFiles(); spinnerMsg = intl.formatMessage({ id: "jilcJH", defaultMessage: [{ type: 0, value: "Pulling files..." }] }); const files = await withSpinner(spinnerMsg, async () => { return await clasp.files.pull(versionNumber); }); if (options.deleteUnusedFiles) { const filesToDelete = localFiles.filter(f => !files.find(p => p.localPath === f.localPath)); await deleteLocalFiles(filesToDelete, forceDelete); } files.forEach(f => console.log(`└─ ${f.localPath}`)); const successMessage = intl.formatMessage({ id: "4mRAfN", defaultMessage: [{ type: 0, value: "Pulled " }, { type: 6, value: "count", options: { "=0": { value: [{ type: 0, value: "no files." }] }, one: { value: [{ type: 0, value: "one file." }] }, other: { value: [{ type: 7 }, { type: 0, value: " files" }] } }, offset: 0, pluralType: "cardinal" }, { type: 0, value: "." }] }, { count: files.length, }); console.log(successMessage); }); async function deleteLocalFiles(filesToDelete, forceDelete = false) { if (!filesToDelete || filesToDelete.length === 0) { return; } const skipConfirmation = forceDelete; if (!isInteractive() && !forceDelete) { const msg = intl.formatMessage({ id: "zLuvSg", defaultMessage: [{ type: 0, value: "You are not in an interactive terminal and --force not used. Skipping file deletion." }] }); console.warn(msg); return; } for (const file of filesToDelete) { if (!skipConfirmation) { const confirm = await inquirer.prompt({ type: 'confirm', name: 'deleteFile', message: intl.formatMessage({ id: "lVx/lI", defaultMessage: [{ type: 0, value: "Delete " }, { type: 1, value: "file" }, { type: 0, value: "?" }] }, { file: file.localPath }), }); if (!confirm.deleteFile) { continue; } } await fs.unlink(file.localPath); console.log(intl.formatMessage({ id: "Nx315v", defaultMessage: [{ type: 0, value: "Deleted " }, { type: 1, value: "file" }] }, { file: file.localPath })); } }