Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Carlhuda committed Mar 4, 2014
0 parents commit 227d4e8
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target/

152 changes: 152 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
## Subcommands

The top-level `cargo` command delegates to sub-commands named
`cargo-foo`.

```
$ cargo compile
# delegates to cargo-compile
```

By default, Cargo will come with a set of built-in commands that don't
need to be on the `$PATH`, but additional commands can be added to the
`$PATH`.

There will also be an additional configuration for locating Cargo
subcommands that are not on the `$PATH`.

### Input/Output

By default, Cargo subcommands are built by implementing the
`CargoCommand` trait. This trait will pass structured data to the
command.

By default, commands will communicate with each other via JSON data, and
the `CargoCommand` trait will convert the JSON data into the structured
data needed by the command. All commands must implement JSON data
output.

Commands must also implement human-readable output, and may implement
additional output forms (such as tab- or space-separated output) for use
in other scripting languages.

```rs
// The main entry point for new commands to implement
trait CargoCommand<T, U> {
fn execute<L: CargoLogger>(input: T, logger: L) -> Result<U, CargoErr>;
}

// For now, the raw IPC communication is represented as JSON primitive
// values. The ConvertToRaw trait below converts a string protocol into the
// Raw format. Obviously, the JSON string protocol can trivially be
// converted, but other line protocols need to be defined on a
// case-by-case basis.
type Raw = serialize::json::Json;
type Flags = Map<~str, serialize::json::Json>

// This is a list of available IPC String protocols. To start, we'll
// support JSON and an (optional) arbitrary type-defined line protocol.
enum Input {
JSONString(~str),
LineOrientedString(~str)
}

// This trait supports converting any supported input form into Raw.
trait ConvertToRaw<Input> {
fn convert(input: Input) -> Raw;
}

// This is the runner implementation. It will not need to be implemented
// by individual commands.
fn execute_command<Config, Output, C: CargoCommand, L: Logger>(command: C, config: Config, logger: L) -> Output {
match command.execute(input, logger) {
Ok(success) => {
// serialize success
},
Err(failure) => {
// error handling/output
}
}
}

// This is an example configuration. It is the combination of the Raw
// input from a previous command and any flags passed to this command.
// Top-level commands will mostly be configured via flags -- plumbing
// commands will be mostly configured via Raw.
//
// Note that because configurations serve as both input and output, and
// the ConvertToRaw trait handles both sides of the pipe, these definitions
// are not part of an individual command. Some configuration structures
// may even be used by multiple different commands.
struct CompileConfig {
flags: ~[~str],
path: ~[~str],
lib_path: ~str
}

struct CompileConfigBuilder {
flags: Option<~[~str]>,
path: Option<~[~str]>,
lib_path: Option<~str>
}

// For now, configurations manually convert the Flags and Raw into a
// single configuration object. This is the main point where a failure
// can occur that is not type-checked. All other functions receive the
// structured type and will get compiler help.
impl CompileConfig {
pub fn deserialize(flags: Flags, raw: Raw) -> CompileConfig {
CompileConfig{ flags: raw.at("flags"), path: raw.at("path"), lib_path: flags.at("lib_path") }
}
}

// Configurations must implement ConvertIntoRaw<JSONString> and may
// implement other ConvertIntoRaw converters.
impl ConvertToRaw<JSONString> for CompileConfig {
fn convert(input: JSONString) -> Raw {

}
}

impl ConvertToRaw<LineOrientedString> for CompileConfig {
fn convert(input: LineOrientedString) -> Raw {

}
}

impl ConvertFlags for CompileConfig {
fn convert(input: FlagDefinition) -> Flags {

}
}

// Commands are simple objects that implement CargoCommand for a given
struct CompileCommand;

impl CompileCommand {
fn new() -> CompileCommand { CompileCommand }
}

impl CargoCommand<CompileConfig, CompileOutput> for CompileCommand {
fn execute<L: CargoLogger>(input: CompileConfig, logger: L) -> Result<CompileOutput, CargoErr>;

}
}

fn main() {
let args = parse_arguments(f);
let config = process_args_and_stdin(args); // { "flags": [ ... ] }
let command = CompileCommand::new()
let logger = CargoLogger::for(config);
let result = execute_command(command, config, logger);

// deal with serialized output or error
}

fn process_args_and_stdin(args: Flags) -> CompileConfig {
// delegate to other generic function; Flags tells us which serializer
// to use
}
```

## Configuration
5 changes: 5 additions & 0 deletions LIBS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
A list of libraries we will extract from the implementation as needed:

* Logging
* More robusts assertions / Matchers
* Option Parsing
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
RUSTC_TARGET = target
RUSTC_FLAGS ?= --out-dir $(RUSTC_TARGET)

default: target/cargo-rustc

clean:
rm -rf target

target/cargo-rustc: target commands/cargo-rustc/main.rs
rustc commands/cargo-rustc/main.rs $(RUSTC_FLAGS)

target:
mkdir -p $(RUSTC_TARGET)

.PHONY: default clean
Empty file added README.md
Empty file.
32 changes: 32 additions & 0 deletions commands/cargo-rustc/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#[crate_id="cargo-rustc"];

use std::os::args;
use std::io::process::Process;

/**
cargo-rustc -- ...args
Delegate ...args to actual rustc command
*/

fn main() {
let mut arguments = args();
arguments.shift();

if arguments[0] != ~"--" {
fail!("LOL");
} else {
arguments.shift();
}

match Process::new("rustc", arguments.as_slice()) {
Ok(mut process) => {
let stdout = process.stdout.get_mut_ref();
println!("output: {:s}", stdout.read_to_str().unwrap());

let stderr = process.stderr.get_mut_ref();
println!("err: {:s}", stderr.read_to_str().unwrap());
},
Err(e) => fail!("Failed to execute: {}", e)
};
}
Empty file added commands/cargo/main.rs
Empty file.
3 changes: 3 additions & 0 deletions tests/fixtures/hello.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("WINNING");
}

0 comments on commit 227d4e8

Please sign in to comment.