feat: Add in the read dir. (#2141)

* feat: Add in the read dir.

Have a test that proves that this is working.

* chore: Let the read dir work while in a read only mode

* revert: To old sync
This commit is contained in:
J H
2023-02-17 12:32:18 -07:00
committed by Aiden McClelland
parent 4d3df867da
commit 2736fa5202
4 changed files with 138 additions and 1 deletions

View File

@@ -599,6 +599,51 @@ async fn js_action_test_zero_dir() {
.unwrap()
.unwrap();
}
#[tokio::test]
async fn js_action_test_read_dir() {
let js_action = JsProcedure { args: vec![] };
let path: PathBuf = "test/js_action_execute/"
.parse::<PathBuf>()
.unwrap()
.canonicalize()
.unwrap();
let package_id = "test-package".parse().unwrap();
let package_version: Version = "0.3.0.3".parse().unwrap();
let name = ProcedureName::Action("test-read-dir".parse().unwrap());
let volumes: Volumes = serde_json::from_value(serde_json::json!({
"main": {
"type": "data"
},
"compat": {
"type": "assets"
},
"filebrowser" :{
"package-id": "filebrowser",
"path": "data",
"readonly": true,
"type": "pointer",
"volume-id": "main",
}
}))
.unwrap();
let input: Option<serde_json::Value> = None;
let timeout = Some(Duration::from_secs(10));
js_action
.execute::<serde_json::Value, serde_json::Value>(
&path,
&package_id,
&package_version,
name,
&volumes,
input,
timeout,
ProcessGroupId(0),
None,
)
.await
.unwrap()
.unwrap();
}
#[tokio::test]
async fn js_rsync() {

View File

@@ -888,6 +888,49 @@ export const action = {
},
};
},
/**
* Test is for the feature of listing what's in a dir
* @param {*} effects
* @param {*} _input
* @returns
*/
async "test-read-dir"(effects, _input) {
await effects
.removeDir({
volumeId: "main",
path: "test-read-dir",
})
.catch(() => {});
await effects.createDir({
volumeId: "main",
path: "test-read-dir/deep/123",
});
await effects.writeFile({
path: "./test-read-dir/broken.log",
toWrite: "This is a test",
volumeId: "main",
})
let readDir = JSON.stringify(await effects.readDir({
volumeId: "main",
path: "test-read-dir",
}))
const expected = '["broken.log","deep"]'
assert(readDir === expected, `Failed to match the input (${readDir}) === (${expected}) of readDir`)
await effects.removeDir({
volumeId: "main",
path: "test-read-dir",
});
return {
result: {
copyable: false,
message: "Done",
version: "0",
qr: false,
},
};
},
/**
* Created this test because of issue
* https://github.com/Start9Labs/embassy-os/issues/2121

View File

@@ -114,6 +114,10 @@ const readJsonFile = async (
const createDir = (
{ volumeId = requireParam("volumeId"), path = requireParam("path") } = requireParam("options"),
) => Deno.core.opAsync("create_dir", volumeId, path);
const readDir = (
{ volumeId = requireParam("volumeId"), path = requireParam("path") } = requireParam("options"),
) => Deno.core.opAsync("read_dir", volumeId, path);
const removeDir = (
{ volumeId = requireParam("volumeId"), path = requireParam("path") } = requireParam("options"),
) => Deno.core.opAsync("remove_dir", volumeId, path);
@@ -186,7 +190,8 @@ const effects = {
sleep,
runDaemon,
signalGroup,
runRsync
runRsync,
readDir
};
const defaults = {

View File

@@ -281,6 +281,7 @@ impl JsExecutionEnvironment {
fns::remove_file::decl(),
fns::create_dir::decl(),
fns::remove_dir::decl(),
fns::read_dir::decl(),
fns::current_function::decl(),
fns::log_trace::decl(),
fns::log_warn::decl(),
@@ -844,6 +845,49 @@ mod fns {
tokio::fs::create_dir_all(new_file).await?;
Ok(())
}
#[op]
async fn read_dir(
state: Rc<RefCell<OpState>>,
volume_id: VolumeId,
path_in: PathBuf,
) -> Result<Vec<String>, AnyError> {
let volume_path = {
let state = state.borrow();
let ctx: &JsContext = state.borrow();
let volume_path = ctx
.volumes
.path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id)
.ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?;
volume_path
};
let new_file = volume_path.join(path_in);
// With the volume check
if !is_subset(&volume_path, &new_file).await? {
bail!(
"Path '{}' has broken away from parent '{}'",
new_file.to_string_lossy(),
volume_path.to_string_lossy(),
);
}
let mut reader = tokio::fs::read_dir(&new_file).await?;
let mut paths: Vec<String> = Vec::new();
let origin_path = format!("{}/", new_file.to_str().unwrap_or_default());
let remove_new_file = |other_path: String| other_path.replacen(&origin_path, "", 1);
let has_origin_path = |other_path: &String| other_path.starts_with(&origin_path);
while let Some(entry) = reader.next_entry().await? {
entry
.path()
.to_str()
.into_iter()
.map(ToString::to_string)
.filter(&has_origin_path)
.map(&remove_new_file)
.for_each(|x| paths.push(x));
}
paths.sort();
Ok(paths)
}
#[op]
fn current_function(state: &mut OpState) -> Result<String, AnyError> {