mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-04 22:39:46 +00:00
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:
@@ -599,6 +599,51 @@ async fn js_action_test_zero_dir() {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.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]
|
#[tokio::test]
|
||||||
async fn js_rsync() {
|
async fn js_rsync() {
|
||||||
|
|||||||
@@ -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
|
* Created this test because of issue
|
||||||
* https://github.com/Start9Labs/embassy-os/issues/2121
|
* https://github.com/Start9Labs/embassy-os/issues/2121
|
||||||
|
|||||||
@@ -114,6 +114,10 @@ const readJsonFile = async (
|
|||||||
const createDir = (
|
const createDir = (
|
||||||
{ volumeId = requireParam("volumeId"), path = requireParam("path") } = requireParam("options"),
|
{ volumeId = requireParam("volumeId"), path = requireParam("path") } = requireParam("options"),
|
||||||
) => Deno.core.opAsync("create_dir", volumeId, path);
|
) => 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 = (
|
const removeDir = (
|
||||||
{ volumeId = requireParam("volumeId"), path = requireParam("path") } = requireParam("options"),
|
{ volumeId = requireParam("volumeId"), path = requireParam("path") } = requireParam("options"),
|
||||||
) => Deno.core.opAsync("remove_dir", volumeId, path);
|
) => Deno.core.opAsync("remove_dir", volumeId, path);
|
||||||
@@ -186,7 +190,8 @@ const effects = {
|
|||||||
sleep,
|
sleep,
|
||||||
runDaemon,
|
runDaemon,
|
||||||
signalGroup,
|
signalGroup,
|
||||||
runRsync
|
runRsync,
|
||||||
|
readDir
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaults = {
|
const defaults = {
|
||||||
|
|||||||
@@ -281,6 +281,7 @@ impl JsExecutionEnvironment {
|
|||||||
fns::remove_file::decl(),
|
fns::remove_file::decl(),
|
||||||
fns::create_dir::decl(),
|
fns::create_dir::decl(),
|
||||||
fns::remove_dir::decl(),
|
fns::remove_dir::decl(),
|
||||||
|
fns::read_dir::decl(),
|
||||||
fns::current_function::decl(),
|
fns::current_function::decl(),
|
||||||
fns::log_trace::decl(),
|
fns::log_trace::decl(),
|
||||||
fns::log_warn::decl(),
|
fns::log_warn::decl(),
|
||||||
@@ -844,6 +845,49 @@ mod fns {
|
|||||||
tokio::fs::create_dir_all(new_file).await?;
|
tokio::fs::create_dir_all(new_file).await?;
|
||||||
Ok(())
|
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]
|
#[op]
|
||||||
fn current_function(state: &mut OpState) -> Result<String, AnyError> {
|
fn current_function(state: &mut OpState) -> Result<String, AnyError> {
|
||||||
|
|||||||
Reference in New Issue
Block a user