Skip to content

Commit 4d4cabf

Browse files
committed
rustpkg: Implement install command
The install command should work now, though it only installs in-place (anything else has to wait until I implement RUST_PATH). Also including: core: Add remove_directory_recursive, change copy_file Make copy_file preserve permissions, and add a remove_directory_recursive function.
1 parent bfd3cd8 commit 4d4cabf

File tree

7 files changed

+328
-85
lines changed

7 files changed

+328
-85
lines changed

src/libcore/os.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,28 @@ pub fn list_dir_path(p: &Path) -> ~[~Path] {
772772
list_dir(p).map(|f| ~p.push(*f))
773773
}
774774
775+
/// Removes a directory at the specified path, after removing
776+
/// all its contents. Use carefully!
777+
pub fn remove_dir_recursive(p: &Path) -> bool {
778+
let mut error_happened = false;
779+
for walk_dir(p) |inner| {
780+
if !error_happened {
781+
if path_is_dir(inner) {
782+
if !remove_dir_recursive(inner) {
783+
error_happened = true;
784+
}
785+
}
786+
else {
787+
if !remove_file(inner) {
788+
error_happened = true;
789+
}
790+
}
791+
}
792+
};
793+
// Directory should now be empty
794+
!error_happened && remove_dir(p)
795+
}
796+
775797
/// Removes a directory at the specified path
776798
pub fn remove_dir(p: &Path) -> bool {
777799
return rmdir(p);
@@ -877,6 +899,10 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
877899
if istream as uint == 0u {
878900
return false;
879901
}
902+
// Preserve permissions
903+
let from_mode = from.get_mode().expect("copy_file: couldn't get permissions \
904+
for source file");
905+
880906
let ostream = do as_c_charp(to.to_str()) |top| {
881907
do as_c_charp("w+b") |modebuf| {
882908
libc::fopen(top, modebuf)
@@ -908,6 +934,15 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
908934
}
909935
fclose(istream);
910936
fclose(ostream);
937+
938+
// Give the new file the old file's permissions
939+
unsafe {
940+
if do str::as_c_str(to.to_str()) |to_buf| {
941+
libc::chmod(to_buf, from_mode as mode_t)
942+
} != 0 {
943+
return false; // should be a condition...
944+
}
945+
}
911946
return ok;
912947
}
913948
}
@@ -1594,13 +1629,15 @@ mod tests {
15941629
== buf.len() as size_t))
15951630
}
15961631
assert!((libc::fclose(ostream) == (0u as c_int)));
1632+
let in_mode = in.get_mode();
15971633
let rs = os::copy_file(&in, &out);
15981634
if (!os::path_exists(&in)) {
15991635
fail!(fmt!("%s doesn't exist", in.to_str()));
16001636
}
16011637
assert!((rs));
16021638
let rslt = run::run_program(~"diff", ~[in.to_str(), out.to_str()]);
16031639
assert!((rslt == 0));
1640+
assert!(out.get_mode() == in_mode);
16041641
assert!((remove_file(&in)));
16051642
assert!((remove_file(&out)));
16061643
}

src/librustpkg/conditions.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,13 @@ condition! {
1818
}
1919

2020
condition! {
21-
nonexistent_package: (super::PkgId, ~str) -> super::Path;
21+
nonexistent_package: (super::PkgId, ~str) -> ();
22+
}
23+
24+
condition! {
25+
copy_failed: (super::Path, super::Path) -> ();
26+
}
27+
28+
condition! {
29+
missing_pkg_files: (super::PkgId) -> ();
2230
}

src/librustpkg/path_util.rs

Lines changed: 119 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
use util::PkgId;
1414
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
15+
use core::os::mkdir_recursive;
1516

1617
#[deriving(Eq)]
1718
pub enum OutputType { Main, Lib, Bench, Test }
@@ -23,7 +24,7 @@ pub fn rust_path() -> ~[Path] {
2324
~[Path(".")]
2425
}
2526

26-
static u_rwx: i32 = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
27+
pub static u_rwx: i32 = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
2728

2829
/// Creates a directory that is readable, writeable,
2930
/// and executable by the user. Returns true iff creation
@@ -70,34 +71,137 @@ pub fn pkgid_src_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
7071
result.push(pkgid.path.to_str())
7172
}
7273

74+
/// Figure out what the executable name for <pkgid> in <workspace>'s build
75+
/// directory is, and if the file exists, return it.
76+
pub fn built_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Option<Path> {
77+
let mut result = workspace.push("build");
78+
result = result.push_rel(&pkgid.path);
79+
// should use a target-specific subdirectory
80+
result = mk_output_path(Main, fmt!("%s-%s", pkgid.path.to_str(), pkgid.version.to_str()),
81+
result);
82+
debug!("built_executable_in_workspace: checking whether %s exists",
83+
result.to_str());
84+
if os::path_exists(&result) {
85+
Some(result)
86+
}
87+
else {
88+
None
89+
}
90+
}
91+
92+
/// Figure out what the library name for <pkgid> in <workspace>'s build
93+
/// directory is, and if the file exists, return it.
94+
pub fn built_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Option<Path> {
95+
let mut result = workspace.push("build");
96+
result = result.push_rel(&pkgid.path);
97+
// should use a target-specific subdirectory
98+
result = mk_output_path(Lib, pkgid.path.to_str(), result);
99+
debug!("built_library_in_workspace: checking whether %s exists",
100+
result.to_str());
101+
102+
// We don't know what the hash is, so we have to search through the directory
103+
// contents
104+
let dir_contents = os::list_dir(&result.pop());
105+
debug!("dir has %? entries", dir_contents.len());
106+
107+
// n.b. This code assumes the pkgid's path only has one element
108+
let lib_prefix = fmt!("%s%s", os::consts::DLL_PREFIX, pkgid.path.to_str());
109+
let lib_filetype = fmt!("%s%s", pkgid.version.to_str(), os::consts::DLL_SUFFIX);
110+
111+
debug!("lib_prefix = %s and lib_filetype = %s", lib_prefix, lib_filetype);
112+
113+
let mut result_filename = None;
114+
for dir_contents.each |&p| {
115+
let mut which = 0;
116+
let mut hash = None;
117+
// Find a filename that matches the pattern: (lib_prefix)-hash-(version)(lib_suffix)
118+
// and remember what the hash was
119+
for p.each_split_char('-') |piece| {
120+
debug!("a piece = %s", piece);
121+
if which == 0 && piece != lib_prefix {
122+
break;
123+
}
124+
else if which == 0 {
125+
which += 1;
126+
}
127+
else if which == 1 {
128+
hash = Some(piece.to_owned());
129+
which += 1;
130+
}
131+
else if which == 2 && piece != lib_filetype {
132+
hash = None;
133+
break;
134+
}
135+
else if which == 2 {
136+
break;
137+
}
138+
else {
139+
// something went wrong
140+
hash = None;
141+
break;
142+
}
143+
}
144+
if hash.is_some() {
145+
result_filename = Some(p);
146+
break;
147+
}
148+
}
149+
150+
// Return the filename that matches, which we now know exists
151+
// (if result_filename != None)
152+
debug!("result_filename = %?", result_filename);
153+
match result_filename {
154+
None => None,
155+
Some(result_filename) => {
156+
let result_filename = result.with_filename(result_filename);
157+
debug!("result_filename = %s", result_filename.to_str());
158+
Some(result_filename)
159+
}
160+
}
161+
}
162+
73163
/// Returns the executable that would be installed for <pkgid>
74164
/// in <workspace>
165+
/// As a side effect, creates the bin-dir if it doesn't exist
75166
pub fn target_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
76-
let result = workspace.push("bin");
77-
// should use a target-specific subdirectory
78-
mk_output_path(Main, pkgid.path.to_str(), result)
167+
target_file_in_workspace(pkgid, workspace, Main)
79168
}
80169

81170

82171
/// Returns the executable that would be installed for <pkgid>
83172
/// in <workspace>
173+
/// As a side effect, creates the bin-dir if it doesn't exist
84174
pub fn target_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
85-
let result = workspace.push("lib");
86-
mk_output_path(Lib, pkgid.path.to_str(), result)
175+
target_file_in_workspace(pkgid, workspace, Lib)
87176
}
88177

89178
/// Returns the test executable that would be installed for <pkgid>
90179
/// in <workspace>
91180
pub fn target_test_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
92-
let result = workspace.push("build");
93-
mk_output_path(Test, pkgid.path.to_str(), result)
181+
target_file_in_workspace(pkgid, workspace, Test)
94182
}
95183

96184
/// Returns the bench executable that would be installed for <pkgid>
97185
/// in <workspace>
98186
pub fn target_bench_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
99-
let result = workspace.push("build");
100-
mk_output_path(Bench, pkgid.path.to_str(), result)
187+
target_file_in_workspace(pkgid, workspace, Bench)
188+
}
189+
190+
fn target_file_in_workspace(pkgid: PkgId, workspace: &Path,
191+
what: OutputType) -> Path {
192+
use conditions::bad_path::cond;
193+
194+
let (subdir, create_dir) = match what {
195+
Main => ("bin", true), Lib => ("lib", true), Test | Bench => ("build", false)
196+
};
197+
let result = workspace.push(subdir);
198+
if create_dir {
199+
if !os::path_exists(&result) && !mkdir_recursive(&result, u_rwx) {
200+
cond.raise((result, fmt!("I couldn't create the %s dir", subdir)));
201+
}
202+
}
203+
mk_output_path(what, pkgid.path.to_str(), result)
204+
101205
}
102206

103207
/// Return the directory for <pkgid>'s build artifacts in <workspace>.
@@ -123,7 +227,11 @@ pub fn mk_output_path(what: OutputType, short_name: ~str, dir: Path) -> Path {
123227
match what {
124228
Lib => dir.push(os::dll_filename(short_name)),
125229
_ => dir.push(fmt!("%s%s%s", short_name,
126-
if what == Test { ~"test" } else { ~"" },
230+
match what {
231+
Test => "test",
232+
Bench => "bench",
233+
_ => ""
234+
}
127235
os::EXE_SUFFIX))
128236
}
129237
}

0 commit comments

Comments
 (0)