1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
//! Defines methods for spawning commands into futures.

use ExitStatus;
use future::{Async, EnvFuture, Poll};
use future_ext::{EnvFutureExt, FlattenedEnvFuture};
use futures::Future;

mod and_or;
mod case;
mod for_cmd;
mod func_exec;
mod if_cmd;
mod local_redirections;
mod loop_cmd;
mod pipeline;
mod rc;
mod sequence;
mod simple;
mod subshell;
mod substitution;
mod swallow_non_fatal;
mod vec_sequence;

pub mod builtin;
#[cfg(feature = "conch-parser")]
pub mod ast_impl;

// Private definitions
use self::vec_sequence::{VecSequence, VecSequenceWithLast};

// Pub reexports
pub use self::and_or::{AndOr, AndOrList, and_or_list};
pub use self::case::{Case, case, PatternBodyPair};
pub use self::for_cmd::{For, ForArgs, for_args, for_loop, for_with_args};
pub use self::func_exec::{Function, function, function_body};
pub use self::if_cmd::{If, if_cmd};
pub use self::local_redirections::{LocalRedirections, spawn_with_local_redirections};
pub use self::loop_cmd::{Loop, loop_cmd};
pub use self::pipeline::{Pipeline, pipeline, SpawnedPipeline};
pub use self::sequence::{Sequence, sequence};
pub use self::simple::{SimpleCommand, simple_command, SpawnedSimpleCommand};
pub use self::subshell::{Subshell, subshell};
pub use self::substitution::{Substitution, SubstitutionEnvFuture, substitution};
pub use self::swallow_non_fatal::{SwallowNonFatal, swallow_non_fatal_errors};

/// A trait for spawning commands into an `EnvFuture` which can be
/// polled to completion.
///
/// Spawning a command is separated into two distinct parts: a future
/// that requires a mutable environment to make progress, and a future
/// which no longer needs any context and can make progress on its own.
///
/// This distinction allows a caller to drop an environment as soon as
/// it is no longer needed, which will free up resources, and especially
/// important in preventing deadlocks between pipelines (since the parent
/// process will contain extra reader/writer ends of a pipe and may prevent
/// processes from exiting).
pub trait Spawn<E: ?Sized> {
    /// The future that represents spawning the command.
    ///
    /// It represents all computations that may need an environment to
    /// progress further.
    type EnvFuture: EnvFuture<E, Item = Self::Future, Error = Self::Error>;
    /// The future that represents the exit status of a fully bootstrapped
    /// command, which no longer requires an environment to be driven to completion.
    type Future: Future<Item = ExitStatus, Error = Self::Error>;
    /// The type of error that a future will resolve with if it fails in a
    /// normal fashion.
    type Error;

    /// Spawn the command as a future.
    ///
    /// Although the implementation is free to make any optimizations or
    /// pre-computations, there should be no observable side-effects until the
    /// very first call to `poll` on the future. That way a constructed future
    /// that was never `poll`ed could be dropped without the risk of unintended
    /// side effects.
    ///
    /// **Note**: There are no guarantees that the environment will not change
    /// between the `spawn` invocation and the first call to `poll()` on the
    /// future. Thus any optimizations the implementation may decide to make
    /// based on the environment should be done with care.
    fn spawn(self, env: &E) -> Self::EnvFuture;
}

impl<'a, 'b: 'a, T, E: ?Sized> Spawn<E> for &'a &'b T
    where &'b T: Spawn<E>
{
    type EnvFuture = <&'b T as Spawn<E>>::EnvFuture;
    type Future = <&'b T as Spawn<E>>::Future;
    type Error = <&'b T as Spawn<E>>::Error;

    fn spawn(self, env: &E) -> Self::EnvFuture {
        (*self).spawn(env)
    }
}

#[cfg_attr(feature = "clippy", allow(boxed_local))]
impl<E: ?Sized, T: Spawn<E>> Spawn<E> for Box<T> {
    type EnvFuture = T::EnvFuture;
    type Future = T::Future;
    type Error = T::Error;

    fn spawn(self, env: &E) -> Self::EnvFuture {
        (*self).spawn(env)
    }
}

#[cfg_attr(feature = "clippy", allow(boxed_local))]
impl<'a, E: ?Sized, T: 'a> Spawn<E> for &'a Box<T>
    where &'a T: Spawn<E>,
{
    type EnvFuture = <&'a T as Spawn<E>>::EnvFuture;
    type Future = <&'a T as Spawn<E>>::Future;
    type Error = <&'a T as Spawn<E>>::Error;

    fn spawn(self, env: &E) -> Self::EnvFuture {
        Spawn::spawn(&**self, env)
    }
}

/// A marker trait for denoting that the receiver of a `Spawn` implementation
/// can also be `spawn`ed by reference without moving. Automatically derived
/// for any `&'a T: Spawn`.
///
/// Until Associated Type Constructors (ATCs) land, we cannot define a version
/// of `Spawn` which takes the receiver by reference since there is no way we
/// reference the receiver's lifetime within the associated futures.
///
/// We can, however, get around this by defining `Spawn` to move its receiver,
/// and then implementing the trait directly on a reference (this moves the
/// reference, but references are `Copy` which is effectively a no-op). That way
/// we can tie the associated futures to the lifetime of the reference since
/// neither can outlive the actual struct.
///
/// This effectively gives rise to two `Spawn` implementations we can add on each
/// type: one that moves the caller and any inner types by value, and one that
/// operates on the outer and inner types by reference only. As long as we don't
/// mix the two kinds, we're golden!
///
/// Except there are situations where we may want to own a type directly, but
/// want to spawn it by reference (imagine we're running a loop on an "owned"
/// implementation chain and need to spawn something repeatedly, but we don't
/// want to clone deeply nested types)... Unfortunately, doing so confuses the
/// compiler which causes it to get stuck in a recursive loop when evaluating
/// bounds (error is `E0275` with a message like "required by the impl for
/// `&T<_>` because of the requirements on the impl for `&T<T<_>>`,
/// `&T<T<T<_>>>`, ...").
///
/// We can apparently point the compiler in the right direction by adding a
/// marker trait only when `Spawn` is implemented directly on a reference,
/// allowing it to avoid the first "owned" implementation on the same type.
pub trait SpawnRef<E: ?Sized> {
    /// The future that represents spawning the command.
    ///
    /// It represents all computations that may need an environment to
    /// progress further.
    type EnvFuture: EnvFuture<E, Item = Self::Future, Error = Self::Error>;
    /// The future that represents the exit status of a fully bootstrapped
    /// command, which no longer requires an environment to be driven to completion.
    type Future: Future<Item = ExitStatus, Error = Self::Error>;
    /// The type of error that a future will resolve with if it fails in a
    /// normal fashion.
    type Error;

    /// Identical to `Spawn::spawn` but does not move `self`.
    fn spawn_ref(&self, env: &E) -> Self::EnvFuture;
}

/// A marker trait for any reference.
pub trait Ref: Copy {}
impl<'a, T> Ref for &'a T {}

impl<S, E: ?Sized> SpawnRef<E> for S
    where S: Spawn<E> + Ref,
{
    type EnvFuture = S::EnvFuture;
    type Future = S::Future;
    type Error = S::Error;

    fn spawn_ref(&self, env: &E) -> Self::EnvFuture {
        (*self).spawn(env)
    }
}

/// Type alias for boxed futures that represent spawning a command.
pub type BoxSpawnEnvFuture<'a, E, ERR> = Box<'a + EnvFuture<
    E,
    Item = BoxStatusFuture<'a, ERR>,
    Error = ERR
>>;

/// Type alias for a boxed future which will resolve to an `ExitStatus`.
pub type BoxStatusFuture<'a, ERR> = Box<'a + Future<Item = ExitStatus, Error = ERR>>;

/// A trait for spawning commands (without moving ownership) into boxed futures.
/// Largely useful for having spawnable trait objects.
pub trait SpawnBoxed<E: ?Sized> {
    /// The type of error that a future will resolve with if it fails in a
    /// normal fashion.
    type Error;

    /// Identical to `Spawn::spawn` but does not move `self` and returns boxed futures.
    fn spawn_boxed<'a>(&'a self, env: &E) -> BoxSpawnEnvFuture<'a, E, Self::Error> where E: 'a;
}

impl<S, ERR, E: ?Sized> SpawnBoxed<E> for S
    where for<'a> &'a S: Spawn<E, Error = ERR>,
{
    type Error = ERR;

    fn spawn_boxed<'a>(&'a self, env: &E) -> BoxSpawnEnvFuture<'a, E, Self::Error> where E: 'a {
        Box::from(self.spawn(env).boxed_result())
    }
}

/// Represents either a ready `ExitStatus` or a future that will resolve to one.
#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
pub enum ExitResult<F> {
    /// An unresolved future.
    Pending(F),
    /// A ready `ExitStatus` value.
    Ready(ExitStatus),
}

impl<F> From<ExitStatus> for ExitResult<F> {
    fn from(status: ExitStatus) -> Self {
        ExitResult::Ready(status)
    }
}

impl<F> Future for ExitResult<F>
    where F: Future<Item = ExitStatus>
{
    type Item = F::Item;
    type Error = F::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match *self {
            ExitResult::Pending(ref mut f) => f.poll(),
            ExitResult::Ready(exit) => Ok(Async::Ready(exit)),
        }
    }
}

/// A grouping of guard and body commands.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct GuardBodyPair<T> {
    /// The guard commands, which if successful, should lead to the
    /// execution of the body commands.
    pub guard: T,
    /// The body commands to execute if the guard is successful.
    pub body: T,
}