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