From 87d1238627eb5042f8b1b7bfa9ad8f89c88a4f11 Mon Sep 17 00:00:00 2001 From: joshuaboud Date: Mon, 30 May 2022 13:45:23 -0300 Subject: [PATCH] add host and move processLinks --- .../src/components/DirectoryEntryList.vue | 30 ++-------------- navigator/src/functions/getDirEntryObjects.js | 35 +++++++++++++++++-- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/navigator/src/components/DirectoryEntryList.vue b/navigator/src/components/DirectoryEntryList.vue index 755e9ff..67fd310 100644 --- a/navigator/src/components/DirectoryEntryList.vue +++ b/navigator/src/components/DirectoryEntryList.vue @@ -32,6 +32,7 @@ export default { name: 'DirectoryEntryList', props: { path: String, + host: String, searchFilterRegExp: RegExp, show: { type: Boolean, @@ -137,31 +138,6 @@ export default { } } - const processLinks = (linkTargets) => { - if (linkTargets.length === 0) - return null; - const callback = state => state.stdout - .trim() - .split(RECORD_SEPARATOR) - .filter(record => record) - .map((record, index) => { - if (record.includes(UNIT_SEPARATOR)) { - const [type, mode] = record.split(UNIT_SEPARATOR); - linkTargets[index].type = type; - linkTargets[index].mode = mode; - linkTargets[index].broken = false; - } else { // error - linkTargets[index].broken = true; - } - }); - return new Promise((resolve, reject) => - useSpawn(['stat', `--printf=%F${UNIT_SEPARATOR}%f${RECORD_SEPARATOR}`, ...linkTargets.map(target => target.path)], { superuser: 'try', err: 'out' }).promise() - .then(callback) - .catch(callback) - .finally(resolve) - ) - } - const getEntries = async () => { if (!props.path) { return; @@ -172,15 +148,15 @@ export default { const cwd = props.path; const procs = []; procs.push(...entryRefs.value.filter(entryRef => entryRef.showEntries).map(entryRef => entryRef.getEntries())); - const entryNames = await getDirListing(cwd, (message) => notifications.value.constructNotification("Failed to parse file name", message, 'error')); + const entryNames = await getDirListing(cwd, props.host, (message) => notifications.value.constructNotification("Failed to parse file name", message, 'error')); const tmpEntries = ( await getDirEntryObjects( entryNames, cwd, + props.host, (message) => notifications.value.constructNotification("Failed to parse file name", message, 'error') ) ); - procs.push(processLinks(tmpEntries.filter(entry => entry.type === 'symbolic link').map(entry => entry.target))); processingHandler.start(); return Promise.all(procs) .then(() => { diff --git a/navigator/src/functions/getDirEntryObjects.js b/navigator/src/functions/getDirEntryObjects.js index ae31d73..2f2873e 100644 --- a/navigator/src/functions/getDirEntryObjects.js +++ b/navigator/src/functions/getDirEntryObjects.js @@ -38,16 +38,43 @@ import { UNIT_SEPARATOR, RECORD_SEPARATOR } from "../constants"; * @property {Boolean} selected - Whether or not the user has selected this entry in the browser */ + async function processLinks(linkTargets, host) { + if (linkTargets.length === 0) + return; + ( + await useSpawn( + // Separate by newline so errors will slot in + ['stat', `--printf=%F${UNIT_SEPARATOR}%f\n`, ...linkTargets.map(target => target.path)], + { superuser: 'try', err: 'out', host: host } // stderr >&stdout for maintaining index order + ).promise() + .catch(state => state) // ignore errors, error message will maintain index order + ).stdout + .trim() + .split('\n') + .filter(record => record) + .map((record, index) => { + if (record.includes(UNIT_SEPARATOR)) { + const [type, mode] = record.split(UNIT_SEPARATOR); + linkTargets[index].type = type; + linkTargets[index].mode = mode; + linkTargets[index].broken = false; + } else { // error + linkTargets[index].broken = true; + } + }); +} + /** * Get list of directory entry objects from list of directory entry names * * @param {String[]} dirListing - List of entry names * @param {String} cwd - Working directory to run stat in + * @param {String} host - Host to run stat on * @param {getDirEntryObjectsFailCallback} failCallback - Callback function for handling errors, receives {String} message * @param {ByteFormatter} byteFormatter - Function to format bytes * @returns {Promise} Array of DirectoryEntry objects */ -async function getDirEntryObjects(dirListing, cwd, failCallback, byteFormatter = cockpit.format_bytes) { +async function getDirEntryObjects(dirListing, cwd, host, failCallback, byteFormatter = cockpit.format_bytes) { const fields = [ '%n', // path '%f', // mode (raw hex) @@ -61,19 +88,21 @@ async function getDirEntryObjects(dirListing, cwd, failCallback, byteFormatter = '%F', // type '%N', // quoted name with symlink ] - return dirListing.length + const entries = dirListing.length ? parseRawEntryStats( ( await useSpawn([ 'stat', `--printf=${fields.join(UNIT_SEPARATOR)}${RECORD_SEPARATOR}`, ...dirListing - ], { superuser: 'try', directory: cwd } + ], { superuser: 'try', directory: cwd, host } ) .promise() .catch(state => state) // ignore errors ).stdout, cwd, failCallback, byteFormatter) : []; + await processLinks(entries.filter(entry => entry.type === 'symbolic link').map(entry => entry.target)); + return entries; } /**