klutzy a6a31ecb04 rustpkg::crate_id: Remove CrateId
There is no significant difference between `rustpkg::crate_id::CrateId`
and `syntax::crateid::CrateId`. rustpkg's one is replaced by syntax's
one.
2014-01-23 03:03:55 +09:00

817 lines
35 KiB
Rust

// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustpkg - a package manager and build system for Rust
#[crate_id = "rustpkg#0.10-pre"];
#[license = "MIT/ASL2"];
#[crate_type = "dylib"];
#[feature(globs, managed_boxes)];
extern mod extra;
extern mod rustc;
extern mod syntax;
use std::{os, run, str, task};
use std::io::process;
use std::io;
use std::io::fs;
pub use std::path::Path;
use extra::workcache;
use rustc::driver::{driver, session};
use rustc::metadata::creader::Loader;
use rustc::metadata::filesearch;
use rustc::metadata::filesearch::rust_path;
use rustc::util::sha2;
use syntax::{ast, diagnostic};
use syntax::crateid::CrateId;
use messages::{error, warn, note};
use parse_args::{ParseResult, parse_args};
use path_util::{build_pkg_id_in_workspace, built_test_in_workspace};
use path_util::in_rust_path;
use path_util::{built_executable_in_workspace, built_library_in_workspace, default_workspace};
use path_util::{target_executable_in_workspace, target_library_in_workspace, dir_has_crate_file};
use source_control::{CheckedOutSources, is_git_dir, make_read_only};
use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces, cwd_to_workspace};
use workspace::determine_destination;
use context::{BuildContext, Trans, Nothing, Pretty, Analysis,
LLVMAssemble, LLVMCompileBitcode};
use context::{Command, BuildCmd, CleanCmd, DoCmd, HelpCmd, InfoCmd, InstallCmd, ListCmd,
PreferCmd, TestCmd, InitCmd, UninstallCmd, UnpreferCmd};
use package_source::PkgSrc;
use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench};
use target::{Main, Tests, MaybeCustom, Inferred, JustOne};
use workcache_support::digest_only_date;
use exit_codes::{COPY_FAILED_CODE};
pub mod api;
mod conditions;
pub mod context;
mod crate;
pub mod exit_codes;
mod installed_packages;
mod messages;
pub mod package_source;
mod parse_args;
mod path_util;
mod source_control;
mod target;
#[cfg(not(windows), test)] // FIXME test failure on windows: #10471
mod tests;
mod util;
pub mod version;
pub mod workcache_support;
mod workspace;
pub mod usage;
/// A PkgScript represents user-supplied custom logic for
/// special build hooks. This only exists for packages with
/// an explicit package script.
struct PkgScript<'a> {
/// Uniquely identifies this package
id: &'a CrateId,
/// File path for the package script
input: Path,
/// The session to use *only* for compiling the custom
/// build script
sess: session::Session,
/// The config for compiling the custom build script
cfg: ast::CrateConfig,
/// The crate and ast_map for the custom build script
crate_and_map: Option<(ast::Crate, syntax::ast_map::Map)>,
/// Directory in which to store build output
build_dir: Path
}
impl<'a> PkgScript<'a> {
/// Given the path name for a package script
/// and a package ID, parse the package script into
/// a PkgScript that we can then execute
fn parse<'a>(sysroot: Path,
script: Path,
workspace: &Path,
id: &'a CrateId) -> PkgScript<'a> {
// Get the executable name that was invoked
let binary = os::args()[0];
// Build the rustc session data structures to pass
// to the compiler
debug!("pkgscript parse: {}", sysroot.display());
let options = @session::Options {
binary: binary,
maybe_sysroot: Some(@sysroot),
outputs: ~[session::OutputExecutable],
.. (*session::basic_options()).clone()
};
let input = driver::FileInput(script.clone());
let sess = driver::build_session(options,
@diagnostic::DefaultEmitter as
@diagnostic::Emitter);
let cfg = driver::build_configuration(sess);
let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
let loader = &mut Loader::new(sess);
let crate_and_map = driver::phase_2_configure_and_expand(sess,
cfg.clone(),
loader,
crate);
let work_dir = build_pkg_id_in_workspace(id, workspace);
debug!("Returning package script with id {}", id.to_str());
PkgScript {
id: id,
input: script,
sess: sess,
cfg: cfg,
crate_and_map: Some(crate_and_map),
build_dir: work_dir
}
}
fn build_custom(&mut self, exec: &mut workcache::Exec) -> ~str {
let sess = self.sess;
debug!("Working directory = {}", self.build_dir.display());
// Collect together any user-defined commands in the package script
let (crate, ast_map) = self.crate_and_map.take_unwrap();
let crate = util::ready_crate(sess, crate);
debug!("Building output filenames with script name {}",
driver::source_name(&driver::FileInput(self.input.clone())));
let exe = self.build_dir.join("pkg" + util::exe_suffix());
util::compile_crate_from_input(&self.input,
exec,
Nothing,
&self.build_dir,
sess,
crate,
ast_map,
Main);
// Discover the output
// FIXME (#9639): This needs to handle non-utf8 paths
// Discover the output
exec.discover_output("binary", exe.as_str().unwrap().to_owned(), digest_only_date(&exe));
exe.as_str().unwrap().to_owned()
}
/// Run the contents of this package script, where <what>
/// is the command to pass to it (e.g., "build", "clean", "install")
/// Returns a pair of an exit code and list of configs (obtained by
/// calling the package script's configs() function if it exists, or
/// None if `exe` could not be started.
fn run_custom(exe: &Path, sysroot: &Path) -> Option<(~[~str], process::ProcessExit)> {
debug!("Running program: {} {} {}", exe.as_str().unwrap().to_owned(),
sysroot.display(), "install");
// FIXME #7401 should support commands besides `install`
// FIXME (#9639): This needs to handle non-utf8 paths
let opt_status = run::process_status(exe.as_str().unwrap(),
[sysroot.as_str().unwrap().to_owned(), ~"install"]);
match opt_status {
Some(status) => {
if !status.success() {
debug!("run_custom: first pkg command failed with {:?}", status);
Some((~[], status))
}
else {
debug!("Running program (configs): {} {} {}",
exe.display(), sysroot.display(), "configs");
// FIXME (#9639): This needs to handle non-utf8 paths
let opt_output = run::process_output(exe.as_str().unwrap(),
[sysroot.as_str().unwrap().to_owned(),
~"configs"]);
match opt_output {
Some(output) => {
debug!("run_custom: second pkg command did {:?}", output.status);
// Run the configs() function to get the configs
let cfgs = str::from_utf8(output.output).unwrap().words()
.map(|w| w.to_owned()).collect();
Some((cfgs, output.status))
},
None => {
debug!("run_custom: second pkg command failed to start");
Some((~[], status))
}
}
}
},
None => {
debug!("run_custom: first pkg command failed to start");
None
}
}
}
}
pub trait CtxMethods {
fn run(&self, cmd: Command, args: ~[~str]);
fn do_cmd(&self, _cmd: &str, _pkgname: &str);
/// Returns a pair of the selected package ID, and the destination workspace
fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(CrateId, Path)>;
/// Returns the destination workspace
fn build(&self, pkg_src: &mut PkgSrc, what: &WhatToBuild);
fn clean(&self, workspace: &Path, id: &CrateId);
fn info(&self);
/// Returns a pair. First component is a list of installed paths,
/// second is a list of declared and discovered inputs
fn install(&self, src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]);
/// Returns a list of installed files
fn install_no_build(&self,
build_workspace: &Path,
build_inputs: &[Path],
target_workspace: &Path,
id: &CrateId) -> ~[~str];
fn prefer(&self, _id: &str, _vers: Option<~str>);
fn test(&self, id: &CrateId, workspace: &Path);
fn uninstall(&self, _id: &str, _vers: Option<~str>);
fn unprefer(&self, _id: &str, _vers: Option<~str>);
fn init(&self);
}
impl CtxMethods for BuildContext {
fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(CrateId, Path)> {
let cwd = os::getcwd();
if args.len() < 1 {
match cwd_to_workspace() {
None if dir_has_crate_file(&cwd) => {
// FIXME (#9639): This needs to handle non-utf8 paths
let crateid = from_str(cwd.filename_str().unwrap()).expect("valid crate id");
let mut pkg_src = PkgSrc::new(cwd, default_workspace(), true, crateid);
self.build(&mut pkg_src, what);
match pkg_src {
PkgSrc { destination_workspace: ws,
id: id, .. } => {
Some((id, ws))
}
}
}
None => { usage::build(); None }
Some((ws, crateid)) => {
let mut pkg_src = PkgSrc::new(ws.clone(), ws, false, crateid);
self.build(&mut pkg_src, what);
match pkg_src {
PkgSrc { destination_workspace: ws,
id: id, .. } => {
Some((id, ws))
}
}
}
}
} else {
// The package id is presumed to be the first command-line
// argument
let crateid = from_str(args[0]).expect("valid crate id");
let mut dest_ws = default_workspace();
each_pkg_parent_workspace(&self.context, &crateid, |workspace| {
debug!("found pkg {} in workspace {}, trying to build",
crateid.to_str(), workspace.display());
dest_ws = determine_destination(os::getcwd(),
self.context.use_rust_path_hack,
workspace);
let mut pkg_src = PkgSrc::new(workspace.clone(), dest_ws.clone(),
false, crateid.clone());
self.build(&mut pkg_src, what);
true
});
// n.b. If this builds multiple packages, it only returns the workspace for
// the last one. The whole building-multiple-packages-with-the-same-ID is weird
// anyway and there are no tests for it, so maybe take it out
Some((crateid, dest_ws))
}
}
fn run(&self, cmd: Command, args: ~[~str]) {
let cwd = os::getcwd();
match cmd {
BuildCmd => {
self.build_args(args, &WhatToBuild::new(MaybeCustom, Everything));
}
CleanCmd => {
if args.len() < 1 {
match cwd_to_workspace() {
None => { usage::clean(); return }
// tjc: Maybe clean should clean all the packages in the
// current workspace, though?
Some((ws, crateid)) => self.clean(&ws, &crateid)
}
}
else {
// The package id is presumed to be the first command-line
// argument
let crateid = from_str(args[0]).expect("valid crate id");
self.clean(&cwd, &crateid); // tjc: should use workspace, not cwd
}
}
DoCmd => {
if args.len() < 2 {
return usage::do_cmd();
}
self.do_cmd(args[0].clone(), args[1].clone());
}
HelpCmd => {
if args.len() != 1 {
return usage::general();
}
match FromStr::from_str(args[0]) {
Some(help_cmd) => usage::usage_for_command(help_cmd),
None => {
usage::general();
error(format!("{} is not a recognized command", args[0]))
}
}
}
InfoCmd => {
self.info();
}
InstallCmd => {
if args.len() < 1 {
match cwd_to_workspace() {
None if dir_has_crate_file(&cwd) => {
// FIXME (#9639): This needs to handle non-utf8 paths
let inferred_crateid =
from_str(cwd.filename_str().unwrap()).expect("valid crate id");
self.install(PkgSrc::new(cwd, default_workspace(),
true, inferred_crateid),
&WhatToBuild::new(MaybeCustom, Everything));
}
None => { usage::install(); return; }
Some((ws, crateid)) => {
let pkg_src = PkgSrc::new(ws.clone(), ws.clone(), false, crateid);
self.install(pkg_src, &WhatToBuild::new(MaybeCustom,
Everything));
}
}
}
else {
// The package id is presumed to be the first command-line
// argument
let crateid = from_str(args[0]).expect("valid crate id");
let workspaces = pkg_parent_workspaces(&self.context, &crateid);
debug!("package ID = {}, found it in {:?} workspaces",
crateid.to_str(), workspaces.len());
if workspaces.is_empty() {
let d = default_workspace();
let src = PkgSrc::new(d.clone(), d, false, crateid.clone());
self.install(src, &WhatToBuild::new(MaybeCustom, Everything));
}
else {
for workspace in workspaces.iter() {
let dest = determine_destination(os::getcwd(),
self.context.use_rust_path_hack,
workspace);
let src = PkgSrc::new(workspace.clone(),
dest,
self.context.use_rust_path_hack,
crateid.clone());
self.install(src, &WhatToBuild::new(MaybeCustom, Everything));
};
}
}
}
ListCmd => {
println!("Installed packages:");
installed_packages::list_installed_packages(|pkg_id| {
println!("{}", pkg_id.path);
true
});
}
PreferCmd => {
if args.len() < 1 {
return usage::prefer();
}
self.prefer(args[0], None);
}
TestCmd => {
// Build the test executable
let maybe_id_and_workspace = self.build_args(args,
&WhatToBuild::new(MaybeCustom, Tests));
match maybe_id_and_workspace {
Some((pkg_id, workspace)) => {
// Assuming it's built, run the tests
self.test(&pkg_id, &workspace);
}
None => {
error("Testing failed because building the specified package failed.");
}
}
}
InitCmd => {
if args.len() != 0 {
return usage::init();
} else {
self.init();
}
}
UninstallCmd => {
if args.len() < 1 {
return usage::uninstall();
}
let crateid = from_str(args[0]).expect("valid crate id");
if !installed_packages::package_is_installed(&crateid) {
warn(format!("Package {} doesn't seem to be installed! \
Doing nothing.", args[0]));
return;
}
else {
let rp = rust_path();
assert!(!rp.is_empty());
each_pkg_parent_workspace(&self.context, &crateid, |workspace| {
path_util::uninstall_package_from(workspace, &crateid);
note(format!("Uninstalled package {} (was installed in {})",
crateid.to_str(), workspace.display()));
true
});
}
}
UnpreferCmd => {
if args.len() < 1 {
return usage::unprefer();
}
self.unprefer(args[0], None);
}
}
}
fn do_cmd(&self, _cmd: &str, _pkgname: &str) {
// stub
fail!("`do` not yet implemented");
}
fn build(&self, pkg_src: &mut PkgSrc, what_to_build: &WhatToBuild) {
use conditions::git_checkout_failed::cond;
let workspace = pkg_src.source_workspace.clone();
let crateid = pkg_src.id.clone();
let path = crateid.path.as_slice();
debug!("build: workspace = {} (in Rust path? {:?} is git dir? {:?} \
crateid = {} pkgsrc start_dir = {}", workspace.display(),
in_rust_path(&workspace), is_git_dir(&workspace.join(path)),
crateid.to_str(), pkg_src.start_dir.display());
debug!("build: what to build = {:?}", what_to_build);
// If workspace isn't in the RUST_PATH, and it's a git repo,
// then clone it into the first entry in RUST_PATH, and repeat
if !in_rust_path(&workspace) && is_git_dir(&workspace.join(path)) {
let mut out_dir = default_workspace().join("src");
out_dir.push(path);
let git_result = source_control::safe_git_clone(&workspace.join(path),
&crateid.version,
&out_dir);
match git_result {
CheckedOutSources => make_read_only(&out_dir),
_ => cond.raise((path.to_owned(), out_dir.clone()))
};
let default_ws = default_workspace();
debug!("Calling build recursively with {:?} and {:?}", default_ws.display(),
crateid.to_str());
return self.build(&mut PkgSrc::new(default_ws.clone(),
default_ws,
false,
crateid.clone()), what_to_build);
}
// Is there custom build logic? If so, use it
let mut custom = false;
debug!("Package source directory = {}", pkg_src.to_str());
let opt = pkg_src.package_script_option();
debug!("Calling pkg_script_option on {:?}", opt);
let cfgs = match (pkg_src.package_script_option(), what_to_build.build_type) {
(Some(package_script_path), MaybeCustom) => {
let sysroot = self.sysroot_to_use();
// Build the package script if needed
let script_build = format!("build_package_script({})",
package_script_path.display());
let pkg_exe = self.workcache_context.with_prep(script_build, |prep| {
let subsysroot = sysroot.clone();
let psp = package_script_path.clone();
let ws = workspace.clone();
let pid = crateid.clone();
prep.exec(proc(exec) {
let mut pscript = PkgScript::parse(subsysroot.clone(),
psp.clone(),
&ws,
&pid);
pscript.build_custom(exec)
})
});
// We always *run* the package script
match PkgScript::run_custom(&Path::new(pkg_exe), &sysroot) {
Some((cfgs, hook_result)) => {
debug!("Command return code = {:?}", hook_result);
if !hook_result.success() {
fail!("Error running custom build command")
}
custom = true;
// otherwise, the package script succeeded
cfgs
},
None => {
fail!("Error starting custom build command")
}
}
}
(Some(_), Inferred) => {
debug!("There is a package script, but we're ignoring it");
~[]
}
(None, _) => {
debug!("No package script, continuing");
~[]
}
} + self.context.cfgs;
// If there was a package script, it should have finished
// the build already. Otherwise...
if !custom {
match what_to_build.sources {
// Find crates inside the workspace
Everything => pkg_src.find_crates(),
// Find only tests
Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path::new(s)) }),
// Don't infer any crates -- just build the one that was requested
JustOne(ref p) => {
// We expect that p is relative to the package source's start directory,
// so check that assumption
debug!("JustOne: p = {}", p.display());
assert!(pkg_src.start_dir.join(p).exists());
if is_lib(p) {
PkgSrc::push_crate(&mut pkg_src.libs, 0, p);
} else if is_main(p) {
PkgSrc::push_crate(&mut pkg_src.mains, 0, p);
} else if is_test(p) {
PkgSrc::push_crate(&mut pkg_src.tests, 0, p);
} else if is_bench(p) {
PkgSrc::push_crate(&mut pkg_src.benchs, 0, p);
} else {
warn(format!("Not building any crates for dependency {}", p.display()));
return;
}
}
}
// Build it!
pkg_src.build(self, cfgs, []);
}
}
fn clean(&self, workspace: &Path, id: &CrateId) {
// 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 = build_pkg_id_in_workspace(id, workspace);
note(format!("Cleaning package {} (removing directory {})",
id.to_str(), dir.display()));
if dir.exists() {
fs::rmdir_recursive(&dir);
note(format!("Removed directory {}", dir.display()));
}
note(format!("Cleaned package {}", id.to_str()));
}
fn info(&self) {
// stub
fail!("info not yet implemented");
}
fn install(&self, mut pkg_src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]) {
let id = pkg_src.id.clone();
let mut installed_files = ~[];
let mut inputs = ~[];
let mut build_inputs = ~[];
debug!("Installing package source: {}", pkg_src.to_str());
// workcache only knows about *crates*. Building a package
// just means inferring all the crates in it, then building each one.
self.build(&mut pkg_src, what);
debug!("Done building package source {}", pkg_src.to_str());
let to_do = ~[pkg_src.libs.clone(), pkg_src.mains.clone(),
pkg_src.tests.clone(), pkg_src.benchs.clone()];
debug!("In declare inputs for {}", id.to_str());
for cs in to_do.iter() {
for c in cs.iter() {
let path = pkg_src.start_dir.join(&c.file);
debug!("Recording input: {}", path.display());
// FIXME (#9639): This needs to handle non-utf8 paths
inputs.push((~"file", path.as_str().unwrap().to_owned()));
build_inputs.push(path);
}
}
let result = self.install_no_build(pkg_src.build_workspace(),
build_inputs,
&pkg_src.destination_workspace,
&id).map(|s| Path::new(s.as_slice()));
installed_files = installed_files + result;
note(format!("Installed package {} to {}",
id.to_str(),
pkg_src.destination_workspace.display()));
(installed_files, inputs)
}
// again, working around lack of Encodable for Path
fn install_no_build(&self,
build_workspace: &Path,
build_inputs: &[Path],
target_workspace: &Path,
id: &CrateId) -> ~[~str] {
debug!("install_no_build: assuming {} comes from {} with target {}",
id.to_str(), build_workspace.display(), target_workspace.display());
// Now copy stuff into the install dirs
let maybe_executable = built_executable_in_workspace(id, build_workspace);
let maybe_library = built_library_in_workspace(id, build_workspace);
let target_exec = target_executable_in_workspace(id, target_workspace);
let target_lib = maybe_library.as_ref()
.map(|_| target_library_in_workspace(id, target_workspace));
debug!("target_exec = {} target_lib = {:?} \
maybe_executable = {:?} maybe_library = {:?}",
target_exec.display(), target_lib,
maybe_executable, maybe_library);
let install_tag = format!("install({}-{})", id.path, id.version_or_default());
self.workcache_context.with_prep(install_tag, |prep| {
for ee in maybe_executable.iter() {
// FIXME (#9639): This needs to handle non-utf8 paths
prep.declare_input("binary",
ee.as_str().unwrap(),
workcache_support::digest_only_date(ee));
}
for ll in maybe_library.iter() {
// FIXME (#9639): This needs to handle non-utf8 paths
prep.declare_input("binary",
ll.as_str().unwrap(),
workcache_support::digest_only_date(ll));
}
let subex = maybe_executable.clone();
let sublib = maybe_library.clone();
let sub_target_ex = target_exec.clone();
let sub_target_lib = target_lib.clone();
let sub_build_inputs = build_inputs.to_owned();
prep.exec(proc(exe_thing) {
let mut outputs = ~[];
// Declare all the *inputs* to the declared input too, as inputs
for executable in subex.iter() {
exe_thing.discover_input("binary",
executable.as_str().unwrap().to_owned(),
workcache_support::digest_only_date(executable));
}
for library in sublib.iter() {
exe_thing.discover_input("binary",
library.as_str().unwrap().to_owned(),
workcache_support::digest_only_date(library));
}
for transitive_dependency in sub_build_inputs.iter() {
exe_thing.discover_input(
"file",
transitive_dependency.as_str().unwrap().to_owned(),
workcache_support::digest_file_with_date(transitive_dependency));
}
for exec in subex.iter() {
debug!("Copying: {} -> {}", exec.display(), sub_target_ex.display());
fs::mkdir_recursive(&sub_target_ex.dir_path(), io::UserRWX);
fs::copy(exec, &sub_target_ex);
// FIXME (#9639): This needs to handle non-utf8 paths
exe_thing.discover_output("binary",
sub_target_ex.as_str().unwrap(),
workcache_support::digest_only_date(&sub_target_ex));
outputs.push(sub_target_ex.as_str().unwrap().to_owned());
}
for lib in sublib.iter() {
let mut target_lib = sub_target_lib
.clone().expect(format!("I built {} but apparently \
didn't install it!", lib.display()));
target_lib.set_filename(lib.filename().expect("weird target lib"));
fs::mkdir_recursive(&target_lib.dir_path(), io::UserRWX);
fs::copy(lib, &target_lib);
debug!("3. discovering output {}", target_lib.display());
exe_thing.discover_output("binary",
target_lib.as_str().unwrap(),
workcache_support::digest_only_date(&target_lib));
outputs.push(target_lib.as_str().unwrap().to_owned());
}
outputs
})
})
}
fn prefer(&self, _id: &str, _vers: Option<~str>) {
fail!("prefer not yet implemented");
}
fn test(&self, crateid: &CrateId, workspace: &Path) {
match built_test_in_workspace(crateid, workspace) {
Some(test_exec) => {
debug!("test: test_exec = {}", test_exec.display());
// FIXME (#9639): This needs to handle non-utf8 paths
let opt_status = run::process_status(test_exec.as_str().unwrap(), [~"--test"]);
match opt_status {
Some(status) => {
if !status.success() {
fail!("Some tests failed");
}
},
None => fail!("Could not exec `{}`", test_exec.display())
}
}
None => {
error(format!("Internal error: test executable for package ID {} in workspace {} \
wasn't built! Please report this as a bug.",
crateid.to_str(), workspace.display()));
}
}
}
fn init(&self) {
fs::mkdir_recursive(&Path::new("src"), io::UserRWX);
fs::mkdir_recursive(&Path::new("bin"), io::UserRWX);
fs::mkdir_recursive(&Path::new("lib"), io::UserRWX);
fs::mkdir_recursive(&Path::new("build"), io::UserRWX);
}
fn uninstall(&self, _id: &str, _vers: Option<~str>) {
fail!("uninstall not yet implemented");
}
fn unprefer(&self, _id: &str, _vers: Option<~str>) {
fail!("unprefer not yet implemented");
}
}
pub fn main() {
println!("WARNING: The Rust package manager is experimental and may be unstable");
os::set_exit_status(main_args(os::args()));
}
pub fn main_args(args: &[~str]) -> int {
let (command, args, context, supplied_sysroot) = match parse_args(args) {
Ok(ParseResult {
command: cmd,
args: args,
context: ctx,
sysroot: sroot}) => (cmd, args, ctx, sroot),
Err(error_code) => {
debug!("Parsing failed. Returning error code {}", error_code);
return error_code
}
};
debug!("Finished parsing commandline args {:?}", args);
debug!(" Using command: {:?}", command);
debug!(" Using args {:?}", args);
debug!(" Using cflags: {:?}", context.rustc_flags);
debug!(" Using rust_path_hack {:b}", context.use_rust_path_hack);
debug!(" Using cfgs: {:?}", context.cfgs);
debug!(" Using supplied_sysroot: {:?}", supplied_sysroot);
let sysroot = match supplied_sysroot {
Some(s) => Path::new(s),
_ => filesearch::get_or_default_sysroot()
};
debug!("Using sysroot: {}", sysroot.display());
let ws = default_workspace();
debug!("Will store workcache in {}", ws.display());
// Wrap the rest in task::try in case of a condition failure in a task
let result = do task::try {
BuildContext {
context: context,
sysroot: sysroot.clone(), // Currently, only tests override this
workcache_context: api::default_context(sysroot.clone(),
default_workspace()).workcache_context
}.run(command, args.clone())
};
// FIXME #9262: This is using the same error code for all errors,
// and at least one test case succeeds if rustpkg returns COPY_FAILED_CODE,
// when actually, it might set the exit code for that even if a different
// unhandled condition got raised.
if result.is_err() { return COPY_FAILED_CODE; }
return 0;
}