diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs
index fab19b68174..fceff55abf8 100644
--- a/src/librustc/back/rpath.rs
+++ b/src/librustc/back/rpath.rs
@@ -40,7 +40,7 @@ pub fn get_rpath_flags(sess: session::Session, out_filename: &Path)
     // where rustrt is and we know every rust program needs it
     let libs = vec::append_one(libs, get_sysroot_absolute_rt_lib(sess));
 
-    let rpaths = get_rpaths(os, &sysroot, output, libs,
+    let rpaths = get_rpaths(os, sysroot, output, libs,
                             sess.opts.target_triple);
     rpaths_to_flags(rpaths)
 }
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 5e5d0640d80..d968cf708d9 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -603,7 +603,7 @@ pub fn build_session_options(binary: @~str,
             link::output_type_bitcode
         } else { link::output_type_exe };
     let sysroot_opt = getopts::opt_maybe_str(matches, ~"sysroot");
-    let sysroot_opt = sysroot_opt.map(|m| Path(*m));
+    let sysroot_opt = sysroot_opt.map(|m| @Path(*m));
     let target_opt = getopts::opt_maybe_str(matches, ~"target");
     let target_feature_opt = getopts::opt_maybe_str(matches, ~"target-feature");
     let save_temps = getopts::opt_present(matches, ~"save-temps");
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index 237b03bc20f..04cf3ca64f9 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -125,7 +125,7 @@ pub struct options {
     output_type: back::link::output_type,
     addl_lib_search_paths: ~[Path],
     linker_args: ~[~str],
-    maybe_sysroot: Option<Path>,
+    maybe_sysroot: Option<@Path>,
     target_triple: ~str,
     target_feature: ~str,
     // User-specified cfg meta items. The compiler itself will add additional
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index c88d5437c84..ded0b314d44 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -20,41 +20,49 @@ pub fn pick_file(file: Path, path: &Path) -> Option<Path> {
 }
 
 pub trait FileSearch {
-    fn sysroot(&self) -> Path;
-    fn lib_search_paths(&self) -> ~[Path];
+    fn sysroot(&self) -> @Path;
+    fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool);
     fn get_target_lib_path(&self) -> Path;
     fn get_target_lib_file_path(&self, file: &Path) -> Path;
 }
 
-pub fn mk_filesearch(maybe_sysroot: &Option<Path>,
+pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
                      target_triple: &str,
                      addl_lib_search_paths: ~[Path])
                   -> @FileSearch {
     struct FileSearchImpl {
-        sysroot: Path,
+        sysroot: @Path,
         addl_lib_search_paths: ~[Path],
         target_triple: ~str
     }
     impl FileSearch for FileSearchImpl {
-        fn sysroot(&self) -> Path { /*bad*/copy self.sysroot }
-        fn lib_search_paths(&self) -> ~[Path] {
-            let mut paths = /*bad*/copy self.addl_lib_search_paths;
+        fn sysroot(&self) -> @Path { self.sysroot }
+        fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) {
+            debug!("filesearch: searching additional lib search paths");
+            if !self.addl_lib_search_paths.each(f) {
+                return;
+            }
 
-            paths.push(
-                make_target_lib_path(&self.sysroot,
-                                     self.target_triple));
-            match get_rustpkg_lib_path_nearest() {
-              result::Ok(ref p) => paths.push((/*bad*/copy *p)),
-              result::Err(_) => ()
+            debug!("filesearch: searching target lib path");
+            if !f(&make_target_lib_path(self.sysroot,
+                                        self.target_triple)) {
+                return;
             }
-            match get_rustpkg_lib_path() {
-              result::Ok(ref p) => paths.push((/*bad*/copy *p)),
-              result::Err(_) => ()
-            }
-            paths
+            debug!("filesearch: searching rustpkg lib path nearest");
+            if match get_rustpkg_lib_path_nearest() {
+                    result::Ok(ref p) => f(p),
+                    result::Err(_) => true
+                } {
+                    return;
+                }
+           debug!("filesearch: searching rustpkg lib path");
+           match get_rustpkg_lib_path() {
+              result::Ok(ref p) => f(p),
+              result::Err(_) => true
+           }
         }
         fn get_target_lib_path(&self) -> Path {
-            make_target_lib_path(&self.sysroot, self.target_triple)
+            make_target_lib_path(self.sysroot, self.target_triple)
         }
         fn get_target_lib_file_path(&self, file: &Path) -> Path {
             self.get_target_lib_path().push_rel(file)
@@ -72,7 +80,7 @@ pub fn mk_filesearch(maybe_sysroot: &Option<Path>,
 
 pub fn search<T:Copy>(filesearch: @FileSearch, pick: pick<T>) -> Option<T> {
     let mut rslt = None;
-    for filesearch.lib_search_paths().each |lib_search_path| {
+    for filesearch.for_each_lib_search_path() |lib_search_path| {
         debug!("searching %s", lib_search_path.to_str());
         for os::list_dir_path(lib_search_path).each |path| {
             debug!("testing %s", path.to_str());
@@ -108,10 +116,10 @@ fn get_or_default_sysroot() -> Path {
     }
 }
 
-fn get_sysroot(maybe_sysroot: &Option<Path>) -> Path {
+fn get_sysroot(maybe_sysroot: &Option<@Path>) -> @Path {
     match *maybe_sysroot {
-      option::Some(ref sr) => (/*bad*/copy *sr),
-      option::None => get_or_default_sysroot()
+      option::Some(sr) => sr,
+      option::None => @get_or_default_sysroot()
     }
 }
 
diff --git a/src/librustpkg/context.rs b/src/librustpkg/context.rs
index db036f44a18..348d828bded 100644
--- a/src/librustpkg/context.rs
+++ b/src/librustpkg/context.rs
@@ -13,6 +13,9 @@
 use core::hashmap::HashMap;
 
 pub struct Ctx {
+    // Sysroot -- if this is None, uses rustc filesearch's
+    // idea of the default
+    sysroot_opt: Option<@Path>,
     // I'm not sure what this is for
     json: bool,
     // Cache of hashes of things already installed
diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs
index 161cb75e9e5..d21fdcda7f7 100644
--- a/src/librustpkg/path_util.rs
+++ b/src/librustpkg/path_util.rs
@@ -29,11 +29,7 @@ pub static u_rwx: i32 = (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.
-pub fn make_dir_rwx(p: &Path) -> bool {
-    use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
-
-    os::make_dir(p, u_rwx)
-}
+pub fn make_dir_rwx(p: &Path) -> bool { os::make_dir(p, u_rwx) }
 
 /// Replace all occurrences of '-' in the stem part of path with '_'
 /// This is because we treat rust-foo-bar-quux and rust_foo_bar_quux
diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc
index cc74f464e0e..dd5806ba015 100644
--- a/src/librustpkg/rustpkg.rc
+++ b/src/librustpkg/rustpkg.rc
@@ -306,7 +306,7 @@ impl Ctx {
             // Find crates inside the workspace
             src.find_crates();
             // Build it!
-            src.build(&build_dir, cfgs);
+            src.build(&build_dir, cfgs, self.sysroot_opt);
         }
 
     }
@@ -506,6 +506,7 @@ pub fn main() {
     }
 
     Ctx {
+        sysroot_opt: None, // Currently, only tests override this
         json: json,
         dep_cache: @mut HashMap::new()
     }.run(cmd, args);
@@ -648,6 +649,8 @@ impl PkgSrc {
 
         debug!("Checking dir: %s", dir.to_str());
 
+        // tjc: Rather than erroring out, need to try downloading the
+        // contents of the path to a local directory (#5679)
         if !os::path_exists(&dir) {
             cond.raise((self.id, ~"missing package dir"));
         }
@@ -744,18 +747,20 @@ impl PkgSrc {
                self.benchs.len())
     }
 
-    fn build_crates(&self, dst_dir: &Path,
-                           src_dir: &Path,
-                           crates: &[Crate],
-                           cfgs: ~[~str],
-                           test: bool, crate_type: crate_type) {
+    fn build_crates(&self,
+                    maybe_sysroot: Option<@Path>,
+                    dst_dir: &Path,
+                    src_dir: &Path,
+                    crates: &[Crate],
+                    cfgs: ~[~str],
+                    test: bool, crate_type: crate_type) {
 
         for crates.each |&crate| {
             let path = &src_dir.push_rel(&crate.file).normalize();
             util::note(fmt!("build_crates: compiling %s", path.to_str()));
             util::note(fmt!("build_crates: destination dir is %s", dst_dir.to_str()));
 
-            let result = util::compile_crate(None, self.id, path,
+            let result = util::compile_crate(maybe_sysroot, self.id, path,
                                      dst_dir,
                                      crate.flags,
                                      crate.cfgs + cfgs,
@@ -769,15 +774,15 @@ impl PkgSrc {
         }
     }
 
-    fn build(&self, dst_dir: &Path, cfgs: ~[~str]) {
+    fn build(&self, dst_dir: &Path, cfgs: ~[~str], maybe_sysroot: Option<@Path>) {
         let dir = self.check_dir();
         debug!("Building libs");
-        self.build_crates(dst_dir, &dir, self.libs, cfgs, false, lib_crate);
+        self.build_crates(maybe_sysroot, dst_dir, &dir, self.libs, cfgs, false, lib_crate);
         debug!("Building mains");
-        self.build_crates(dst_dir, &dir, self.mains, cfgs, false, bin_crate);
+        self.build_crates(maybe_sysroot, dst_dir, &dir, self.mains, cfgs, false, bin_crate);
         debug!("Building tests");
-        self.build_crates(dst_dir, &dir, self.tests, cfgs, true, bin_crate);
+        self.build_crates(maybe_sysroot, dst_dir, &dir, self.tests, cfgs, true, bin_crate);
         debug!("Building benches");
-        self.build_crates(dst_dir, &dir, self.benchs, cfgs, true, bin_crate);
+        self.build_crates(maybe_sysroot, dst_dir, &dir, self.benchs, cfgs, true, bin_crate);
     }
 }
diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs
index f38fc88f727..486e2959e9e 100644
--- a/src/librustpkg/tests.rs
+++ b/src/librustpkg/tests.rs
@@ -20,8 +20,9 @@ use path_util::{target_executable_in_workspace, target_library_in_workspace,
                make_dir_rwx, u_rwx};
 use core::os::mkdir_recursive;
 
-fn fake_ctxt() -> Ctx {
+fn fake_ctxt(sysroot_opt: Option<@Path>) -> Ctx {
     Ctx {
+        sysroot_opt: sysroot_opt,
         json: false,
         dep_cache: @mut HashMap::new()
     }
@@ -34,6 +35,13 @@ fn fake_pkg() -> PkgId {
     }
 }
 
+fn remote_pkg() -> PkgId {
+    PkgId {
+        path: Path(~"github.com/catamorphism/test-pkg"),
+        version: default_version()
+    }
+}
+
 fn writeFile(file_path: &Path, contents: ~str) {
     let out: @io::Writer =
         result::get(&io::file_writer(file_path,
@@ -69,6 +77,15 @@ fn is_rwx(p: &Path) -> bool {
     }
 }
 
+#[cfg(test)]
+fn test_sysroot() -> Path {
+    // Totally gross hack but it's just for test cases.
+    // Infer the sysroot from the exe name and tack "stage2"
+    // onto it. (Did I mention it was a gross hack?)
+    let self_path = os::self_exe_path().expect("Couldn't get self_exe path");
+    self_path.pop().push("stage2")
+}
+
 #[test]
 fn test_make_dir_rwx() {
     let temp = &os::tmpdir();
@@ -84,11 +101,9 @@ fn test_make_dir_rwx() {
 
 #[test]
 fn test_install_valid() {
-    use rustc::metadata::filesearch;
-
-    let sysroot = filesearch::get_rustpkg_sysroot();
-    debug!("sysroot = %s", sysroot.get().to_str());
-    let ctxt = fake_ctxt();
+    let sysroot = test_sysroot();
+    debug!("sysroot = %s", sysroot.to_str());
+    let ctxt = fake_ctxt(Some(@sysroot));
     let temp_pkg_id = fake_pkg();
     let temp_workspace = mk_temp_workspace(&temp_pkg_id.path);
     // should have test, bench, lib, and main
@@ -114,7 +129,7 @@ fn test_install_invalid() {
     use conditions::nonexistent_package::cond;
     use cond1 = conditions::missing_pkg_files::cond;
 
-    let ctxt = fake_ctxt();
+    let ctxt = fake_ctxt(None);
     let pkgid = fake_pkg();
     let temp_workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
     let mut error_occurred = false;
@@ -130,3 +145,29 @@ fn test_install_invalid() {
     }
     assert!(error_occurred && error1_occurred);
 }
+
+#[test]
+#[ignore(reason = "install from URL-fragment not yet implemented")]
+fn test_install_url() {
+    let sysroot = test_sysroot();
+    debug!("sysroot = %s", sysroot.to_str());
+    let ctxt = fake_ctxt(Some(@sysroot));
+    let temp_pkg_id = remote_pkg();
+    let temp_workspace = mk_temp_workspace(&temp_pkg_id.path);
+    // 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);
+    debug!("exec = %s", exec.to_str());
+    assert!(os::path_exists(&exec));
+    assert!(is_rwx(&exec));
+    let lib = target_library_in_workspace(temp_pkg_id, &temp_workspace);
+    debug!("lib = %s", lib.to_str());
+    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)));
+    let bench = target_bench_in_workspace(temp_pkg_id, &temp_workspace);
+    debug!("bench = %s", bench.to_str());
+    assert!(!os::path_exists(&bench));
+}
\ No newline at end of file
diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs
index 1b3d72bf6aa..0762fa4ad7f 100644
--- a/src/librustpkg/util.rs
+++ b/src/librustpkg/util.rs
@@ -435,7 +435,7 @@ pub fn add_pkg(pkg: &Pkg) -> bool {
 }
 
 // FIXME (#4432): Use workcache to only compile when needed
-pub fn compile_input(sysroot: Option<Path>,
+pub fn compile_input(sysroot: Option<@Path>,
                      pkg_id: PkgId,
                      in_file: &Path,
                      out_dir: &Path,
@@ -474,6 +474,7 @@ pub fn compile_input(sysroot: Option<Path>,
            out_file.to_str());
     debug!("flags: %s", str::connect(flags, ~" "));
     debug!("cfgs: %s", str::connect(cfgs, ~" "));
+    debug!("compile_input's sysroot = %?", sysroot);
 
     let matches = getopts(~[~"-Z", ~"time-passes"]
                           + if building_library { ~[~"--lib"] }
@@ -587,7 +588,7 @@ fn add_attrs(c: ast::crate, new_attrs: ~[attribute]) -> @ast::crate {
 
 // Called by build_crates
 // FIXME (#4432): Use workcache to only compile when needed
-pub fn compile_crate(sysroot: Option<Path>, pkg_id: PkgId,
+pub fn compile_crate(sysroot: Option<@Path>, pkg_id: PkgId,
                      crate: &Path, dir: &Path,
                      flags: ~[~str], cfgs: ~[~str], opt: bool,
                      test: bool, crate_type: crate_type) -> bool {