ADDED: path_canonical/2, obtaining the canonical absolute path.

This addresses a remaining aspect of #511.
This commit is contained in:
Markus Triska
2020-07-15 20:24:26 +02:00
parent ec75e21898
commit 0f4667d942
3 changed files with 57 additions and 1 deletions

View File

@@ -178,6 +178,7 @@ pub enum SystemClauseType {
MakeDirectory,
DeleteFile,
WorkingDirectory,
PathCanonical,
DeleteAttribute,
DeleteHeadAttribute,
DynamicModuleResolution(usize),
@@ -345,6 +346,7 @@ impl SystemClauseType {
&SystemClauseType::MakeDirectory => clause_name!("$make_directory"),
&SystemClauseType::DeleteFile => clause_name!("$delete_file"),
&SystemClauseType::WorkingDirectory => clause_name!("$working_directory"),
&SystemClauseType::PathCanonical => clause_name!("$path_canonical"),
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
&SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
@@ -681,6 +683,7 @@ impl SystemClauseType {
("$make_directory", 1) => Some(SystemClauseType::MakeDirectory),
("$delete_file", 1) => Some(SystemClauseType::DeleteFile),
("$working_directory", 2) => Some(SystemClauseType::WorkingDirectory),
("$path_canonical", 2) => Some(SystemClauseType::PathCanonical),
("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
("$use_module_from_file", 1) =>
Some(SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile)),

View File

@@ -52,7 +52,8 @@
directory_exists/1,
delete_file/1,
make_directory/1,
working_directory/2]).
working_directory/2,
path_canonical/2]).
:- use_module(library(error)).
:- use_module(library(lists)).
@@ -87,7 +88,34 @@ delete_file(File) :-
list_of_chars(File),
'$delete_file'(File).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dir0 is the current working directory, and the working directory
is changed to Dir.
Use working_directory(Ds, Ds) to determine the current working directory,
and leave it as is.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
working_directory(Dir0, Dir) :-
can_be(list, Dir0),
can_be(list, Dir),
'$working_directory'(Dir0, Dir).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
True iff Cs is the canonical, absolute path of Ps.
All intermediate components are normalized, and all symbolic links
are resolved.
The predicate fails in the following situations, though not
necessarily *only* in these cases:
1. Ps is a path that does not exist.
2. A non-final component in Ps is not a directory.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
path_canonical(Ps, Cs) :-
must_be(list, Ps),
maplist(must_be(character), Ps),
can_be(list, Cs),
'$path_canonical'(Ps, Cs).

View File

@@ -918,6 +918,31 @@ impl MachineState {
return Ok(());
}
}
&SystemClauseType::PathCanonical => {
let path = self.heap_pstr_iter(self[temp_v!(1)]).to_string();
match fs::canonicalize(path) {
Ok(canonical) => {
let cs =
match canonical.to_str() {
Some(s) => { s }
_ => {
let stub = MachineError::functor_stub(clause_name!("path_canonical"), 2);
let err = MachineError::representation_error(RepFlag::Character);
let err = self.error_form(err, stub);
return Err(err);
}
};
let chars = self.heap.put_complete_string(cs);
self.unify(self[temp_v!(2)], chars);
}
_ => {
self.fail = true;
return Ok(());
}
}
}
&SystemClauseType::AtEndOfExpansion => {
if self.cp == LocalCodePtr::TopLevel(0, 0) {
self.at_end_of_expansion = true;