summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xrclone-ide192
1 files changed, 192 insertions, 0 deletions
diff --git a/rclone-ide b/rclone-ide
new file mode 100755
index 0000000..167614b
--- /dev/null
+++ b/rclone-ide
@@ -0,0 +1,192 @@
+#!/bin/env python3
+
+
+"""
+Rclone helper script for
+ - uploading files
+ - uploading directories
+ - downloading files
+ - downloading directories
+"""
+
+
+from typing import Mapping, List, Optional, Any
+import sys
+import os
+import argparse
+import subprocess
+import json
+
+
+config_file = ""
+config_dir = ""
+
+def find_config_file() -> str:
+ global config_file
+ global config_dir
+
+ if config_file != "":
+ return config_file
+
+ current_dir = os.getcwd()
+ while config_file == "":
+ for entry in os.scandir(current_dir):
+ if "rclone.conf" in entry.path:
+ config_file = entry.path
+ config_dir = current_dir
+
+ return config_file
+
+ # no config file found, fall back to system
+ if current_dir == "/":
+ process = subprocess.run(["rclone", "config", "file"], capture_output=True, text=True)
+ config_file = process.stdout.strip().splitlines()[1]
+ config_dir = os.path.dirname(config_file)
+
+ return config_file
+
+ current_dir = os.path.dirname(current_dir)
+
+
+
+def get_config() -> Mapping[str, Mapping[str, Any]]:
+ """Parse the rclone config"""
+
+ process = subprocess.run(["rclone", "config", "dump", "--config", find_config_file()], capture_output=True, text=True)
+ config = process.stdout.strip()
+
+ return json.loads(config)
+
+config = get_config()
+
+
+def get_remote_config(remote: str = "") -> Optional[Mapping[str, Mapping[str, Any]]]:
+ """Get config for specific remote. Fall back to default if unspecified"""
+
+ global config
+
+ if remote != "":
+ return {
+ "remote": remote,
+ "config": config[remote],
+ }
+
+ else:
+ if len(config.keys()) == 1:
+ return config.values[0]
+ else:
+ for remote_name in config.keys():
+ remote_config = config[remote_name]
+ if "rclone_ide_default" in remote_config.keys():
+ return {
+ "remote": remote_name,
+ "config": remote_config,
+ }
+
+ return None
+
+
+def build_cmd_local_path(config: Mapping[str, Any]) -> str:
+ """Build the local path part for the rclone command"""
+
+ global config_dir
+
+ if config["rclone_ide_local_path"] in [".", "./"]:
+ return config_dir
+
+ local_path = os.path.join(config_dir, config["rclone_ide_local_path"])
+
+ return local_path
+
+
+def build_cmd_remote_path(remote: str, config: Mapping[str, Any]) -> str:
+ """Build the remote path part for the rclone command"""
+
+ return "{}:{}".format(remote, config["rclone_ide_remote_path"])
+
+
+def build_cmd_config() -> str:
+ """Build the config option for the rclone command"""
+
+ global config_file
+
+ return f"--config={config_file}"
+
+
+def build_cmd_exclude() -> List[str]:
+ """Build the various exclude option parts for the rclone command."""
+
+ return ""
+
+
+def build_cmd_logging(log_level: str = "INFO") -> List[str]:
+ """Build the option parts for logging for the rclone command"""
+
+ log_dir_path = os.path.expanduser("~/.local/share/rclone-ide")
+
+ if not os.path.isdir(log_dir_path):
+ os.mkdir(log_dir_path)
+
+ cmd = [
+ f"--log-level={log_level}",
+ "--log-file={}".format(os.path.join(log_dir_path, "rclone.log")),
+ ]
+
+ return cmd
+
+
+def command_copy_file(options: Mapping[str, Any]) -> None:
+ """Copy specific file to remote"""
+
+ remote_config = get_remote_config(options.remote)
+
+ local_path = build_cmd_local_path(remote_config["config"])
+
+ # build relative path to file
+ local_file_path = os.path.join(
+ os.getcwd().replace(local_path, ""),
+ options.filepath
+ )
+
+ cmd = [
+ "rclone", "copy",
+ os.path.join(local_path, local_file_path),
+ os.path.join(
+ build_cmd_remote_path(remote_config["remote"], remote_config["config"]),
+ os.path.dirname(local_file_path),
+ ),
+ build_cmd_config(),
+ *build_cmd_logging(),
+ ]
+
+ if options.dry_run:
+ print(cmd)
+ else:
+ subprocess.run(cmd)
+
+
+parser = argparse.ArgumentParser(
+ prog="rclone-ide"
+)
+
+subparsers = parser.add_subparsers(dest="command")
+
+
+parser.add_argument("--dry-run", action="store_true")
+
+
+parser_copy_file = subparsers.add_parser("copyFile")
+parser_copy_file.add_argument("remote", help="rclone remote to upload to", choices=config.keys())
+parser_copy_file.add_argument("filepath", help="cwd-relative path to file")
+
+
+args = parser.parse_args()
+
+
+if args.command:
+ match args.command:
+ case "copyFile":
+ command_copy_file(args)
+
+else:
+ parser.print_help()