mirror of
https://github.com/rust-lang/cargo
synced 2024-10-13 19:22:33 +00:00
Initial work on the git source
This commit is contained in:
parent
ca668c6605
commit
452654250d
5
Makefile
5
Makefile
|
@ -3,10 +3,11 @@ RUSTC_FLAGS ?=
|
|||
|
||||
# Link flags to pull in dependencies
|
||||
BINS = cargo \
|
||||
cargo-compile \
|
||||
cargo-compile \
|
||||
cargo-read-manifest \
|
||||
cargo-rustc \
|
||||
cargo-verify-project
|
||||
cargo-verify-project \
|
||||
cargo-git-checkout \
|
||||
|
||||
SRC = $(shell find src -name '*.rs')
|
||||
|
||||
|
|
34
src/bin/cargo-git-checkout.rs
Normal file
34
src/bin/cargo-git-checkout.rs
Normal file
|
@ -0,0 +1,34 @@
|
|||
#![crate_id="cargo-git-checkout"]
|
||||
|
||||
extern crate cargo;
|
||||
extern crate serialize;
|
||||
extern crate hammer;
|
||||
extern crate url;
|
||||
|
||||
use hammer::FlagConfig;
|
||||
use cargo::{execute_main_without_stdin,CLIResult,CLIError,ToResult};
|
||||
use cargo::core::Package;
|
||||
use cargo::util::{Require,ToCLI,simple_human};
|
||||
use cargo::sources::git::{GitCommand,GitRepo};
|
||||
use url::Url;
|
||||
|
||||
#[deriving(Eq,Clone,Decodable)]
|
||||
struct Options {
|
||||
directory: StrBuf,
|
||||
url: StrBuf,
|
||||
reference: StrBuf
|
||||
}
|
||||
|
||||
impl FlagConfig for Options {}
|
||||
|
||||
fn main() {
|
||||
execute_main_without_stdin(execute);
|
||||
}
|
||||
|
||||
fn execute(options: Options) -> CLIResult<Option<GitRepo>> {
|
||||
let url: Url = try!(from_str(options.url.as_slice()).to_result(|_|
|
||||
CLIError::new(format!("The URL `{}` you passed was not a valid URL", options.url), None::<&str>, 1)));
|
||||
|
||||
let cmd = GitCommand::new(Path::new(options.directory.clone()), url, options.reference);
|
||||
cmd.checkout().to_cli(1).map(|repo| Some(repo))
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
#![feature(macro_rules)]
|
||||
|
||||
extern crate collections;
|
||||
extern crate url;
|
||||
extern crate hammer;
|
||||
extern crate serialize;
|
||||
extern crate semver;
|
||||
|
|
103
src/cargo/sources/git.rs
Normal file
103
src/cargo/sources/git.rs
Normal file
|
@ -0,0 +1,103 @@
|
|||
use url::Url;
|
||||
use util::{CargoResult,ProcessBuilder,io_error,human_error,process};
|
||||
use std::str;
|
||||
use std::io::UserDir;
|
||||
use std::io::fs::mkdir_recursive;
|
||||
use serialize::{Encodable,Encoder};
|
||||
|
||||
macro_rules! git(
|
||||
($config:expr, $str:expr, $($rest:expr),*) => (
|
||||
try!(git_inherit($config, format_strbuf!($str, $($rest),*)))
|
||||
);
|
||||
)
|
||||
|
||||
macro_rules! git_output(
|
||||
($config:expr, $str:expr, $($rest:expr),*) => (
|
||||
try!(git_output($config, format_strbuf!($str, $($rest),*)))
|
||||
);
|
||||
)
|
||||
|
||||
#[deriving(Eq,Clone)]
|
||||
struct GitConfig {
|
||||
path: Path,
|
||||
uri: Url,
|
||||
reference: StrBuf
|
||||
}
|
||||
|
||||
#[deriving(Eq,Clone,Encodable)]
|
||||
struct EncodableGitConfig {
|
||||
path: StrBuf,
|
||||
uri: StrBuf,
|
||||
reference: StrBuf
|
||||
}
|
||||
|
||||
impl<E, S: Encoder<E>> Encodable<S, E> for GitConfig {
|
||||
fn encode(&self, s: &mut S) -> Result<(), E> {
|
||||
EncodableGitConfig {
|
||||
path: format_strbuf!("{}", self.path.display()),
|
||||
uri: format_strbuf!("{}", self.uri),
|
||||
reference: self.reference.clone()
|
||||
}.encode(s)
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Eq,Clone)]
|
||||
pub struct GitCommand {
|
||||
config: GitConfig
|
||||
}
|
||||
|
||||
#[deriving(Eq,Clone,Encodable)]
|
||||
pub struct GitRepo {
|
||||
config: GitConfig,
|
||||
revision: StrBuf
|
||||
}
|
||||
|
||||
impl GitCommand {
|
||||
pub fn new(path: Path, uri: Url, reference: StrBuf) -> GitCommand {
|
||||
GitCommand { config: GitConfig { path: path, uri: uri, reference: reference } }
|
||||
}
|
||||
|
||||
pub fn checkout(&self) -> CargoResult<GitRepo> {
|
||||
let config = &self.config;
|
||||
|
||||
if config.path.exists() {
|
||||
git!(config, "fetch --force --quiet --tags {} refs/heads/*:refs/heads/*", config.uri);
|
||||
} else {
|
||||
let dirname = Path::new(config.path.dirname());
|
||||
let mut checkout_config = self.config.clone();
|
||||
checkout_config.path = dirname;
|
||||
|
||||
try!(mkdir_recursive(&checkout_config.path, UserDir).map_err(|err|
|
||||
human_error(format_strbuf!("Couldn't recursively create `{}`", checkout_config.path.display()), format_strbuf!("path={}", checkout_config.path.display()), io_error(err))));
|
||||
|
||||
git!(&checkout_config, "clone {} {} --bare --no-hardlinks --quiet", config.uri, config.path.display());
|
||||
}
|
||||
|
||||
Ok(GitRepo { config: config.clone(), revision: try!(rev_for(config)) })
|
||||
}
|
||||
}
|
||||
|
||||
fn rev_for(config: &GitConfig) -> CargoResult<StrBuf> {
|
||||
Ok(git_output!(config, "rev-parse {}", config.reference))
|
||||
}
|
||||
|
||||
fn git(config: &GitConfig, str: &str) -> ProcessBuilder {
|
||||
println!("Executing git {} @ {}", str, config.path.display());
|
||||
process("git").args(str.split(' ').collect::<Vec<&str>>().as_slice()).cwd(config.path.clone())
|
||||
}
|
||||
|
||||
fn git_inherit(config: &GitConfig, str: StrBuf) -> CargoResult<()> {
|
||||
git(config, str.as_slice()).exec().map_err(|err|
|
||||
human_error(format_strbuf!("Couldn't execute `git {}`: {}", str, err), None::<&str>, err))
|
||||
}
|
||||
|
||||
fn git_output(config: &GitConfig, str: StrBuf) -> CargoResult<StrBuf> {
|
||||
let output = try!(git(config, str.as_slice()).exec_with_output().map_err(|err|
|
||||
human_error(format_strbuf!("Couldn't execute `git {}`", str), None::<&str>, err)));
|
||||
|
||||
Ok(to_str(output.output.as_slice()))
|
||||
}
|
||||
|
||||
fn to_str(vec: &[u8]) -> StrBuf {
|
||||
format_strbuf!("{}", str::from_utf8_lossy(vec))
|
||||
}
|
|
@ -1 +1,2 @@
|
|||
pub mod path;
|
||||
pub mod git;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
pub use self::process_builder::{process,ProcessBuilder};
|
||||
pub use self::result::{CargoError,CargoResult,Wrap,Require,ToCLI,other_error,human_error,toml_error,io_error,process_error};
|
||||
pub use self::result::{CargoError,CargoResult,Wrap,Require,ToCLI,other_error,human_error,simple_human,toml_error,io_error,process_error};
|
||||
|
||||
pub mod graph;
|
||||
pub mod process_builder;
|
||||
|
|
|
@ -31,8 +31,8 @@ impl Show for ProcessBuilder {
|
|||
static PATH_SEP : &'static str = ":";
|
||||
|
||||
impl ProcessBuilder {
|
||||
pub fn args(mut self, arguments: &[StrBuf]) -> ProcessBuilder {
|
||||
self.args = Vec::from_slice(arguments);
|
||||
pub fn args<T: Show>(mut self, arguments: &[T]) -> ProcessBuilder {
|
||||
self.args = arguments.iter().map(|a| format_strbuf!("{}", a)).collect();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -42,15 +42,24 @@ pub fn process_error(detail: StrBuf, exit: ProcessExit, output: Option<ProcessOu
|
|||
}
|
||||
}
|
||||
|
||||
pub fn human_error(desc: StrBuf, detail: StrBuf, cause: CargoError) -> CargoError {
|
||||
pub fn human_error<T: ToStr, U: ToStr>(desc: T, detail: U, cause: CargoError) -> CargoError {
|
||||
CargoError {
|
||||
kind: HumanReadableError,
|
||||
desc: BoxedDescription(desc),
|
||||
detail: Some(detail),
|
||||
desc: BoxedDescription(desc.to_str().to_strbuf()),
|
||||
detail: Some(detail.to_str().to_strbuf()),
|
||||
cause: Some(box cause)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn simple_human<T: Show>(desc: T) -> CargoError {
|
||||
CargoError {
|
||||
kind: HumanReadableError,
|
||||
desc: BoxedDescription(format_strbuf!("{}", desc)),
|
||||
detail: None,
|
||||
cause: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toml_error(desc: &'static str, error: toml::Error) -> CargoError {
|
||||
CargoError {
|
||||
kind: TomlError(error),
|
||||
|
|
Loading…
Reference in a new issue