1+ using CliFx ;
2+ using CliFx . Attributes ;
3+ using CliFx . Infrastructure ;
4+ using System . Net ;
5+ using System . Net . Http . Headers ;
6+
7+ [ Command ( "exec" , Description = "exec command in the app container" ) ]
8+ public class ExecCommand : ApplicationBaseCommand , ICommand
9+ {
10+ [ CommandParameter ( 0 ) ]
11+ public string Command { get ; set ; }
12+
13+ public async ValueTask ExecuteAsync ( IConsole console )
14+ {
15+ var request = new HttpRequestMessage ( ) ;
16+ request . Method = HttpMethod . Put ;
17+ request . Headers . Authorization = new AuthenticationHeaderValue ( "Bearer" , Token ) ;
18+ request . RequestUri = new Uri ( new Uri ( ApiUrl ) , $ "api/application/{ AppId } /exec") ;
19+ var content = new MultipartFormDataContent ( ) ;
20+
21+ foreach ( var command in ParseCmd ( Command ) )
22+ {
23+ content . Add ( new StringContent ( command ) , "command" ) ;
24+ }
25+
26+ if ( console . IsInputRedirected )
27+ {
28+ content . Add ( new StreamContent ( console . Input . BaseStream ) , "file" , "stdin" ) ;
29+ }
30+
31+ request . Content = content ;
32+
33+ var response = await new HttpClient ( ) . SendAsync ( request ) ;
34+
35+ response . EnsureSuccessStatusCode ( ) ;
36+
37+ await response . Content . ReadAsStream ( ) . CopyToAsync ( console . Output . BaseStream ) ;
38+ }
39+
40+ static IEnumerable < string > ParseCmd ( string command )
41+ {
42+ if ( command . Length == 0 )
43+ {
44+ yield break ;
45+ }
46+
47+ var inSubstring = false ;
48+ var start = 0 ;
49+ var inEncaps = false ;
50+
51+ for ( int i = 0 ; i < command . Length ; i ++ )
52+ {
53+ if ( inEncaps )
54+ {
55+ inEncaps = false ;
56+ continue ;
57+ }
58+
59+ var ch = command [ i ] ;
60+
61+ if ( inSubstring )
62+ {
63+ if ( ch == '"' || ch == '\' ' )
64+ {
65+ inSubstring = false ;
66+ yield return Trim ( command [ start ..i ] ) ;
67+ start = i + 1 ;
68+ }
69+ continue ;
70+ }
71+
72+ if ( ch == ' ' || ch == '\t ' )
73+ {
74+ if ( i == start || command [ start ] == ' ' || command [ start ] == '\t ' )
75+ {
76+ start = i + 1 ;
77+ }
78+ else
79+ {
80+ yield return Trim ( command [ start ..i ] ) ;
81+ start = i + 1 ;
82+ }
83+ }
84+ else if ( ch == '"' || ch == '\' ' )
85+ {
86+ inSubstring = true ;
87+ if ( ( i - start ) >= 1 )
88+ {
89+ yield return Trim ( command [ start ..i ] ) ;
90+ }
91+ start = i + 1 ;
92+ }
93+ else if ( ch == '\\ ' )
94+ {
95+ inEncaps = true ;
96+ }
97+ }
98+
99+ if ( ( command . Length - 1 ) >= start && command . Last ( ) != '"' && command . Last ( ) != '\' ' )
100+ {
101+ yield return Trim ( command . Substring ( start ) ) ;
102+ }
103+ else if ( start == 0 && command . Length > 0 )
104+ {
105+ yield return Trim ( command . Substring ( start ) ) ;
106+ }
107+ else if ( start == 0 && command . Length == 1 )
108+ {
109+ yield return command ;
110+ }
111+
112+ string Trim ( string input )
113+ {
114+ return input . Replace ( "\\ '" , "'" ) . Replace ( "\\ \" " , "\" " ) . Replace ( "\\ \\ " , "\\ " ) ;
115+ }
116+ }
117+ }
0 commit comments