import { ChangeFileInfo , ChangeInfoMultiple } from '../types/ChangeInfo' ; import { findPackageRoot , getChangePath } from '../paths' ; import { getChanges , getStagedChanges , git , fetchRemoteBranch , parseRemoteBranch } from 'workspace-tools' ; import fs from 'fs-extra' ; import path from 'path' ; import minimatch from 'minimatch' ; import { getScopedPackages } from '../monorepo/getScopedPackages' ; import { BeachballOptions } from '../types/BeachballOptions' ; import { PackageInfos } from '../types/PackageInfo' ; /**
 * Gets all the changed packages, regardless of the change files
 */ function getAllChangedPackages ( options , packageInfos ) { const { branch , path : cwd } = options ; const changes = [ ... ( getChanges ( branch , cwd ) || [ ] ) , ... ( getStagedChanges ( cwd ) || [ ] ) ] ; const scopedPackages = getScopedPackages ( options , packageInfos ) ; const ignorePatterns = [ ... ( options . ignorePatterns || [ ] ) , 'CHANGELOG.md' , 'CHANGELOG.json' ] ; const packageRoots = { } ; if ( changes ) { changes . filter ( name => ! ignorePatterns . some ( pattern => minimatch ( name , pattern , { matchBase : true } ) ) ) . forEach ( moddedFile => { const root = findPackageRoot ( path . join ( cwd , path . dirname ( moddedFile ) ) ) ; if ( root && ! packageRoots [ root ] ) { try { const packageJson = fs . readJSONSync ( path . join ( root , 'package.json' ) ) ; if ( ! packageJson . private && ( ! packageJson . beachball || packageJson . beachball . shouldPublish !== false ) ) { const packageName = packageJson . name ; if ( scopedPackages . includes ( packageName ) ) { packageRoots [ root ] = packageName ; } } } catch ( e ) { } } } ) ; } return Object . values ( packageRoots ) ; } /**
 * Gets all the changed packages, accounting for change files
 */ export function getChangedPackages ( options , packageInfos ) { const { fetch , path : cwd , branch } = options ; const changePath = getChangePath ( cwd ) ; if ( fetch ) { const { remote , remoteBranch } = parseRemoteBranch ( branch ) ; console . log ( `fetching latest from remotes "${ remote }/${ remoteBranch }"` ) ; fetchRemoteBranch ( remote , remoteBranch , cwd ) ; } const changedPackages = getAllChangedPackages ( options , packageInfos ) ; const changeFilesResult = git ( [ 'diff' , '--name-only' , '--relative' , '--no-renames' , '--diff-filter=A' , `${ branch }...` ] , { cwd } ) ; if ( ! changePath || ! fs . existsSync ( changePath ) || ! changeFilesResult . success ) { return changedPackages ; } const changes = changeFilesResult . stdout . split ( /\n/ ) ; const changeFiles = changes . filter ( name => path . dirname ( name ) === 'change' ) ; const changeFilePackageSet = new Set < string > ( ) ; changeFiles . forEach ( file => { try { const changeInfo = fs . readJSONSync ( file ) ; if ( 'changes' in changeInfo ) { for ( const change of ( changeInfo as ChangeInfoMultiple ) . changes ) { changeFilePackageSet . add ( change . packageName ) ; } } else { changeFilePackageSet . add ( ( changeInfo as ChangeFileInfo ) . packageName ) ; } } catch ( e ) { console . warn ( `Error reading or parsing change file ${ file }: ${ e }` ) ; } } ) ; if ( changeFilePackageSet . size > 0 ) { console . log ( 'Your local repository already has change files for these packages:' + [ ... changeFilePackageSet ] . sort ( ) . map ( pkg => `\n  ${ pkg }` ) . join ( '' ) ) ; } return changedPackages . filter ( pkgName => ! changeFilePackageSet . has ( pkgName ) ) ; }