From 4d3960dfc17a2e52a8f182c4f7974bae079c0270 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 27 Jan 2025 20:17:30 -0300 Subject: [PATCH] chore: cleanup system vs internal vs sidecar rclone logic --- lib/rclone/init.ts | 93 +++++++++++++++++++++++------ main.ts | 80 +++++++++---------------- src-tauri/capabilities/default.json | 30 ++++------ 3 files changed, 116 insertions(+), 87 deletions(-) diff --git a/lib/rclone/init.ts b/lib/rclone/init.ts index 4f8cd73..a1268e7 100644 --- a/lib/rclone/init.ts +++ b/lib/rclone/init.ts @@ -7,30 +7,89 @@ import { fetch } from '@tauri-apps/plugin-http' import { platform } from '@tauri-apps/plugin-os' import { Command } from '@tauri-apps/plugin-shell' +export async function init() { + const system = await isSystemRcloneInstalled() + let internal = await isInternalRcloneInstalled() + const sidecar = await isSidecarRcloneInstalled() + + // rclone not available, let's download it + if (!(system || internal || sidecar)) { + await provisionRclone() + internal = true + } + + return { + system: system + ? async (args: string[]) => { + console.log('running system rclone') + return Command.create("rclone-system", args) + } + : null, + internal: internal + ? async (args: string[]) => { + console.log('running internal rclone') + return Command.create("rclone-internal", args, { + cwd: `${await appLocalDataDir()}`, + }) + } + : null, + sidecar: sidecar + ? async (args: string[]) => { + console.log('running sidecar rclone') + return Command.sidecar("binaries/rclone", args) + } + : null, + }; +} + /** * Checks if rclone is installed and accessible from the system PATH * @returns {Promise} True if rclone is installed and working */ -export async function checkRcloneInstalled() { - const output = await Command.create('rclone').execute() - // console.log('[checkRcloneInstalled] output', output) - return ( - output.stdout.includes('Available commands') || output.stderr.includes('Available commands') - ) +export async function isSystemRcloneInstalled() { + try { + const output = await Command.create('rclone-system').execute() + // console.log('[checkRcloneInstalled] output', output) + return ( + output.stdout.includes('Available commands') || output.stderr.includes('Available commands') + ) + } catch (_) { + return false + } } /** - * Checks if rclone is bundled with the application in the app's local data directory - * @returns {Promise} True if bundled rclone is present and working + * Checks if rclone is downloaded by the application in the app's local data directory + * @returns {Promise} True if downloaded rclone is present and working */ -export async function checkRcloneBundled() { - const output = await Command.create('./rclone', [], { - cwd: `${await appLocalDataDir()}`, - }).execute() - // console.log('[checkRcloneBundled] output', output) - return ( - output.stdout.includes('Available commands') || output.stderr.includes('Available commands') - ) +export async function isInternalRcloneInstalled() { + try { + const output = await Command.create('rclone-internal', [], { + cwd: `${await appLocalDataDir()}`, + }).execute() + // console.log('[checkRcloneBundled] output', output) + return ( + output.stdout.includes('Available commands') || output.stderr.includes('Available commands') + ) + } catch (_) { + return false + } +} + +/** + * Checks if rclone is available as a sidecar + * @returns {Promise} True if sidecar rclone is present and working + */ +export async function isSidecarRcloneInstalled() { + try { + const output = await Command.sidecar('binaries/rclone').execute() + // console.log('[checkRcloneBundled] output', output) + return ( + output.stdout.includes('Available commands') || output.stderr.includes('Available commands') + ) + } catch (_) { + return false + } } /** @@ -113,7 +172,7 @@ export async function provisionRclone() { await copyFile(rcloneBinaryPath, `${await appLocalDataDir()}/rclone`) - const hasInstalled = await checkRcloneInstalled() + const hasInstalled = await isInternalRcloneInstalled(); if (!hasInstalled) { throw new Error('Failed to install rclone') diff --git a/main.ts b/main.ts index 5037c69..79312f6 100644 --- a/main.ts +++ b/main.ts @@ -6,7 +6,7 @@ import { debug, error, info, trace, warn } from '@tauri-apps/plugin-log' import { exit } from '@tauri-apps/plugin-process' import { Command } from '@tauri-apps/plugin-shell' import { listRemotes } from './lib/rclone/api' -import { checkRcloneBundled, checkRcloneInstalled, provisionRclone } from './lib/rclone/init' +import { init as initRclone } from "./lib/rclone/init"; import { useStore } from './lib/store' import { initLoadingTray, initTray, rebuildTrayMenu } from './lib/tray' @@ -34,34 +34,19 @@ console.log('main') console.error('main') async function startRclone() { - let hasLocalRclone = false - try { - hasLocalRclone = await checkRcloneInstalled() - console.log('hasLocalRclone', hasLocalRclone) - } catch (error) { - console.error('Failed to check if rclone is installed', error) - } - console.log('hasLocalRclone', hasLocalRclone) + let rclone; - let hasBundledRclone = false try { - hasBundledRclone = await checkRcloneBundled() - console.log('hasBundledRclone', hasBundledRclone) + rclone = await initRclone(); } catch (error) { - console.error('Failed to check if rclone is bundled', error) - } - console.log('hasBundledRclone', hasBundledRclone) - - if (!hasLocalRclone && !hasBundledRclone) { - try { - await provisionRclone() - } catch (error) { - await confirm(error?.message || 'Failed to provision rclone, please try again later.', { - title: 'Error', - kind: 'error', - }) - return await exit(0) + await confirm( + error.message || "Failed to provision rclone, please try again later.", + { + title: "Error", + kind: "error", } + ); + return await exit(0); } try { @@ -72,31 +57,22 @@ async function startRclone() { return } catch {} - //! this works - // const command = Command.sidecar('binaries/rclone', [ - // 'rcd', - // '--rc-no-auth', - // '--rc-serve', - // // '-rc-addr', - // // ':5572', - // ]) + const rcloneCommandFn = rclone.system || rclone.internal || rclone.sidecar; - //! sidecar does not work with global or appdata binaries - const command = Command.create( - hasLocalRclone ? 'rclone' : './rclone', - [ - 'rcd', - '--rc-no-auth', - '--rc-serve', - // '-rc-addr', - // ':5572', - ], - hasLocalRclone - ? undefined - : { - cwd: `${await appLocalDataDir()}`, - } - ) + const command = await rcloneCommandFn([ + "rcd", + "--rc-no-auth", + "--rc-serve", + // '-rc-addr', + // ':5572', + ]); + + command.stdout.on("data", (line) => { + console.log("[rclone] " + line); + }); + command.stderr.on("data", (line) => { + console.log("[[rclone]] " + line); + }); command.addListener('close', async (event) => { console.log('close', event) @@ -114,9 +90,8 @@ async function startRclone() { console.log('error', event) }) - //! so we have to do this: - //! not await the call - const childProcess = command.execute() + console.log('running rclone') + const childProcess = await command.spawn() await new Promise((resolve) => setTimeout(resolve, 200)) @@ -143,3 +118,4 @@ getCurrentWindow().listen('rebuild-tray', async (e) => { initLoadingTray() .then(() => startRclone()) .then(() => initTray()) + .catch(console.error) diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 2f103f2..c08ffad 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -163,28 +163,22 @@ "shell:allow-spawn", "shell:allow-stdin-write", "shell:allow-open", - "shell:allow-execute", { "identifier": "shell:allow-execute", "allow": [ { - "name": "./rclone", - "cmd": "./rclone", - "args": true + "name": "binaries/rclone", + "args": true, + "sidecar": true }, { - "name": "rclone", + "name": "rclone-system", "cmd": "rclone", "args": true }, { - "name": "umount", - "cmd": "umount", - "args": true - }, - { - "name": "mount", - "cmd": "mount", + "name": "rclone-internal", + "cmd": "$APPLOCALDATA/rclone", "args": true } ] @@ -198,14 +192,14 @@ "sidecar": true }, { - "name": "./rclone", - "args": true, - "sidecar": true + "name": "rclone-system", + "cmd": "rclone", + "args": true }, { - "name": "rclone", - "args": true, - "sidecar": true + "name": "rclone-internal", + "cmd": "$APPLOCALDATA/rclone", + "args": true } ] },