Initial commit
authorCarlhuda <wycats+carl@gmail.com>
Tue, 4 Mar 2014 23:16:18 +0000 (15:16 -0800)
committerCarlhuda <wycats+carl@gmail.com>
Tue, 4 Mar 2014 23:22:44 +0000 (15:22 -0800)
.gitignore [new file with mode: 0644]
DESIGN.md [new file with mode: 0644]
LIBS.md [new file with mode: 0644]
Makefile [new file with mode: 0644]
README.md [new file with mode: 0644]
commands/cargo-rustc/main.rs [new file with mode: 0644]
commands/cargo/main.rs [new file with mode: 0644]
tests/fixtures/hello.rs [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..66cc710
--- /dev/null
@@ -0,0 +1,2 @@
+/target/
+
diff --git a/DESIGN.md b/DESIGN.md
new file mode 100644 (file)
index 0000000..d91d25c
--- /dev/null
+++ b/DESIGN.md
@@ -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
diff --git a/LIBS.md b/LIBS.md
new file mode 100644 (file)
index 0000000..b3a18e9
--- /dev/null
+++ b/LIBS.md
@@ -0,0 +1,5 @@
+A list of libraries we will extract from the implementation as needed:
+
+* Logging
+* More robusts assertions / Matchers
+* Option Parsing
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..04fcba9
--- /dev/null
+++ b/Makefile
@@ -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
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/commands/cargo-rustc/main.rs b/commands/cargo-rustc/main.rs
new file mode 100644 (file)
index 0000000..29bdfab
--- /dev/null
@@ -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)
+  };
+}
diff --git a/commands/cargo/main.rs b/commands/cargo/main.rs
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/fixtures/hello.rs b/tests/fixtures/hello.rs
new file mode 100644 (file)
index 0000000..e7a694f
--- /dev/null
@@ -0,0 +1,3 @@
+fn main() {
+  println!("WINNING");
+}