1313// (or maybe don't - what does this option mean?)
1414
1515import { transformFileAsync } from '@babel/core' ;
16- import { readdir , readFile , rename , writeFile } from 'fs/promises' ;
17- import { join as pathJoin } from 'path' ;
16+ import assert from 'assert' ;
17+ import { copyFile , readdir , readFile , rename , writeFile } from 'fs/promises' ;
18+ import { extname , join as pathJoin } from 'path' ;
1819
1920const PACKAGES = [ 'babel-plugin-transform-class-properties' ] ;
2021const FILTER_OUT_PRESETS = [ 'env' ] ;
@@ -25,6 +26,7 @@ const FILTER_OUT_PLUGINS = [
2526] ;
2627
2728const PACKAGES_PATH = pathJoin ( import . meta. dirname , '../coverage/babel/packages' ) ;
29+ const OVERRIDES_PATH = pathJoin ( import . meta. dirname , 'overrides' ) ;
2830
2931// Copied from `@babel/helper-transform-fixture-test-runner`
3032const EXTERNAL_HELPERS_VERSION = '7.100.0' ;
@@ -45,41 +47,80 @@ async function updateDir(dirPath, options, hasChangedOptions) {
4547 const files = await readdir ( dirPath , { withFileTypes : true } ) ;
4648
4749 const dirFiles = [ ] ;
48- let optionsFile , inputFile , outputFile ;
50+
51+ const filenames = { options : null , input : null , output : null , exec : null } ;
52+ const overrides = { options : false , input : false , output : false , exec : false } ;
53+
54+ // Find files in dir
4955 for ( const file of files ) {
56+ const filename = file . name ;
5057 if ( file . isDirectory ( ) ) {
51- dirFiles . push ( file ) ;
52- } else if ( file . name === 'options.json' ) {
53- optionsFile = file ;
54- } else if ( file . name . startsWith ( 'output.' ) ) {
55- outputFile = file ;
56- } else if ( file . name . startsWith ( 'input.' ) ) {
57- inputFile = file ;
58+ dirFiles . push ( filename ) ;
59+ } else {
60+ const ext = extname ( filename ) ,
61+ type = ext === '' ? filename : filename . slice ( 0 , - ext . length ) ;
62+ if ( Object . hasOwn ( filenames , type ) ) filenames [ type ] = filename ;
5863 }
5964 }
6065
61- if ( optionsFile ) {
62- const path = pathJoin ( dirPath , optionsFile . name ) ;
66+ // Find override files
67+ const overridesDirPath = pathJoin ( `${ OVERRIDES_PATH } ${ dirPath . slice ( PACKAGES_PATH . length ) } ` ) ;
68+ let overrideFiles ;
69+ try {
70+ overrideFiles = await readdir ( overridesDirPath , { withFileTypes : true } ) ;
71+ } catch ( err ) {
72+ if ( err ?. code !== 'ENOENT' ) throw err ;
73+ }
74+
75+ if ( overrideFiles ) {
76+ for ( const file of overrideFiles ) {
77+ if ( file . isDirectory ( ) ) continue ;
78+
79+ const filename = file . name ,
80+ ext = extname ( filename ) ,
81+ type = filename . slice ( 0 , - ext . length ) ,
82+ path = pathJoin ( overridesDirPath , filename ) ;
83+
84+ assert ( Object . hasOwn ( overrides , type ) , `Unexpected override file: ${ path } ` ) ;
85+
86+ const originalPath = pathJoin ( dirPath , filename ) ;
87+ if ( filenames [ type ] ) {
88+ const originalFilename = filenames [ type ] ;
89+ assert ( originalFilename === filename , `Unmatched override file: ${ path } ` ) ;
90+ await backupFile ( originalPath ) ;
91+ }
92+
93+ filenames [ type ] = filename ;
94+ overrides [ type ] = true ;
95+ if ( type === 'options' ) hasChangedOptions = true ;
96+
97+ await copyFile ( path , originalPath ) ;
98+ }
99+ }
100+
101+ // Update options, save to file, and merge options with parent
102+ if ( filenames . options ) {
103+ const path = pathJoin ( dirPath , filenames . options ) ;
63104 const localOptions = JSON . parse ( await readFile ( path , 'utf8' ) ) ;
64- if ( updateOptions ( localOptions ) ) {
105+ if ( ! overrides . options && updateOptions ( localOptions ) ) {
65106 hasChangedOptions = true ;
66- const backupPath = pathJoin ( dirPath , 'options.original.json' ) ;
67- await rename ( path , backupPath ) ;
107+ await backupFile ( path ) ;
68108 await writeFile ( path , JSON . stringify ( localOptions , null , 2 ) + '\n' ) ;
69109 }
70110 options = mergeOptions ( options , localOptions ) ;
71111 }
72112
73- if ( outputFile && hasChangedOptions ) {
74- const inputPath = pathJoin ( dirPath , inputFile . name ) ;
75- const outputPath = pathJoin ( dirPath , outputFile . name ) ;
76- const backupOutputPath = pathJoin ( dirPath , `output.original. ${ outputFile . name . slice ( 7 ) } ` ) ;
77- await rename ( outputPath , backupOutputPath ) ;
113+ // Run Babel with updated options/input
114+ if ( filenames . output && ( hasChangedOptions || overrides . input ) && ! overrides . output ) {
115+ const inputPath = pathJoin ( dirPath , filenames . input ) ,
116+ outputPath = pathJoin ( dirPath , filenames . output ) ;
117+ await backupFile ( outputPath ) ;
78118 await transform ( inputPath , outputPath , options ) ;
79119 }
80120
81- for ( const file of dirFiles ) {
82- const path = pathJoin ( dirPath , file . name ) ;
121+ // Process subfolders
122+ for ( const filename of dirFiles ) {
123+ const path = pathJoin ( dirPath , filename ) ;
83124 await updateDir ( path , options , hasChangedOptions ) ;
84125 }
85126}
@@ -211,3 +252,14 @@ function getName(stringOrArray) {
211252 if ( Array . isArray ( stringOrArray ) ) return stringOrArray [ 0 ] ;
212253 return stringOrArray ;
213254}
255+
256+ /**
257+ * Backup file.
258+ * @param {string } path - Original path
259+ * @returns {undefined }
260+ */
261+ async function backupFile ( path ) {
262+ const ext = extname ( path ) ,
263+ backupPath = `${ path . slice ( 0 , - ext . length ) } .original${ ext } ` ;
264+ await rename ( path , backupPath ) ;
265+ }
0 commit comments