1import { Task } from './Task'; 2import path from 'path'; 3import chalk from 'chalk'; 4import fs from 'fs-extra'; 5import { toRepoPath, findFiles } from '../utils'; 6 7export type CopyFilesSettings = { 8 from?: string; 9 subDirectory?: string; 10 filePattern: string | string[]; 11 to: string; 12}; 13 14/** 15 * A task which will copy files from `workingDirectory()/subDirectory/filePatterns` to the provided path. 16 * 17 * It's searching for file names which match `filePatterns` and then it copies them into `to/<matched_part_of_file_name>`. 18 * So the `subDirectory` part won't be copied. 19 * 20 * If for this file structure: 21 * 22 * ``` 23 * android/ 24 * src/ 25 * main.java 26 * lib/ 27 * lib.java 28 * ``` 29 * 30 * you runs CopyFiles with: 31 * ``` 32 * { 33 * from: 'android', 34 * subDirectory: 'src|lib', 35 * to: 'copied', 36 * filePatterns: '*' 37 * } 38 * ``` 39 * you gets: 40 * ``` 41 * android/ 42 * src/ 43 * main.java 44 * lib/ 45 * lib.java 46 * lib/ 47 * main.java 48 * lib.java 49 * ``` 50 */ 51export class CopyFiles extends Task { 52 private from?: string; 53 private subDirectory?: string; 54 private readonly filePattern: string[]; 55 private readonly to: string; 56 57 /** 58 * Using `from` key, you can override the work directory. 59 * @param settings 60 */ 61 constructor({ from, subDirectory, filePattern, to }: CopyFilesSettings) { 62 super(); 63 this.from = from; 64 this.subDirectory = subDirectory; 65 this.to = toRepoPath(to); 66 if (typeof filePattern === 'string') { 67 this.filePattern = [filePattern]; 68 } else { 69 this.filePattern = filePattern; 70 } 71 } 72 73 protected overrideWorkingDirectory(): string | undefined { 74 return this.from; 75 } 76 77 async execute() { 78 const workDirectory = this.getWorkingDirectory(); 79 80 for (const pattern of this.filePattern) { 81 const subPath = this.subDirectory 82 ? path.join(workDirectory, this.subDirectory) 83 : workDirectory; 84 85 this.logSubStep( 86 ` copy ${chalk.green(this.from || '<workingDirectory>')}/${chalk.green( 87 this.subDirectory ? this.subDirectory + '/' : '' 88 )}${chalk.yellow(pattern)} into ${chalk.magenta(this.to)}` 89 ); 90 91 const files = await findFiles(subPath, pattern); 92 await Promise.all( 93 files.map(async (file) => { 94 const relativeFilePath = path.relative(subPath, file); 95 const destinationFullPath = path.join(this.to, relativeFilePath); 96 97 await fs.mkdirs(path.dirname(destinationFullPath)); 98 return await fs.copy(file, destinationFullPath); 99 }) 100 ); 101 } 102 } 103} 104