package cmd import ( "context" "fmt" "os" "os/exec" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) var ( remoteName string remoteType string remoteURL string remoteUser string remotePass string saFile string ) func init() { remoteCmd := &cobra.Command{ Use: "remote", Short: "Manage rclone remotes via drive-migrator", } createCmd := &cobra.Command{ Use: "create", Short: "Create new rclone remote", RunE: runRemoteCreate, } // Common flags createCmd.Flags().StringVar(&remoteName, "name", "", "Remote name (required)") createCmd.Flags().StringVar(&remoteType, "type", "", "Remote type (nextcloud|gdrive|webdav|onedrive|...) (required)") // WebDAV / Nextcloud createCmd.Flags().StringVar(&remoteURL, "url", "", "URL for WebDAV/Nextcloud remote") createCmd.Flags().StringVar(&remoteUser, "user", "", "Username for remote") createCmd.Flags().StringVar(&remotePass, "pass", "", "Password for remote") // Google Drive createCmd.Flags().StringVar(&saFile, "sa-file", "", "Service account JSON file for Google Drive") createCmd.MarkFlagRequired("name") createCmd.MarkFlagRequired("type") remoteCmd.AddCommand(createCmd) rootCmd.AddCommand(remoteCmd) } func runRemoteCreate(cmd *cobra.Command, args []string) error { ctx := context.Background() if remoteName == "" { return fmt.Errorf("remote name is required") } if remoteType == "" { return fmt.Errorf("remote type is required") } var rcloneArgs []string switch remoteType { case "nextcloud": if remoteURL == "" || remoteUser == "" || remotePass == "" { return fmt.Errorf("url, user, and pass are required for nextcloud remote") } rcloneArgs = []string{"config", "create", remoteName, "webdav", "vendor", "nextcloud", "url", remoteURL, "user", remoteUser, "pass", remotePass} case "webdav": if remoteURL == "" { return fmt.Errorf("url is required for webdav remote") } // If user/pass provided, include them rcloneArgs = []string{"config", "create", remoteName, "webdav", "url", remoteURL} if remoteUser != "" { rcloneArgs = append(rcloneArgs, "user", remoteUser) } if remotePass != "" { rcloneArgs = append(rcloneArgs, "pass", remotePass) } case "gdrive", "drive": if saFile == "" { return fmt.Errorf("sa-file is required for gdrive remote (service account)") } // Ensure file exists if _, err := os.Stat(saFile); err != nil { return fmt.Errorf("service account file not found: %v", err) } rcloneArgs = []string{"config", "create", remoteName, "drive", "service_account_file", saFile} default: return fmt.Errorf("unsupported remote type: %s", remoteType) } logrus.Infof("Creating rclone remote '%s' of type '%s'", remoteName, remoteType) cmdRclone := exec.CommandContext(ctx, "rclone", rcloneArgs...) cmdRclone.Stdout = logrus.StandardLogger().Writer() cmdRclone.Stderr = logrus.StandardLogger().Writer() if err := cmdRclone.Run(); err != nil { return fmt.Errorf("failed to create remote: %w", err) } logrus.Infof("Remote '%s' created successfully", remoteName) return nil }