1
- use super :: get_meta;
2
- use crate :: args:: get_spawned_by;
3
- use crate :: args:: ENV_BUF_MODE ;
4
- use crate :: args:: ENV_BUF_SIZE ;
5
- use crate :: args:: ENV_NULL ;
6
- use crate :: args:: ENV_SPAWNED_BY ;
7
1
use crate :: colors:: RESET ;
8
2
use crate :: colors:: YELLOW ;
9
3
use crate :: command:: Context ;
@@ -12,32 +6,26 @@ use crate::command::Meta;
12
6
use crate :: command_examples;
13
7
use crate :: command_meta;
14
8
use crate :: commands:: cat;
9
+ use crate :: env:: Env ;
15
10
use crate :: examples:: Example ;
16
11
use crate :: io:: LineReader ;
17
- use crate :: pattern;
18
12
use crate :: pattern:: Expression ;
19
13
use crate :: pattern:: ExpressionValue ;
20
14
use crate :: pattern:: Item ;
21
15
use crate :: pattern:: Pattern ;
22
16
use crate :: pattern:: SimpleItem ;
23
17
use crate :: pattern:: SimplePattern ;
18
+ use crate :: process:: Command ;
24
19
use crate :: process:: Pipeline ;
25
- use crate :: process:: StdinMode ;
26
20
use crate :: shell:: Shell ;
27
21
use crate :: spawn:: Spawned ;
28
- use crate :: stdbuf:: StdBuf ;
29
- use anyhow:: Context as _;
30
22
use anyhow:: Result ;
31
23
use bstr:: ByteVec ;
32
- use clap:: crate_name;
33
24
use clap:: ArgAction ;
34
- use std:: env;
35
- use std:: env:: current_exe;
36
25
use std:: panic:: resume_unwind;
37
26
use std:: process:: Child ;
38
27
use std:: process:: ChildStdin ;
39
28
use std:: process:: ChildStdout ;
40
- use std:: process:: Command ;
41
29
use std:: thread;
42
30
use std:: time:: Duration ;
43
31
@@ -211,7 +199,7 @@ fn eval_simple_pattern(context: &Context, pattern: &SimplePattern) -> Result<()>
211
199
}
212
200
213
201
fn eval_pattern ( context : & Context , pattern : & Pattern , shell : & Shell ) -> Result < ( ) > {
214
- let mut stdbuf = StdBuf :: default ( ) ;
202
+ let mut env = context . env ( ) ;
215
203
let mut children = Vec :: new ( ) ;
216
204
let mut consumers = Vec :: new ( ) ;
217
205
let mut producers = Vec :: new ( ) ;
@@ -220,7 +208,7 @@ fn eval_pattern(context: &Context, pattern: &Pattern, shell: &Shell) -> Result<(
220
208
match & item {
221
209
Item :: Constant ( value) => producers. push ( Producer :: Constant ( value. clone ( ) ) ) ,
222
210
Item :: Expression ( ref expr) => {
223
- let pipeline = build_pipeline ( context , & mut stdbuf , shell, expr) ?;
211
+ let pipeline = build_pipeline ( & mut env , shell, expr) ?;
224
212
225
213
for child in pipeline. children {
226
214
children. push ( child) ;
@@ -260,9 +248,37 @@ fn eval_pattern(context: &Context, pattern: &Pattern, shell: &Shell) -> Result<(
260
248
}
261
249
}
262
250
263
- enum Producer {
264
- Constant ( String ) ,
265
- Child ( Spawned < LineReader < ChildStdout > > ) ,
251
+ fn build_pipeline ( env : & mut Env , shell : & Shell , expr : & Expression ) -> Result < Pipeline > {
252
+ let raw_expr = format ! ( "{YELLOW}{}{RESET}" , expr. raw_value) ;
253
+
254
+ match build_pipeline_internal ( env, shell, expr) {
255
+ Ok ( pipeline) => Ok ( pipeline. context ( format ! ( "expression: {raw_expr}" ) ) ) ,
256
+ Err ( err) => Err ( err. context ( format ! ( "failed to initialize expression {raw_expr}" ) ) ) ,
257
+ }
258
+ }
259
+
260
+ fn build_pipeline_internal ( env : & mut Env , shell : & Shell , expr : & Expression ) -> Result < Pipeline > {
261
+ let mut pipeline = Pipeline :: new ( expr. stdin_mode ) ;
262
+
263
+ match & expr. value {
264
+ ExpressionValue :: RawShell ( command) => {
265
+ let mut command = shell. build_command ( command) ;
266
+ command. envs ( env. external ( ) ) ;
267
+ pipeline = pipeline. add_command ( command, expr. stdin_mode ) ?;
268
+ }
269
+ ExpressionValue :: Pipeline ( commands) => {
270
+ for command in commands {
271
+ let command = Command :: detect ( & command. name , & command. args , command. external ) ;
272
+ pipeline = pipeline. add_command ( command. build ( env) ?, command. stdin_mode ( ) ) ?;
273
+ }
274
+ if pipeline. is_empty ( ) {
275
+ let command = Command :: internal ( & cat:: META ) ;
276
+ pipeline = pipeline. add_command ( command. build ( env) ?, command. stdin_mode ( ) ) ?;
277
+ }
278
+ }
279
+ } ;
280
+
281
+ Ok ( pipeline)
266
282
}
267
283
268
284
fn forward_input ( context : & Context , mut stdins : Vec < Option < Spawned < ChildStdin > > > ) -> Result < ( ) > {
@@ -291,6 +307,11 @@ fn forward_input(context: &Context, mut stdins: Vec<Option<Spawned<ChildStdin>>>
291
307
Ok ( ( ) )
292
308
}
293
309
310
+ enum Producer {
311
+ Constant ( String ) ,
312
+ Child ( Spawned < LineReader < ChildStdout > > ) ,
313
+ }
314
+
294
315
fn collect_output ( context : & Context , mut producers : Vec < Producer > ) -> Result < ( ) > {
295
316
let mut writer = context. writer ( ) ;
296
317
let mut buffer = context. uninit_buf ( ) ;
@@ -342,111 +363,3 @@ fn wait_children(mut children: Vec<Spawned<Child>>) -> Result<()> {
342
363
343
364
Ok ( ( ) )
344
365
}
345
-
346
- fn build_pipeline (
347
- context : & Context ,
348
- stdbuf : & mut StdBuf ,
349
- shell : & Shell ,
350
- expr : & Expression ,
351
- ) -> Result < Pipeline > {
352
- let raw_expr = format ! ( "{YELLOW}{}{RESET}" , expr. raw_value) ;
353
-
354
- match build_pipeline_internal ( context, stdbuf, shell, expr) {
355
- Ok ( pipeline) => Ok ( pipeline. context ( format ! ( "expression: {raw_expr}" ) ) ) ,
356
- Err ( err) => Err ( err. context ( format ! ( "failed to initialize expression {raw_expr}" ) ) ) ,
357
- }
358
- }
359
-
360
- fn build_pipeline_internal (
361
- context : & Context ,
362
- stdbuf : & mut StdBuf ,
363
- shell : & Shell ,
364
- expr : & Expression ,
365
- ) -> Result < Pipeline > {
366
- let mut pipeline = Pipeline :: new ( expr. stdin_mode ) ;
367
-
368
- match & expr. value {
369
- ExpressionValue :: RawShell ( command) => {
370
- let command = shell. build_command ( command) ;
371
- pipeline = pipeline. command ( command, expr. stdin_mode ) ?;
372
- }
373
- ExpressionValue :: Pipeline ( commands) => {
374
- for command in commands {
375
- let ( command, stdin_mode) = build_command ( context, stdbuf, command) ?;
376
- pipeline = pipeline. command ( command, stdin_mode) ?;
377
- }
378
- if pipeline. is_empty ( ) {
379
- let command = build_default_command ( context) ?;
380
- pipeline = pipeline. command ( command, StdinMode :: Connected ) ?;
381
- }
382
- }
383
- } ;
384
-
385
- Ok ( pipeline)
386
- }
387
-
388
- fn build_command (
389
- context : & Context ,
390
- stdbuf : & mut StdBuf ,
391
- params : & pattern:: Command ,
392
- ) -> Result < ( Command , StdinMode ) > {
393
- let pattern:: Command {
394
- name,
395
- args,
396
- external,
397
- } = params;
398
-
399
- if !external {
400
- if let Some ( meta) = get_meta ( name) {
401
- let command = build_internal_command ( context, Some ( name) , args) ?;
402
- return Ok ( ( command, meta. group . stdin_mode ( ) ) ) ;
403
- }
404
-
405
- if name == crate_name ! ( ) {
406
- if let Some ( ( name, args) ) = args. split_first ( ) {
407
- if let Some ( meta) = get_meta ( name) {
408
- let command = build_internal_command ( context, Some ( name) , args) ?;
409
- return Ok ( ( command, meta. group . stdin_mode ( ) ) ) ;
410
- }
411
- }
412
-
413
- let command = build_internal_command ( context, None , args) ?;
414
- return Ok ( ( command, StdinMode :: Connected ) ) ;
415
- }
416
- }
417
-
418
- let mut command = Command :: new ( name) ;
419
- command. args ( args) ;
420
-
421
- if context. buf_mode ( ) . is_line ( ) {
422
- command. envs ( stdbuf. line_buf_envs ( ) ) ; // libc based programs
423
- command. env ( "PYTHONUNBUFFERED" , "1" ) ; // Python programs
424
- }
425
-
426
- Ok ( ( command, StdinMode :: Connected ) )
427
- }
428
-
429
- fn build_internal_command (
430
- context : & Context ,
431
- name : Option < & str > ,
432
- args : & [ String ] ,
433
- ) -> Result < Command > {
434
- let program = current_exe ( ) . context ( "could not detect current executable" ) ?;
435
- let mut command = Command :: new ( program) ;
436
-
437
- command. env ( ENV_NULL , context. separator ( ) . is_null ( ) . to_string ( ) ) ;
438
- command. env ( ENV_BUF_MODE , context. buf_mode ( ) . to_string ( ) ) ;
439
- command. env ( ENV_BUF_SIZE , context. buf_size ( ) . to_string ( ) ) ;
440
- command. env ( ENV_SPAWNED_BY , get_spawned_by ( META . name ) ) ;
441
-
442
- if let Some ( name) = name {
443
- command. arg ( name) ;
444
- }
445
-
446
- command. args ( args) ;
447
- Ok ( command)
448
- }
449
-
450
- fn build_default_command ( context : & Context ) -> Result < Command > {
451
- build_internal_command ( context, Some ( cat:: META . name ) , & [ ] )
452
- }
0 commit comments