rustpkg: Implement clean; replace boolean result flags with fail!()

1. Implemented the `clean` command

2. The methods implementing rustpkg commands all returned `bool`.
Since most of not all of the error situations seem unrecoverable,
I changed the methods to return unit (and also stubbed out several
more methods that were assuming a package script existed, to be
re-implemented in the future)
This commit is contained in:
Tim Chevalier 2013-04-17 15:47:24 -07:00
parent e6c3c371a5
commit 82765a0b48
2 changed files with 67 additions and 159 deletions

View file

@ -33,7 +33,6 @@ use core::hashmap::HashMap;
use core::io::WriterUtil;
use rustc::driver::{driver, session};
use rustc::metadata::filesearch;
use std::net::url;
use std::{getopts};
use syntax::{ast, diagnostic};
use util::*;
@ -244,16 +243,21 @@ impl Ctx {
src.build(&dst_dir, cfgs);
}
~"clean" => {
self.clean();
if args.len() < 1 {
return usage::build();
}
// The package id is presumed to be the first command-line
// argument
let pkgid = PkgId::new(args[0]);
self.clean(pkgid);
}
~"do" => {
if args.len() < 2 {
return usage::do_cmd();
}
if !self.do_cmd(args[0], args[1]) {
fail!(~"a command failed!");
}
self.do_cmd(args[0], args[1]);
}
~"info" => {
self.info();
@ -298,12 +302,11 @@ impl Ctx {
}
}
fn do_cmd(&self, cmd: ~str, pkgname: ~str) -> bool {
fn do_cmd(&self, cmd: ~str, pkgname: ~str) {
match cmd {
~"build" | ~"test" => {
util::error(~"that command cannot be manually called");
return false;
fail!(~"do_cmd");
}
_ => {}
}
@ -319,16 +322,15 @@ impl Ctx {
Some(script_path) => {
let script = PkgScript::parse(script_path, pkgid);
let (_, status) = script.run_custom(cmd); // Ignore cfgs?
if status == 42 { // ???
if status == 42 {
util::error(~"no fns are listening for that cmd");
return false;
fail!(~"do_cmd");
}
status == 0
}
None => {
util::error(fmt!("invoked `do`, but there is no package script in %s",
cwd.to_str()));
false
fail!(~"do_cmd");
}
}
}
@ -341,128 +343,44 @@ impl Ctx {
}
fn compile(&self, _crate: &Path, _dir: &Path, _flags: ~[~str],
_cfgs: ~[~str], _opt: bool, _test: bool) -> bool {
_cfgs: ~[~str], _opt: bool, _test: bool) {
// What's the difference between build and compile?
fail!(~"compile not yet implemented");
}
fn clean(&self) -> bool {
// stub
fail!();
fn clean(&self, id: PkgId) {
// Could also support a custom build hook in the pkg
// script for cleaning files rustpkg doesn't know about.
// Do something reasonable for now
let dir = dest_dir(id);
util::note(fmt!("Cleaning package %s (removing directory %s)",
id.to_str(), dir.to_str()));
if os::path_exists(&dir) {
util::remove_dir_r(&dir);
util::note(fmt!("Removed directory %s", dir.to_str()));
}
util::note(fmt!("Cleaned package %s", id.to_str()));
}
fn info(&self) {
// stub
fail!();
fail!(~"info not yet implemented");
}
fn install(&self, url: Option<~str>,
target: Option<~str>, cache: bool) -> bool {
let dir = match url {
None => {
util::note(~"installing from the cwd");
os::getcwd()
}
Some(url) => {
let hash = util::hash(if !target.is_none() {
url + target.get()
}
else { url });
if self.dep_cache.contains_key(&hash) {
util::warn(~"already installed dep this run");
return true;
}
self.dep_cache.insert(hash, true);
let dir = util::root().push(~"tmp").push(hash);
if cache && os::path_exists(&dir) {
return true;
}
if !self.fetch(&dir, url, target) {
return false;
}
dir
}
};
let script = match self.build(&dir, false, true, false) {
Some(script) => script,
None => {
return false;
}
};
let work_dir = script.build_dir;
let from_bin_dir = work_dir.push(~"bin");
let from_lib_dir = work_dir.push(~"lib");
let to_bin_dir = util::root().push(~"bin");
let to_lib_dir = util::root().push(~"lib");
let mut bins = ~[];
let mut libs = ~[];
for os::walk_dir(&from_bin_dir) |bin| {
let to = to_bin_dir.push_rel(&bin.file_path());
os::copy_file(bin, &to);
bins.push(to.to_str());
}
for os::walk_dir(&from_lib_dir) |lib| {
let to = to_lib_dir.push_rel(&lib.file_path());
os::copy_file(lib, &to);
libs.push(to.to_str());
}
let package = Pkg {
id: script.id,
bins: bins,
libs: libs
};
util::note(fmt!("installed %s", script.id.to_str()));
util::add_pkg(&package);
true
fn install(&self, _url: Option<~str>,
_target: Option<~str>, _cache: bool) {
// stub
fail!(~"install not yet implemented");
}
fn fetch(&self, dir: &Path, url: ~str, target: Option<~str>) -> bool {
let url = if str::find_str(url, "://").is_none() {
~"http://" + url }
else { url };
let url = match url::from_str(url) {
result::Ok(url) => url,
result::Err(err) => {
util::error(fmt!("failed parsing %s", err.to_lower()));
return false;
}
};
let str = url.to_str();
match Path(url.path).filetype() {
Some(ext) => {
if ext == ~".git" {
return self.fetch_git(dir, str, target);
}
}
None => {}
}
match url.scheme {
~"git" => self.fetch_git(dir, str, target),
~"http" | ~"ftp" | ~"file" => self.fetch_curl(dir, str),
_ => {
util::warn(~"unknown url scheme to fetch, using curl");
self.fetch_curl(dir, str)
}
}
fn fetch(&self, _dir: &Path, _url: ~str, _target: Option<~str>) {
// stub
fail!(~"fetch not yet implemented");
}
fn fetch_curl(&self, dir: &Path, url: ~str) -> bool {
fn fetch_curl(&self, dir: &Path, url: ~str) {
util::note(fmt!("fetching from %s using curl", url));
let tar = dir.dir_path().push(&dir.file_path().to_str() + ~".tar");
@ -472,7 +390,7 @@ impl Ctx {
url]).status != 0 {
util::error(~"fetching failed: downloading using curl failed");
return false;
fail!();
}
if run::program_output(~"tar", ~[~"-x", ~"--strip-components=1",
@ -481,13 +399,11 @@ impl Ctx {
util::error(~"fetching failed: extracting using tar failed" +
~"(is it a valid tar archive?)");
return false;
fail!();
}
true
}
fn fetch_git(&self, dir: &Path, url: ~str, target: Option<~str>) -> bool {
fn fetch_git(&self, dir: &Path, url: ~str, target: Option<~str>) {
util::note(fmt!("fetching from %s using git", url));
// Git can't clone into a non-empty directory
@ -496,8 +412,7 @@ impl Ctx {
if run::program_output(~"git", ~[~"clone", url,
dir.to_str()]).status != 0 {
util::error(~"fetching failed: can't clone repository");
return false;
fail!();
}
if !target.is_none() {
@ -511,21 +426,17 @@ impl Ctx {
if !success {
util::error(~"fetching failed: can't checkout target");
return false;
fail!();
}
}
true
}
fn prefer(&self, id: ~str, vers: Option<~str>) -> bool {
fn prefer(&self, id: ~str, vers: Option<~str>) {
let package = match util::get_pkg(id, vers) {
result::Ok(package) => package,
result::Err(err) => {
util::error(err);
return false;
fail!(); // Condition?
}
};
let name = package.id.path.to_str(); // ???
@ -548,29 +459,18 @@ impl Ctx {
}
util::note(fmt!("preferred %s v%s", name, package.id.version.to_str()));
true
}
fn test(&self) -> bool {
let script = match self.build(&os::getcwd(), false, false, true) {
Some(script) => script,
None => {
return false;
}
};
// To do
util::note(fmt!("Would test %s, but this is a dry run",
script.id.to_str()));
false
fn test(&self) {
// stub
fail!(~"test not yet implemented");
}
fn uninstall(&self, _id: ~str, _vers: Option<~str>) -> bool {
fn uninstall(&self, _id: ~str, _vers: Option<~str>) {
fail!(~"uninstall not yet implemented");
}
fn unprefer(&self, _id: ~str, _vers: Option<~str>) -> bool {
fn unprefer(&self, _id: ~str, _vers: Option<~str>) {
fail!(~"unprefer not yet implemented");
}
}
@ -839,14 +739,19 @@ impl PkgSrc {
prefix, pth),
Some(~"bench.rs") => push_crate(&mut self.benchs,
prefix, pth),
_ => {
util::note(~"Couldn't infer any crates to build.\n\
Try naming a crate `main.rs`, `lib.rs`, \
`test.rs`, or `bench.rs`.");
fail!(~"Failed to infer crates to build");
}
_ => ()
}
}
if self.libs.is_empty() && self.mains.is_empty()
&& self.tests.is_empty() && self.benchs.is_empty() {
util::note(~"Couldn't infer any crates to build.\n\
Try naming a crate `main.rs`, `lib.rs`, \
`test.rs`, or `bench.rs`.");
fail!(~"Failed to infer crates to build");
}
debug!("found %u libs, %u mains, %u tests, %u benchs",
self.libs.len(),
self.mains.len(),

View file

@ -10,9 +10,12 @@
/*
The test runner should check that, after `rustpkg build hello-world`:
* testsuite/hello-world/build/ exists
* testsuite/hello-world/build/ contains an executable named hello-world
* testsuite/hello-world/build/ does not contain a library
* testsuite/pass/hello-world/build/ exists
* testsuite/pass/hello-world/build/ contains an executable named hello-world
* testsuite/pass/hello-world/build/ does not contain a library
It should also check that after `rustpkg clean hello-world`:
* testsuite/pass/hello-world/build is empty
*/
use core::io;