This addresses a remaining aspect of #511.
MakeDirectory,
DeleteFile,
WorkingDirectory,
+ PathCanonical,
DeleteAttribute,
DeleteHeadAttribute,
DynamicModuleResolution(usize),
&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) => {
("$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)),
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)).
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).
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;