From 08109aa0ad3d53ff11202d2846652785ddefb02a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 17:47:55 -0700 Subject: [PATCH 1/5] core: Comments only -- move FIXME to correct location --- src/libcore/os.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 1000fd88b52..62633837207 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -43,8 +43,6 @@ use vec; pub use libc::fclose; pub use os::consts::*; -// FIXME: move these to str perhaps? #2620 - pub fn close(fd: c_int) -> c_int { unsafe { libc::close(fd) @@ -79,6 +77,8 @@ pub fn getcwd() -> Path { } } +// FIXME: move these to str perhaps? #2620 + pub fn as_c_charp(s: &str, f: &fn(*c_char) -> T) -> T { str::as_c_str(s, |b| f(b as *c_char)) } From c2af1de95b65a0cc2225565f47aa9c08fd072371 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 17:48:21 -0700 Subject: [PATCH 2/5] rustpkg: update README saying which tests pass --- src/librustpkg/README.txt | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/librustpkg/README.txt b/src/librustpkg/README.txt index eacf07e01ea..acfbf395e4b 100644 --- a/src/librustpkg/README.txt +++ b/src/librustpkg/README.txt @@ -1,4 +1,24 @@ -Right now (2013-04-11), only one package works, the branch of rust-sdl at: -https://github.com/catamorphism/rust-sdl/tree/new-rustpkg +Right now, commands that work are "build" and "clean". -and only one command works, "build". +`rustpkg build` and `rustpkg clean` should work + +for example: +$ cd ~/rust/src/librustpkg/testsuite/pass +$ rustpkg build hello-world +... some output ... +$ rustpkg clean hello-world + +------------- +the following test packages in librustpkg/testsuite/pass: + * hello-world + * install-paths + * simple-lib + * deeply/nested/path + * fancy-lib + + It fails on the following test packages: + * external-crate (no support for `extern mod` inference yet) + +and should fail with proper error messages +on all of the test packages in librustpkg/testsuite/fail + * no-inferred-crates From 6a3e26aa4062019629e144196a7852ef039f8b0a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 17:54:54 -0700 Subject: [PATCH 3/5] rustpkg: Make path searching work as described in the rustpkg doc rustpkg now searches for package directories in ./src rather than in . . I also added a rudimentary RUST_PATH that's currently hard-wired to the current directory. rustpkg now uses src/, lib/, and build/ directories as described in the manual. Most of the existing test scenarios build now; the README file (in a separate commit) explains which ones. --- src/librustpkg/path_util.rs | 172 +++++++++++++++++++++++++----------- src/librustpkg/rustpkg.rc | 154 +++++++++++++------------------- src/librustpkg/util.rs | 15 +++- 3 files changed, 190 insertions(+), 151 deletions(-) diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index cd9b44c278e..a8931e52747 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -15,39 +15,43 @@ use core::{os, str}; use core::option::*; use util::PkgId; -/// Returns the output directory to use. -/// Right now is always the default, should -/// support changing it. -pub fn dest_dir(pkgid: PkgId) -> Path { - default_dest_dir(&pkgid.path) +#[deriving(Eq)] +pub enum OutputType { Main, Lib, Bench, Test } + +/// Returns the value of RUST_PATH, as a list +/// of Paths. In general this should be read from the +/// environment; for now, it's hard-wired to just be "." +pub fn rust_path() -> ~[Path] { + ~[Path(".")] } -/// Returns the default output directory for compilation. -/// Creates that directory if it doesn't exist. -pub fn default_dest_dir(pkg_dir: &Path) -> Path { +/// Creates a directory that is readable, writeable, +/// and executable by the user. Returns true iff creation +/// succeeded. +pub fn make_dir_rwx(p: &Path) -> bool { use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; - use conditions::bad_path::cond; - // For now: assumes that pkg_dir exists and is relative - // to the CWD. Change this later when we do path searching. - let rslt = pkg_dir.push("build"); - let is_dir = os::path_is_dir(&rslt); - if os::path_exists(&rslt) { - if is_dir { - rslt - } - else { - cond.raise((rslt, ~"Path names a file that isn't a directory")) - } + os::make_dir(p, (S_IRUSR | S_IWUSR | S_IXUSR) as i32) +} + +/// Creates a directory that is readable, writeable, +/// and executable by the user. Returns true iff creation +/// succeeded. Also creates all intermediate subdirectories +/// if they don't already exist. +pub fn mkdir_recursive(p: &Path) -> bool { + if os::path_is_dir(p) { + return true; + } + let parent = p.dir_path(); + debug!("mkdir_recursive: parent = %s", + parent.to_str()); + if parent.to_str() == ~"." + || parent.to_str() == ~"/" { // !!! + // No parent directories to create + os::path_is_dir(&parent) && make_dir_rwx(p) } else { - // Create it - if os::make_dir(&rslt, (S_IRUSR | S_IWUSR | S_IXUSR) as i32) { - rslt - } - else { - cond.raise((rslt, ~"Could not create directory")) - } + mkdir_recursive(&parent) && make_dir_rwx(p) } } @@ -69,34 +73,94 @@ pub fn normalize(p: ~Path) -> ~Path { } } -#[cfg(test)] -mod test { - use core::{os, rand}; - use core::path::Path; - use path_util::*; - use core::rand::RngUtil; +// n.b. So far this only handles local workspaces +// n.b. The next three functions ignore the package version right +// now. Should fix that. - // Helper function to create a directory name that doesn't exist - pub fn mk_nonexistent(tmpdir: &Path, suffix: &str) -> Path { - let r = rand::rng(); - for 1000.times { - let p = tmpdir.push(r.gen_str(16) + suffix); - if !os::path_exists(&p) { - return p; - } - } - fail!(~"Couldn't compute a non-existent path name; this is worrisome") +/// True if there's a directory in with +/// pkgid's short name +pub fn workspace_contains_package_id(pkgid: PkgId, workspace: &Path) -> bool { + let pkgpath = workspace.push("src").push(pkgid.path.to_str()); + os::path_is_dir(&pkgpath) +} + +/// Return the directory for 's source files in . +/// Doesn't check that it exists. +pub fn pkgid_src_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + let result = workspace.push("src"); + result.push(pkgid.path.to_str()) +} + +/// Returns the executable that would be installed for +/// in +pub fn target_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + let result = workspace.push("bin"); + // should use a target-specific subdirectory + mk_output_path(Main, pkgid.path.to_str(), result) +} + + +/// Returns the executable that would be installed for +/// in +pub fn target_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + let result = workspace.push("lib"); + mk_output_path(Lib, pkgid.path.to_str(), result) +} + +/// Returns the test executable that would be installed for +/// in +pub fn target_test_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + let result = workspace.push("build"); + mk_output_path(Test, pkgid.path.to_str(), result) +} + +/// Returns the bench executable that would be installed for +/// in +pub fn target_bench_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + let result = workspace.push("build"); + mk_output_path(Bench, pkgid.path.to_str(), result) +} + +/// Return the directory for 's build artifacts in . +/// Creates it if it doesn't exist. +pub fn build_pkg_id_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + use conditions::bad_path::cond; + + let mut result = workspace.push("build"); + // n.b. Should actually use a target-specific + // subdirectory of build/ + result = result.push(normalize(~pkgid.path).to_str()); + if os::path_exists(&result) || mkdir_recursive(&result) { + result } - - #[test] - fn default_dir_ok() { - let the_path = os::tmpdir(); - let substitute_path = Path("xyzzy"); - assert!(default_dest_dir(&the_path) == the_path.push(~"build")); - let nonexistent_path = mk_nonexistent(&the_path, "quux"); - let bogus = do ::conditions::bad_path::cond.trap(|_| { - substitute_path - }).in { default_dest_dir(&nonexistent_path) }; - assert!(bogus == substitute_path); + else { + cond.raise((result, fmt!("Could not create directory for package %s", pkgid.to_str()))) + } +} + +/// Return the output file for a given directory name, +/// given whether we're building a library and whether we're building tests +pub fn mk_output_path(what: OutputType, short_name: ~str, dir: Path) -> Path { + match what { + Lib => dir.push(os::dll_filename(short_name)), + _ => dir.push(fmt!("%s%s%s", short_name, + if what == Test { ~"test" } else { ~"" }, + os::EXE_SUFFIX)) + } +} + +#[cfg(test)] +mod test { + use core::os; + + #[test] + fn recursive_mkdir_ok() { + let root = os::tmpdir(); + let path = "xy/z/zy"; + let nested = root.push(path); + assert!(super::mkdir_recursive(&nested)); + assert!(os::path_is_dir(&root.push("xy"))); + assert!(os::path_is_dir(&root.push("xy/z"))); + assert!(os::path_is_dir(&nested)); } } diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 705bcc82427..8381e6ad816 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -36,7 +36,8 @@ use rustc::metadata::filesearch; use std::{getopts}; use syntax::{ast, diagnostic}; use util::*; -use path_util::{dest_dir, normalize}; +use path_util::{normalize, workspace_contains_package_id}; +use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace, rust_path}; use rustc::driver::session::{lib_crate, bin_crate, crate_type}; mod conditions; @@ -70,7 +71,7 @@ impl PkgScript { /// 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(script: Path, id: PkgId) -> PkgScript { + fn parse(script: Path, workspace: &Path, id: PkgId) -> PkgScript { // Get the executable name that was invoked let binary = os::args()[0]; // Build the rustc session data structures to pass @@ -85,7 +86,7 @@ impl PkgScript { let cfg = driver::build_configuration(sess, @binary, &input); let (crate, _) = driver::compile_upto(sess, cfg, &input, driver::cu_parse, None); - let work_dir = dest_dir(id); + let work_dir = build_pkg_id_in_workspace(id, workspace); debug!("Returning package script with id %?", id); @@ -193,54 +194,60 @@ impl Ctx { // The package id is presumed to be the first command-line // argument let pkgid = PkgId::new(args[0]); - // Should allow the build directory to be configured. - // Right now it's always the "build" subdirectory in - // the package directory - let dst_dir = dest_dir(pkgid); - debug!("Destination dir = %s", dst_dir.to_str()); - // Right now, we assume the pkgid path is a valid dir - // relative to the CWD. In the future, we should search - // paths - let cwd = os::getcwd().normalize(); - debug!("Current working directory = %s", cwd.to_str()); + // Using the RUST_PATH, find workspaces that contain + // this package ID + let workspaces = rust_path().filtered(|ws| + workspace_contains_package_id(pkgid, ws)); + if workspaces.is_empty() { + fail!(fmt!("Package %s not found in any of \ + the following workspaces: %s", + pkgid.path.to_str(), + rust_path().to_str())); + } + for workspaces.each |workspace| { + let src_dir = pkgid_src_in_workspace(pkgid, workspace); + let build_dir = build_pkg_id_in_workspace(pkgid, workspace); + debug!("Destination dir = %s", build_dir.to_str()); - // Create the package source - let mut src = PkgSrc::new(&cwd, &dst_dir, &pkgid); - debug!("Package src = %?", src); + // Create the package source + let mut src = PkgSrc::new(&workspace.push("src"), &build_dir, &pkgid); + debug!("Package src = %?", src); - // Is there custom build logic? If so, use it - let pkg_src_dir = cwd.push_rel(&pkgid.path); - let mut custom = false;; - debug!("Package source directory = %s", pkg_src_dir.to_str()); - let cfgs = match src.package_script_option(&pkg_src_dir) { - Some(package_script_path) => { - let pscript = PkgScript::parse(package_script_path, - pkgid); - // Limited right now -- we're only running the post_build - // hook and probably fail otherwise - // also post_build should be called pre_build - let (cfgs, hook_result) = pscript.run_custom(~"post_build"); - debug!("Command return code = %?", hook_result); - if hook_result != 0 { - fail!(fmt!("Error running custom build command")) + // Is there custom build logic? If so, use it + let pkg_src_dir = src_dir; + let mut custom = false; + debug!("Package source directory = %s", pkg_src_dir.to_str()); + let cfgs = match src.package_script_option(&pkg_src_dir) { + Some(package_script_path) => { + let pscript = PkgScript::parse(package_script_path, + workspace, + pkgid); + // Limited right now -- we're only running the post_build + // hook and probably fail otherwise + // also post_build should be called pre_build + let (cfgs, hook_result) = pscript.run_custom(~"post_build"); + debug!("Command return code = %?", hook_result); + if hook_result != 0 { + fail!(fmt!("Error running custom build command")) + } + custom = true; + // otherwise, the package script succeeded + cfgs } - custom = true; - // otherwise, the package script succeeded - cfgs - } - None => { - debug!("No package script, continuing"); - ~[] - } - }; + None => { + debug!("No package script, continuing"); + ~[] + } + }; - // If there was a package script, it should have finished - // the build already. Otherwise... - if !custom { - // Find crates inside the workspace - src.find_crates(); - // Build it! - src.build(&dst_dir, cfgs); + // If there was a package script, it should have finished + // the build already. Otherwise... + if !custom { + // Find crates inside the workspace + src.find_crates(); + // Build it! + src.build(&build_dir, cfgs); + } } } ~"clean" => { @@ -250,8 +257,8 @@ impl Ctx { // The package id is presumed to be the first command-line // argument let pkgid = PkgId::new(args[0]); - - self.clean(pkgid); + let cwd = os::getcwd(); + self.clean(&cwd, pkgid); // tjc: should use workspace, not cwd } ~"do" => { if args.len() < 2 { @@ -304,57 +311,16 @@ impl Ctx { } fn do_cmd(&self, cmd: ~str, pkgname: ~str) { - match cmd { - ~"build" | ~"test" => { - util::error(~"that command cannot be manually called"); - fail!(~"do_cmd"); - } - _ => {} - } - - let cwd = &os::getcwd(); - let pkgid = PkgId::new(pkgname); - // Always use the "build" subdirectory of the package dir, - // but we should allow this to be configured - let dst_dir = dest_dir(pkgid); - - let mut src = PkgSrc::new(cwd, &dst_dir, &pkgid); - match src.package_script_option(cwd) { - Some(script_path) => { - let script = PkgScript::parse(script_path, pkgid); - let (_, status) = script.run_custom(cmd); // Ignore cfgs? - if status == 42 { - util::error(~"no fns are listening for that cmd"); - fail!(~"do_cmd"); - } - } - None => { - util::error(fmt!("invoked `do`, but there is no package script in %s", - cwd.to_str())); - fail!(~"do_cmd"); - } - } + // stub + fail!("`do` not yet implemented"); } - fn build(&self, _dir: &Path, _verbose: bool, _opt: bool, - _test: bool) -> Option { - // either not needed anymore, - // or needed only when we don't have a package script. Not sure which one. - fail!(); - } - - fn compile(&self, _crate: &Path, _dir: &Path, _flags: ~[~str], - _cfgs: ~[~str], _opt: bool, _test: bool) { - // What's the difference between build and compile? - fail!(~"compile not yet implemented"); - } - - fn clean(&self, id: PkgId) { + fn clean(&self, workspace: &Path, 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); + let dir = build_pkg_id_in_workspace(id, workspace); util::note(fmt!("Cleaning package %s (removing directory %s)", id.to_str(), dir.to_str())); if os::path_exists(&dir) { diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 2ab1ea1e7d2..36d409adcd2 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -116,7 +116,14 @@ pub impl PkgId { impl ToStr for PkgId { fn to_str(&self) -> ~str { // should probably use the filestem and not the whole path - fmt!("%s-%s", self.path.to_str(), self.version.to_str()) + fmt!("%s-%s", self.path.to_str(), + // Replace dots with -s in the version + // this is because otherwise rustc will think + // that foo-0.1 has .1 as its extension + // (Temporary hack until I figure out how to + // get rustc to not name the object file + // foo-0.o if I pass in foo-0.1 to build_output_filenames) + str::replace(self.version.to_str(), ".", "-")) } } @@ -438,7 +445,9 @@ pub fn compile_input(sysroot: Option, test: bool, crate_type: session::crate_type) -> bool { - let short_name = pkg_id.to_str(); + // Want just the directory component here + let pkg_filename = pkg_id.path.filename().expect(~"Weird pkg id"); + let short_name = fmt!("%s-%s", pkg_filename, pkg_id.version.to_str()); assert!(in_file.components.len() > 1); let input = driver::file_input(copy *in_file); @@ -515,7 +524,7 @@ pub fn compile_crate_from_input(input: driver::input, out_file: Path, binary: ~str, what: driver::compile_upto) -> @ast::crate { - debug!("Calling build_output_filenames with %?", build_dir_opt); + debug!("Calling build_output_filenames with %? and %s", build_dir_opt, out_file.to_str()); let outputs = driver::build_output_filenames(&input, &build_dir_opt, &Some(out_file), sess); debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type); let cfg = driver::build_configuration(sess, @binary, &input); From f945e57bd050227bbf92f151303785991173f2fe Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 17:56:15 -0700 Subject: [PATCH 4/5] rustpkg: Correct directory structure in test scenarios --- .../testsuite/pass/src/fancy-lib/{src => }/bar.rs | 0 .../pass/src/fancy-lib/{src => }/fancy-lib.rs | 2 +- .../testsuite/pass/src/fancy-lib/{src => }/foo.rs | 0 .../testsuite/pass/src/fancy-lib/pkg.rs | 15 ++++++++++----- .../pass/src/hello-world/{src => }/main.rs | 0 .../pass/src/install-paths/{src => }/bench.rs | 0 .../pass/src/install-paths/{src => }/lib.rs | 0 .../pass/src/install-paths/{src => }/main.rs | 0 .../pass/src/install-paths/{src => }/test.rs | 0 9 files changed, 11 insertions(+), 6 deletions(-) rename src/librustpkg/testsuite/pass/src/fancy-lib/{src => }/bar.rs (100%) rename src/librustpkg/testsuite/pass/src/fancy-lib/{src => }/fancy-lib.rs (92%) rename src/librustpkg/testsuite/pass/src/fancy-lib/{src => }/foo.rs (100%) rename src/librustpkg/testsuite/pass/src/hello-world/{src => }/main.rs (100%) rename src/librustpkg/testsuite/pass/src/install-paths/{src => }/bench.rs (100%) rename src/librustpkg/testsuite/pass/src/install-paths/{src => }/lib.rs (100%) rename src/librustpkg/testsuite/pass/src/install-paths/{src => }/main.rs (100%) rename src/librustpkg/testsuite/pass/src/install-paths/{src => }/test.rs (100%) diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/src/bar.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/bar.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/fancy-lib/src/bar.rs rename to src/librustpkg/testsuite/pass/src/fancy-lib/bar.rs diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/src/fancy-lib.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/fancy-lib.rs similarity index 92% rename from src/librustpkg/testsuite/pass/src/fancy-lib/src/fancy-lib.rs rename to src/librustpkg/testsuite/pass/src/fancy-lib/fancy-lib.rs index 55261a82098..dc068eed143 100644 --- a/src/librustpkg/testsuite/pass/src/fancy-lib/src/fancy-lib.rs +++ b/src/librustpkg/testsuite/pass/src/fancy-lib/fancy-lib.rs @@ -21,4 +21,4 @@ extern mod std; pub mod foo; pub mod bar; -#[path = "build/generated.rs"] pub mod generated; +#[path = "../../build/fancy_lib/generated.rs"] pub mod generated; diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/src/foo.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/foo.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/fancy-lib/src/foo.rs rename to src/librustpkg/testsuite/pass/src/fancy-lib/foo.rs diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs index be3c68d731b..eeaa0f68ed5 100644 --- a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs +++ b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs @@ -11,13 +11,18 @@ use core::run; pub fn main() { - let cwd = os::getcwd(); - debug!("cwd = %s", cwd.to_str()); - let file = io::file_writer(&Path(~"fancy-lib/build/generated.rs"), + use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; + + let out_path = Path(~"build/fancy_lib"); + if !os::path_exists(&out_path) { + assert!(os::make_dir(&out_path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); + } + + let file = io::file_writer(&out_path.push("generated.rs"), [io::Create]).get(); file.write_str("pub fn wheeeee() { for [1, 2, 3].each() |_| { assert!(true); } }"); // now compile the crate itself - run::run_program("rustc", ~[~"fancy-lib/fancy-lib.rs", ~"--lib", - ~"-o", ~"fancy-lib/build/fancy_lib"]); + run::run_program("rustc", ~[~"src/fancy-lib/fancy-lib.rs", ~"--lib", + ~"-o", out_path.push(~"fancy_lib").to_str()]); } \ No newline at end of file diff --git a/src/librustpkg/testsuite/pass/src/hello-world/src/main.rs b/src/librustpkg/testsuite/pass/src/hello-world/main.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/hello-world/src/main.rs rename to src/librustpkg/testsuite/pass/src/hello-world/main.rs diff --git a/src/librustpkg/testsuite/pass/src/install-paths/src/bench.rs b/src/librustpkg/testsuite/pass/src/install-paths/bench.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/install-paths/src/bench.rs rename to src/librustpkg/testsuite/pass/src/install-paths/bench.rs diff --git a/src/librustpkg/testsuite/pass/src/install-paths/src/lib.rs b/src/librustpkg/testsuite/pass/src/install-paths/lib.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/install-paths/src/lib.rs rename to src/librustpkg/testsuite/pass/src/install-paths/lib.rs diff --git a/src/librustpkg/testsuite/pass/src/install-paths/src/main.rs b/src/librustpkg/testsuite/pass/src/install-paths/main.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/install-paths/src/main.rs rename to src/librustpkg/testsuite/pass/src/install-paths/main.rs diff --git a/src/librustpkg/testsuite/pass/src/install-paths/src/test.rs b/src/librustpkg/testsuite/pass/src/install-paths/test.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/install-paths/src/test.rs rename to src/librustpkg/testsuite/pass/src/install-paths/test.rs From 4e2c8f422aec1aef910fdfdac57f5f66a7465355 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 24 Apr 2013 17:37:59 -0700 Subject: [PATCH 5/5] rustpkg: Preliminary work on install command Mostly just tests (that are ignored); install command is still stubbed out. --- src/librustpkg/conditions.rs | 5 ++ src/librustpkg/context.rs | 21 ++++++++ src/librustpkg/rustpkg.rc | 50 ++++++++----------- src/librustpkg/tests.rs | 93 ++++++++++++++++++++++++++++++++++++ src/librustpkg/util.rs | 2 +- src/librustpkg/workspace.rs | 34 +++++++++++++ 6 files changed, 175 insertions(+), 30 deletions(-) create mode 100644 src/librustpkg/context.rs create mode 100644 src/librustpkg/workspace.rs diff --git a/src/librustpkg/conditions.rs b/src/librustpkg/conditions.rs index 353995a816e..35e70af7914 100644 --- a/src/librustpkg/conditions.rs +++ b/src/librustpkg/conditions.rs @@ -11,7 +11,12 @@ // Useful conditions pub use core::path::Path; +pub use util::PkgId; condition! { bad_path: (super::Path, ~str) -> super::Path; } + +condition! { + nonexistent_package: (super::PkgId, ~str) -> super::Path; +} diff --git a/src/librustpkg/context.rs b/src/librustpkg/context.rs new file mode 100644 index 00000000000..db036f44a18 --- /dev/null +++ b/src/librustpkg/context.rs @@ -0,0 +1,21 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Context data structure used by rustpkg + +use core::hashmap::HashMap; + +pub struct Ctx { + // I'm not sure what this is for + json: bool, + // Cache of hashes of things already installed + // though I'm not sure why the value is a bool + dep_cache: @mut HashMap<~str, bool>, +} diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 8381e6ad816..e1edce6ce5b 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -36,14 +36,19 @@ use rustc::metadata::filesearch; use std::{getopts}; use syntax::{ast, diagnostic}; use util::*; -use path_util::{normalize, workspace_contains_package_id}; -use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace, rust_path}; +use path_util::normalize; +use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace}; +use workspace::pkg_parent_workspaces; use rustc::driver::session::{lib_crate, bin_crate, crate_type}; +use context::Ctx; mod conditions; +mod context; mod usage; mod path_util; +mod tests; mod util; +mod workspace; /// A PkgScript represents user-supplied custom logic for /// special build hooks. This only exists for packages with @@ -154,14 +159,6 @@ impl PkgScript { } -struct Ctx { - // I'm not sure what this is for - json: bool, - // Cache of hashes of things already installed - // though I'm not sure why the value is a bool - dep_cache: @mut HashMap<~str, bool>, -} - impl Ctx { fn run(&self, cmd: ~str, args: ~[~str]) { @@ -194,17 +191,7 @@ impl Ctx { // The package id is presumed to be the first command-line // argument let pkgid = PkgId::new(args[0]); - // Using the RUST_PATH, find workspaces that contain - // this package ID - let workspaces = rust_path().filtered(|ws| - workspace_contains_package_id(pkgid, ws)); - if workspaces.is_empty() { - fail!(fmt!("Package %s not found in any of \ - the following workspaces: %s", - pkgid.path.to_str(), - rust_path().to_str())); - } - for workspaces.each |workspace| { + for pkg_parent_workspaces(pkgid) |workspace| { let src_dir = pkgid_src_in_workspace(pkgid, workspace); let build_dir = build_pkg_id_in_workspace(pkgid, workspace); debug!("Destination dir = %s", build_dir.to_str()); @@ -271,10 +258,16 @@ impl Ctx { self.info(); } ~"install" => { - self.install(if args.len() >= 1 { Some(args[0]) } - else { None }, - if args.len() >= 2 { Some(args[1]) } - else { None }, false); + if args.len() < 1 { + return usage::install(); + } + + // The package id is presumed to be the first command-line + // argument + let pkgid = PkgId::new(args[0]); + for pkg_parent_workspaces(pkgid) |workspace| { + self.install(workspace, pkgid); + } } ~"prefer" => { if args.len() < 1 { @@ -310,9 +303,9 @@ impl Ctx { } } - fn do_cmd(&self, cmd: ~str, pkgname: ~str) { + fn do_cmd(&self, _cmd: ~str, _pkgname: ~str) { // stub - fail!("`do` not yet implemented"); + fail!(~"`do` not yet implemented"); } fn clean(&self, workspace: &Path, id: PkgId) { @@ -336,8 +329,7 @@ impl Ctx { fail!(~"info not yet implemented"); } - fn install(&self, _url: Option<~str>, - _target: Option<~str>, _cache: bool) { + fn install(&self, _workspace: &Path, _id: PkgId) { // stub fail!(~"install not yet implemented"); } diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index f5948606072..70c03c845ce 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -9,3 +9,96 @@ // except according to those terms. // rustpkg unit tests + +use context::Ctx; +use core::hashmap::HashMap; +use core::path::Path; +use core::os; +use core::io; +use core::option::*; +use std::tempfile::mkdtemp; +use util::{PkgId, default_version}; +use path_util::{target_executable_in_workspace, target_library_in_workspace, + target_test_in_workspace, target_bench_in_workspace, + make_dir_rwx}; + +fn fake_ctxt() -> Ctx { + Ctx { + json: false, + dep_cache: @mut HashMap::new() + } +} + +fn fake_pkg() -> PkgId { + PkgId { + path: Path(~"bogus"), + version: default_version() + } +} + +fn mk_temp_workspace() -> Path { + mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir") +} + +fn is_rwx(p: &Path) -> bool { + use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; + + match p.get_mode() { + None => return false, + Some(m) => { + ((m & S_IRUSR as uint) == S_IRUSR as uint + && (m & S_IWUSR as uint) == S_IWUSR as uint + && (m & S_IXUSR as uint) == S_IXUSR as uint) + } + } +} + +#[test] +fn test_make_dir_rwx() { + let temp = &os::tmpdir(); + let dir = temp.push(~"quux"); + let _ = os::remove_dir(&dir); + assert!(make_dir_rwx(&dir)); + assert!(os::path_is_dir(&dir)); + assert!(is_rwx(&dir)); + assert!(os::remove_dir(&dir)); +} + +#[test] +#[ignore(reason = "install not yet implemented")] +fn test_install_valid() { + let ctxt = fake_ctxt(); + let temp_pkg_id = fake_pkg(); + let temp_workspace() = mk_temp_workspace(); + // should have test, bench, lib, and main + ctxt.install(&temp_workspace, temp_pkg_id); + // Check that all files exist + let exec = target_executable_in_workspace(temp_pkg_id, &temp_workspace); + assert!(os::path_exists(&exec)); + assert!(is_rwx(&exec)); + let lib = target_library_in_workspace(temp_pkg_id, &temp_workspace); + assert!(os::path_exists(&lib)); + assert!(is_rwx(&lib)); + // And that the test and bench executables aren't installed + assert!(!os::path_exists(&target_test_in_workspace(temp_pkg_id, &temp_workspace))); + assert!(!os::path_exists(&target_bench_in_workspace(temp_pkg_id, &temp_workspace))); +} + +#[test] +#[ignore(reason = "install not yet implemented")] +fn test_install_invalid() { + use conditions::nonexistent_package::cond; + + let ctxt = fake_ctxt(); + let pkgid = fake_pkg(); + let temp_workspace = mk_temp_workspace(); + let expected_path = Path(~"quux"); + let substituted: Path = do cond.trap(|_| { + expected_path + }).in { + ctxt.install(&temp_workspace, pkgid); + // ok + fail!(~"test_install_invalid failed, should have raised a condition"); + }; + assert!(substituted == expected_path); +} \ No newline at end of file diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 36d409adcd2..28198e59f86 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -78,7 +78,7 @@ impl ToStr for Version { } /// Placeholder -fn default_version() -> Version { ExactRevision(0.1) } +pub fn default_version() -> Version { ExactRevision(0.1) } // Path-fragment identifier of a package such as // 'github.com/graydon/test'; path must be a relative diff --git a/src/librustpkg/workspace.rs b/src/librustpkg/workspace.rs new file mode 100644 index 00000000000..15e2166b24a --- /dev/null +++ b/src/librustpkg/workspace.rs @@ -0,0 +1,34 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// rustpkg utilities having to do with workspaces + +use path_util::{rust_path, workspace_contains_package_id}; +use util::PkgId; +use core::path::Path; + +pub fn pkg_parent_workspaces(pkgid: PkgId, action: &fn(&Path) -> bool) { + // Using the RUST_PATH, find workspaces that contain + // this package ID + let workspaces = rust_path().filtered(|ws| + workspace_contains_package_id(pkgid, ws)); + if workspaces.is_empty() { + // tjc: make this a condition + fail!(fmt!("Package %s not found in any of \ + the following workspaces: %s", + pkgid.path.to_str(), + rust_path().to_str())); + } + for workspaces.each |ws| { + if action(ws) { + break; + } + } +} \ No newline at end of file