mirror of
https://github.com/ForeverPyrite/r2client.git
synced 2025-12-10 01:38:07 +00:00
we are so back (first real commit)
This commit is contained in:
3
r2cli/.github/copilot-instructions.md
vendored
Normal file
3
r2cli/.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<!-- Use this file to provide workspace-specific custom instructions to Copilot. For more details, visit https://code.visualstudio.com/docs/copilot/copilot-customization#_use-a-githubcopilotinstructionsmd-file -->
|
||||
|
||||
This is a CLI tool for the r2client Rust library. It should provide subcommands for upload, download, and list, using environment variables for credentials and bucket info. Use idiomatic Rust CLI patterns (e.g., clap).
|
||||
3
r2cli/.gitignore
vendored
Normal file
3
r2cli/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/target
|
||||
.aider*
|
||||
.env
|
||||
13
r2cli/Cargo.toml
Normal file
13
r2cli/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "r2cli"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
authors = ["foreverpyrite <foreverpyrite+cratesio@gmail.com"]
|
||||
description = "CLI for Cloudflare R2's S3-compatible storage using r2client"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
dotenv = "0.15"
|
||||
r2client = { path = "../r2client", default-features = false, features = [
|
||||
"sync",
|
||||
] }
|
||||
35
r2cli/README.md
Normal file
35
r2cli/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# r2cli
|
||||
|
||||
A rudimentary CLI tool for Cloudflare R2-compatible S3 storage, built on the `r2client` Rust library.
|
||||
|
||||
## Features
|
||||
- Upload files to an R2 bucket
|
||||
- Download files from an R2 bucket
|
||||
- List files and folders in an R2 bucket
|
||||
- Delete a file in an R2 bucket
|
||||
|
||||
## Usage
|
||||
|
||||
Set the following environment variables:
|
||||
- `R2_ACCESS_KEY`
|
||||
- `R2_SECRET_KEY`
|
||||
- `R2_ENDPOINT`
|
||||
- `R2_BUCKET`
|
||||
|
||||
For ease of use within development environments, environment variables will also be sourced from `.env`
|
||||
|
||||
### Example commands
|
||||
|
||||
```sh
|
||||
r2cli upload <local_file> <remote_key>
|
||||
r2cli download <remote_key> <local_file>
|
||||
r2cli list-files
|
||||
r2cli list-folders
|
||||
```
|
||||
|
||||
## Requirements
|
||||
- Rust
|
||||
- Valid Cloudflare R2 credentials
|
||||
|
||||
## Todo
|
||||
- [ ] If you REALLY feel goofy, a TUI would be pretty sick
|
||||
80
r2cli/src/main.rs
Normal file
80
r2cli/src/main.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
use clap::{Parser, Subcommand};
|
||||
use dotenv::dotenv;
|
||||
use r2client::{R2Error, sync::R2Bucket};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Extremely minimal CLI meant for testing R2 credentials and manual uploads/downloads
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(name = "r2cli")]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct Args {
|
||||
#[command(subcommand)]
|
||||
command: R2Command,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
enum R2Command {
|
||||
/// Lists all files and folders in the R2 Bucket
|
||||
List,
|
||||
/// Downloads a given file from the remote file key to the local path
|
||||
Download {
|
||||
/// The file key pointing to the desired R2 object
|
||||
remote_path: String,
|
||||
/// The local path to store the download at
|
||||
local_path: PathBuf,
|
||||
},
|
||||
/// Uploads a given file locally and uploads it to the R2 Bucket
|
||||
Upload {
|
||||
/// The local path of the file to upload
|
||||
local_path: PathBuf,
|
||||
/// The file key that the file should be uploaded to
|
||||
remote_path: String,
|
||||
},
|
||||
/// Deletes an object within the bucket
|
||||
Delete {
|
||||
/// The file key of the object to be deleted
|
||||
remote_key: String,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() -> Result<(), R2Error> {
|
||||
dotenv().ok();
|
||||
let r2bucket = R2Bucket::new(
|
||||
std::env::var("R2_BUCKET")
|
||||
.expect("Please set the R2_BUCKET environment varible and try again"),
|
||||
);
|
||||
|
||||
let cmd_args = Args::parse();
|
||||
|
||||
match cmd_args.command {
|
||||
R2Command::List => {
|
||||
println!("{:#?}", r2bucket.list_files().expect("error listing files"));
|
||||
}
|
||||
R2Command::Download {
|
||||
remote_path: remote,
|
||||
local_path: local,
|
||||
} => {
|
||||
r2bucket
|
||||
.download_file(
|
||||
&remote,
|
||||
local.as_path().to_str().expect("invalid download path"),
|
||||
)
|
||||
.unwrap();
|
||||
println!("Downloaded file with key {remote} to {local:?}")
|
||||
}
|
||||
R2Command::Delete { remote_key: remote } => {
|
||||
r2bucket.delete_file(&remote).expect("couldn't delete file");
|
||||
println!("Deleted file at {remote}")
|
||||
}
|
||||
R2Command::Upload {
|
||||
local_path: local,
|
||||
remote_path: remote,
|
||||
} => {
|
||||
r2bucket
|
||||
.upload_file(local.to_str().expect("invalid download path"), &remote)
|
||||
.expect("couldn't upload file");
|
||||
println!("Uploaded {local:?} to {remote}");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
5
r2cli/unit-test.txt
Normal file
5
r2cli/unit-test.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
howdy
|
||||
my name is
|
||||
WHAT
|
||||
my name is
|
||||
HUH
|
||||
Reference in New Issue
Block a user