@@ -31,15 +31,17 @@ export class ShellOperationRunnerPlugin implements IPhasedCommandPlugin {
3131 ) : Set < Operation > {
3232 const { rushConfiguration, isInitial } = context ;
3333
34- const getCustomParameterValuesForPhase : ( phase : IPhase ) => ReadonlyArray < string > =
35- getCustomParameterValuesByPhase ( ) ;
34+ const getCustomParameterValues : ( operation : Operation ) => ICustomParameterValuesForOperation =
35+ getCustomParameterValuesForOperation ( ) ;
36+
3637 for ( const operation of operations ) {
3738 const { associatedPhase : phase , associatedProject : project } = operation ;
3839
3940 if ( ! operation . runner ) {
4041 // This is a shell command. In the future, may consider having a property on the initial operation
4142 // to specify a runner type requested in rush-project.json
42- const customParameterValues : ReadonlyArray < string > = getCustomParameterValuesForPhase ( phase ) ;
43+ const { parameterValues : customParameterValues , ignoredParameterNames } =
44+ getCustomParameterValues ( operation ) ;
4345
4446 const displayName : string = getDisplayName ( phase , project ) ;
4547 const { name : phaseName , shellCommand } = phase ;
@@ -63,6 +65,7 @@ export class ShellOperationRunnerPlugin implements IPhasedCommandPlugin {
6365 commandForHash,
6466 commandToRun,
6567 customParameterValues,
68+ ignoredParameterNames,
6669 rushConfiguration
6770 } ) ;
6871 }
@@ -82,8 +85,9 @@ export function initializeShellOperationRunner(options: {
8285 commandToRun : string | undefined ;
8386 commandForHash ?: string ;
8487 customParameterValues : ReadonlyArray < string > ;
88+ ignoredParameterNames : ReadonlyArray < string > ;
8589} ) : IOperationRunner {
86- const { phase, project, commandToRun : rawCommandToRun , displayName } = options ;
90+ const { phase, project, commandToRun : rawCommandToRun , displayName, ignoredParameterNames } = options ;
8791
8892 if ( typeof rawCommandToRun !== 'string' && phase . missingScriptBehavior === 'error' ) {
8993 throw new Error (
@@ -104,7 +108,8 @@ export function initializeShellOperationRunner(options: {
104108 commandForHash,
105109 displayName,
106110 phase,
107- rushProject : project
111+ rushProject : project ,
112+ ignoredParameterNames
108113 } ) ;
109114 } else {
110115 // Empty build script indicates a no-op, so use a no-op runner
@@ -116,30 +121,110 @@ export function initializeShellOperationRunner(options: {
116121 }
117122}
118123
124+ /**
125+ * Result of filtering custom parameters for an operation
126+ */
127+ export interface ICustomParameterValuesForOperation {
128+ /**
129+ * The serialized custom parameter values that should be included in the command
130+ */
131+ parameterValues : ReadonlyArray < string > ;
132+ /**
133+ * The names of parameters that were ignored for this operation
134+ */
135+ ignoredParameterNames : ReadonlyArray < string > ;
136+ }
137+
119138/**
120139 * Memoizer for custom parameter values by phase
121140 * @returns A function that returns the custom parameter values for a given phase
122141 */
123142export function getCustomParameterValuesByPhase ( ) : ( phase : IPhase ) => ReadonlyArray < string > {
124- const customParametersByPhase : Map < IPhase , string [ ] > = new Map ( ) ;
143+ const customParametersByPhase : Map < IPhase , Set < string > > = new Map ( ) ;
125144
126145 function getCustomParameterValuesForPhase ( phase : IPhase ) : ReadonlyArray < string > {
127- let customParameterValues : string [ ] | undefined = customParametersByPhase . get ( phase ) ;
128- if ( ! customParameterValues ) {
129- customParameterValues = [ ] ;
146+ let customParameterSet : Set < string > | undefined = customParametersByPhase . get ( phase ) ;
147+ if ( ! customParameterSet ) {
148+ const customParameterValues : string [ ] = [ ] ;
130149 for ( const tsCommandLineParameter of phase . associatedParameters ) {
131150 tsCommandLineParameter . appendToArgList ( customParameterValues ) ;
132151 }
133152
134- customParametersByPhase . set ( phase , customParameterValues ) ;
153+ customParameterSet = new Set ( customParameterValues ) ;
154+ customParametersByPhase . set ( phase , customParameterSet ) ;
135155 }
136156
137- return customParameterValues ;
157+ return Array . from ( customParameterSet ) ;
138158 }
139159
140160 return getCustomParameterValuesForPhase ;
141161}
142162
163+ /**
164+ * Gets custom parameter values for an operation, filtering out any parameters that should be ignored
165+ * based on the operation's settings.
166+ * @returns A function that returns the filtered custom parameter values and ignored parameter names for a given operation
167+ */
168+ export function getCustomParameterValuesForOperation ( ) : (
169+ operation : Operation
170+ ) => ICustomParameterValuesForOperation {
171+ const customParametersByPhase : Map < IPhase , Set < string > > = new Map ( ) ;
172+
173+ function getCustomParameterValuesForOp ( operation : Operation ) : ICustomParameterValuesForOperation {
174+ const { associatedPhase : phase , settings } = operation ;
175+
176+ // Get or compute the set of all custom parameters for this phase
177+ let customParameterSet : Set < string > | undefined = customParametersByPhase . get ( phase ) ;
178+ if ( ! customParameterSet ) {
179+ customParameterSet = new Set ( ) ;
180+ for ( const tsCommandLineParameter of phase . associatedParameters ) {
181+ const tempArgs : string [ ] = [ ] ;
182+ tsCommandLineParameter . appendToArgList ( tempArgs ) ;
183+ for ( const arg of tempArgs ) {
184+ customParameterSet . add ( arg ) ;
185+ }
186+ }
187+
188+ customParametersByPhase . set ( phase , customParameterSet ) ;
189+ }
190+
191+ // If there are no parameters to ignore, return early with all parameters
192+ const parameterNamesToIgnore : string [ ] | undefined = settings ?. parameterNamesToIgnore ;
193+ if ( ! parameterNamesToIgnore || parameterNamesToIgnore . length === 0 ) {
194+ return {
195+ parameterValues : Array . from ( customParameterSet ) ,
196+ ignoredParameterNames : [ ]
197+ } ;
198+ }
199+
200+ // Create a set of parameter long names to ignore for fast lookup
201+ const ignoreSet : Set < string > = new Set ( parameterNamesToIgnore ) ;
202+
203+ // Filter out ignored parameters and track which ones were ignored
204+ const filteredParameterValues : string [ ] = [ ] ;
205+ const ignoredParameterNames : string [ ] = [ ] ;
206+
207+ for ( const tsCommandLineParameter of phase . associatedParameters ) {
208+ const parameterLongName : string = tsCommandLineParameter . longName ;
209+
210+ if ( ignoreSet . has ( parameterLongName ) ) {
211+ // This parameter should be ignored for this operation
212+ ignoredParameterNames . push ( parameterLongName ) ;
213+ } else {
214+ // Include this parameter in the command
215+ tsCommandLineParameter . appendToArgList ( filteredParameterValues ) ;
216+ }
217+ }
218+
219+ return {
220+ parameterValues : filteredParameterValues ,
221+ ignoredParameterNames
222+ } ;
223+ }
224+
225+ return getCustomParameterValuesForOp ;
226+ }
227+
143228export function formatCommand ( rawCommand : string , customParameterValues : ReadonlyArray < string > ) : string {
144229 if ( ! rawCommand ) {
145230 return '' ;
0 commit comments