22
33use assert_cmd:: cargo:: { self , cargo_bin_cmd} ;
44use assert_cmd:: cmd:: Command ;
5+ use std:: io:: Write ;
56use std:: path:: PathBuf ;
6- use tempfile:: { Builder , TempDir } ;
7+ use std:: { env, fs, io} ;
8+ use tempfile:: { Builder , NamedTempFile , TempDir } ;
79
810#[ derive( Debug ) ]
911pub enum Error {
1012 Which ( which:: Error ) ,
11- IO ( std :: io:: Error ) ,
13+ IO ( io:: Error ) ,
1214 Regex ( regex:: Error ) ,
1315 GenericError ( String ) ,
1416}
1517
16- impl From < std :: io:: Error > for Error {
17- fn from ( err : std :: io:: Error ) -> Self {
18+ impl From < io:: Error > for Error {
19+ fn from ( err : io:: Error ) -> Self {
1820 Self :: IO ( err)
1921 }
2022}
@@ -64,7 +66,7 @@ impl Csm {
6466 command
6567 }
6668
67- pub fn ext_command ( & self , bin : PathBuf ) -> Command {
69+ pub fn ext_command ( & self , bin : & str ) -> Command {
6870 let mut command = Command :: new ( bin) ;
6971 self . prepare_command ( & mut command) ;
7072
@@ -76,7 +78,7 @@ impl Csm {
7678 . to_string_lossy ( )
7779 . replace ( "\\ " , "/" ) ;
7880 let separator = if cfg ! ( windows) { ";" } else { ":" } ;
79- let path = match std :: env:: var ( "PATH" ) {
81+ let path = match env:: var ( "PATH" ) {
8082 Ok ( path) => format ! ( "{}{}{}" , path, separator, csm_bin_dir) ,
8183 Err ( _) => csm_bin_dir,
8284 } ;
@@ -85,8 +87,48 @@ impl Csm {
8587 command
8688 }
8789
88- pub fn write_csmrc ( & self , config : & str ) -> Result < ( ) , std:: io:: Error > {
89- std:: fs:: write ( self . home_dir . path ( ) . join ( ".csmrc" ) , config)
90+ /// Similar to `ext_command`, but stores a script in a temporary file
91+ /// (outside of the temporary home directory).
92+ ///
93+ /// This primarily exists because when reading from stdin, PowerShell will
94+ /// by default insist on displaying its prompt and name banner, unlike every
95+ /// other shell in existence.
96+ pub fn run_script ( & self , bin : & str , script : & str , suffix : & str ) -> io:: Result < ScriptCommand > {
97+ let mut tmpfile = NamedTempFile :: with_suffix ( suffix) ?;
98+ writeln ! ( tmpfile, "{}" , script) ?;
99+ let mut cmd = self . ext_command ( bin) ;
100+ cmd. arg ( tmpfile. path ( ) ) ;
101+ Ok ( ScriptCommand {
102+ command : cmd,
103+ _tmpfile : tmpfile,
104+ } )
105+ }
106+
107+ pub fn write_csmrc ( & self , config : & str ) -> Result < ( ) , io:: Error > {
108+ fs:: write ( self . home_dir . path ( ) . join ( ".csmrc" ) , config)
109+ }
110+ }
111+
112+ /// This exists only to make sure that the tmpfile doesn't get dropped
113+ /// prematurely from Csm.run_script(). The tmpfile will get dropped when the
114+ /// reference to it goes away - so we need a way to keep the reference around
115+ /// with the Command that we return.
116+ pub struct ScriptCommand {
117+ pub command : Command ,
118+ _tmpfile : NamedTempFile ,
119+ }
120+
121+ impl std:: ops:: Deref for ScriptCommand {
122+ type Target = Command ;
123+
124+ fn deref ( & self ) -> & Self :: Target {
125+ & self . command
126+ }
127+ }
128+
129+ impl std:: ops:: DerefMut for ScriptCommand {
130+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
131+ & mut self . command
90132 }
91133}
92134
0 commit comments