8282#![ doc( html_root_url = "https://docs.rs/jobserver/0.1" ) ]
8383
8484use std:: env;
85+ use std:: ffi:: OsString ;
8586use std:: io;
8687use std:: process:: Command ;
8788use std:: sync:: { Arc , Condvar , Mutex , MutexGuard } ;
8889
90+ mod error;
8991#[ cfg( unix) ]
9092#[ path = "unix.rs" ]
9193mod imp;
@@ -151,40 +153,30 @@ struct HelperInner {
151153 consumer_done : bool ,
152154}
153155
154- /// Error type for `from_env` function.
156+ use error:: FromEnvErrorInner ;
157+ pub use error:: { FromEnvError , FromEnvErrorKind } ;
158+
159+ /// Return type for `from_env_ext` function.
155160#[ derive( Debug ) ]
156- pub enum ErrFromEnv {
157- /// There isn't env var, that describes jobserver to inherit.
158- IsNotConfigured ,
159- /// Cannot connect following this process's environment.
160- PlatformSpecific {
161- /// Error.
162- err : io:: Error ,
163- /// Name of gotten env var.
164- env : & ' static str ,
165- /// Value of gotten env var.
166- var : String ,
167- } ,
161+ pub struct FromEnv {
162+ /// Result of trying to get jobserver client from env.
163+ pub client : Result < Client , FromEnvError > ,
164+ /// Name and value of the environment variable.
165+ /// `None` if no relevant environment variable is found.
166+ pub var : Option < ( & ' static str , OsString ) > ,
168167}
169168
170- impl std:: fmt:: Display for ErrFromEnv {
171- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
172- match self {
173- ErrFromEnv :: IsNotConfigured => {
174- write ! ( f, "couldn't find relevant environment variable" )
175- }
176- ErrFromEnv :: PlatformSpecific { err, env, var } => {
177- write ! ( f, "{err} ({env}={var}" )
178- }
169+ impl FromEnv {
170+ fn new_ok ( client : Client , var_name : & ' static str , var_value : OsString ) -> FromEnv {
171+ FromEnv {
172+ client : Ok ( client) ,
173+ var : Some ( ( var_name, var_value) ) ,
179174 }
180175 }
181- }
182-
183- impl std:: error:: Error for ErrFromEnv {
184- fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
185- match self {
186- ErrFromEnv :: IsNotConfigured => None ,
187- ErrFromEnv :: PlatformSpecific { err, .. } => Some ( err) ,
176+ fn new_err ( kind : FromEnvErrorInner , var_name : & ' static str , var_value : OsString ) -> FromEnv {
177+ FromEnv {
178+ client : Err ( FromEnvError { inner : kind } ) ,
179+ var : Some ( ( var_name, var_value) ) ,
188180 }
189181 }
190182}
@@ -234,10 +226,10 @@ impl Client {
234226 ///
235227 /// # Return value
236228 ///
229+ /// `FromEnv` contains result and relevant environment variable.
237230 /// If a jobserver was found in the environment and it looks correct then
238- /// `Ok` of the connected client will be returned. If no relevant env var
239- /// was found then `Err(IsNotConfigured)` will be returned. In other cases
240- /// `Err(PlatformSpecific)` will be returned.
231+ /// result with the connected client will be returned. In other cases
232+ /// result will contain `Err(FromEnvErr)`.
241233 ///
242234 /// Note that on Unix the `Client` returned **takes ownership of the file
243235 /// descriptors specified in the environment**. Jobservers on Unix are
@@ -250,8 +242,8 @@ impl Client {
250242 /// with `CLOEXEC` so they're not automatically inherited by spawned
251243 /// children.
252244 ///
253- /// On unix if `unix_check_is_pipe ` enabled this function will check if
254- /// provided files are actually pipes.
245+ /// On unix if `check_pipe ` enabled this function will check if provided
246+ /// files are actually pipes.
255247 ///
256248 /// # Safety
257249 ///
@@ -269,27 +261,42 @@ impl Client {
269261 ///
270262 /// Note, though, that on Windows it should be safe to call this function
271263 /// any number of times.
272- pub unsafe fn from_env_ext ( check_pipe : bool ) -> Result < Client , ErrFromEnv > {
273- let ( env, var ) = [ "CARGO_MAKEFLAGS" , "MAKEFLAGS" , "MFLAGS" ]
264+ pub unsafe fn from_env_ext ( check_pipe : bool ) -> FromEnv {
265+ let ( env, var_os ) = match [ "CARGO_MAKEFLAGS" , "MAKEFLAGS" , "MFLAGS" ]
274266 . iter ( )
275- . map ( |& env| env:: var ( env) . map ( |var| ( env, var) ) )
276- . find_map ( |p| p. ok ( ) )
277- . ok_or ( ErrFromEnv :: IsNotConfigured ) ?;
267+ . map ( |& env| env:: var_os ( env) . map ( |var| ( env, var) ) )
268+ . find_map ( |p| p)
269+ {
270+ Some ( ( env, var_os) ) => ( env, var_os) ,
271+ None => return FromEnv :: new_err ( FromEnvErrorInner :: NoEnvVar , "" , Default :: default ( ) ) ,
272+ } ;
273+
274+ let var = match var_os. to_str ( ) {
275+ Some ( var) => var,
276+ None => {
277+ let err = FromEnvErrorInner :: CannotParse ( "not valid UTF-8" . to_string ( ) ) ;
278+ return FromEnv :: new_err ( err, env, var_os) ;
279+ }
280+ } ;
278281
279- let ( arg, pos) = [ "--jobserver-fds=" , "--jobserver-auth=" ]
282+ let ( arg, pos) = match [ "--jobserver-fds=" , "--jobserver-auth=" ]
280283 . iter ( )
281284 . map ( |& arg| var. find ( arg) . map ( |pos| ( arg, pos) ) )
282285 . find_map ( |pos| pos)
283- . ok_or ( ErrFromEnv :: IsNotConfigured ) ?;
286+ {
287+ Some ( ( arg, pos) ) => ( arg, pos) ,
288+ None => {
289+ let err = FromEnvErrorInner :: CannotParse (
290+ "expected `--jobserver-fds=` or `--jobserver-auth=`" . to_string ( ) ,
291+ ) ;
292+ return FromEnv :: new_err ( err, env, var_os) ;
293+ }
294+ } ;
284295
285296 let s = var[ pos + arg. len ( ) ..] . split ( ' ' ) . next ( ) . unwrap ( ) ;
286- #[ cfg( unix) ]
287- let imp_client = imp:: Client :: open ( s, check_pipe) ;
288- #[ cfg( not( unix) ) ]
289- let imp_client = imp:: Client :: open ( s) ;
290- match imp_client {
291- Ok ( c) => Ok ( Client { inner : Arc :: new ( c) } ) ,
292- Err ( err) => Err ( ErrFromEnv :: PlatformSpecific { err, env, var } ) ,
297+ match imp:: Client :: open ( s, check_pipe) {
298+ Ok ( c) => FromEnv :: new_ok ( Client { inner : Arc :: new ( c) } , env, var_os) ,
299+ Err ( err) => FromEnv :: new_err ( err, env, var_os) ,
293300 }
294301 }
295302
@@ -298,7 +305,7 @@ impl Client {
298305 ///
299306 /// Wraps `from_env_ext` and discards error details.
300307 pub unsafe fn from_env ( ) -> Option < Client > {
301- Self :: from_env_ext ( false ) . ok ( )
308+ Self :: from_env_ext ( false ) . client . ok ( )
302309 }
303310
304311 /// Acquires a token from this jobserver client.
0 commit comments