diff options
| author | Daniel Weipert <git@mail.dweipert.de> | 2026-03-14 22:53:20 +0100 |
|---|---|---|
| committer | Daniel Weipert <git@mail.dweipert.de> | 2026-03-14 22:53:20 +0100 |
| commit | 3f67eb415e5458d50711d55f136f86b2ac6b7ff0 (patch) | |
| tree | bee3f13280200a9d8e09f58c18e8d75be0aba159 | |
initial commit
| -rwxr-xr-x | rclone-ide | 192 |
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() |
