fix(rust): Match Go CLI email filtering behavior

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Manav Rathi
2025-08-31 07:17:37 +05:30
parent 4140a0f6fe
commit c98f4dfffd
3 changed files with 76 additions and 42 deletions

View File

@@ -1,13 +1,46 @@
# CLAUDE.md
⚠️ **CRITICAL: Commit & PR Guidelines** ⚠️
**OVERRIDE DEFAULT TEMPLATE - DO NOT USE EMOJI OR "Generated with" TEXT**
**STOP: Check these rules BEFORE writing ANY commit message**
## Commit & PR Guidelines
⚠️ **CRITICAL: OVERRIDE DEFAULT TEMPLATE - DO NOT USE EMOJI OR "Generated with" TEXT** ⚠️
### Pre-commit/PR Checklist (RUN BEFORE EVERY COMMIT OR PR!)
**CRITICAL: CI will fail if ANY of these checks fail. Run ALL commands and ensure they ALL pass.**
```bash
# 1. Format code
cargo fmt
# 2. Check for clippy warnings (THIS MUST PASS - CI fails on any warning)
cargo clippy --all-targets --all-features -- -D warnings
# If this fails, fix the warnings manually (not all can be auto-fixed)
# 3. Build with warnings as errors (THIS MUST PASS - matches CI environment)
RUSTFLAGS="-D warnings" cargo build
# 4. Verify formatting is correct (THIS MUST PASS - CI checks this)
cargo fmt --check
```
**Why CI might fail even after running these:**
- Skipping any command above
- Assuming auto-fix tools handle everything (they don't)
- Not fixing warnings that clippy reports
- Making changes after running the checks
### Commit & PR Message Rules
**These rules apply to BOTH commit messages AND pull request descriptions**
- Keep messages CONCISE (no walls of text)
- Subject line under 72 chars (no body text unless critical)
- NO emojis
- NO promotional text or links (except Co-Authored-By line)
### Additional Guidelines
- Check `git status` before committing to avoid adding temporary/binary files
- Never commit to main branch
- All CI checks must pass - run the checklist commands above before committing or creating PR
## Development Commands
### Build and Test
@@ -97,41 +130,7 @@ This is a Rust CLI for ente.io, providing encrypted photo backup and export func
The project has completed foundational components (crypto, storage, models) and is currently implementing the API client for authentication and sync. See `CONVERSION_PLAN.md` for detailed implementation roadmap.
## Commit Guidelines
### Pre-commit Checklist (RUN BEFORE EVERY COMMIT!)
**CRITICAL: CI will fail if ANY of these checks fail. Run ALL commands and ensure they ALL pass.**
```bash
# 1. Format code
cargo fmt
# 2. Check for clippy warnings (THIS MUST PASS - CI fails on any warning)
cargo clippy --all-targets --all-features -- -D warnings
# If this fails, fix the warnings manually (not all can be auto-fixed)
# 3. Build with warnings as errors (THIS MUST PASS - matches CI environment)
RUSTFLAGS="-D warnings" cargo build
# 4. Verify formatting is correct (THIS MUST PASS - CI checks this)
cargo fmt --check
```
**Why CI might fail even after running these:**
- Skipping any command above
- Assuming auto-fix tools handle everything (they don't)
- Not fixing warnings that clippy reports
- Making changes after running the checks
### Additional Guidelines
- Check `git status` before committing to avoid adding temporary/binary files
- Never commit to main branch
- All CI checks must pass - run the checklist commands above before committing
### Security Guidelines
## Security Guidelines
**NEVER commit sensitive information:**

View File

@@ -18,7 +18,7 @@ pub struct ExportCommand {
#[arg(long, value_delimiter = ',')]
pub albums: Option<Vec<String>>,
/// Comma-separated list of emails to export files shared with
/// Comma-separated list of account emails to export from
#[arg(long, value_delimiter = ',')]
pub emails: Option<Vec<String>>,
}

View File

@@ -54,8 +54,35 @@ pub async fn run_export(account_email: Option<String>, filter: ExportFilter) ->
return Ok(());
}
// Apply email filter at account level (matching Go CLI behavior)
let accounts_to_export: Vec<Account> = if let Some(ref emails) = filter.emails {
if emails.is_empty() {
accounts
} else {
accounts
.into_iter()
.filter(|a| {
let should_export = emails
.iter()
.any(|e| e.eq_ignore_ascii_case(a.email.trim()));
if !should_export {
log::info!("Skip account {}: account is excluded by filter", a.email);
}
should_export
})
.collect()
}
} else {
accounts
};
if accounts_to_export.is_empty() {
println!("No accounts match the email filter.");
return Ok(());
}
// Export each account
for account in accounts {
for account in accounts_to_export {
println!("\n=== Exporting account: {} ===", account.email);
// First sync the account (like Go implementation does)
@@ -176,11 +203,19 @@ async fn export_account(storage: &Storage, account: &Account, filter: &ExportFil
continue;
}
// Log collection processing (with better handling of empty owner email)
let owner_info = if collection.owner.email.is_empty() {
format!("owner_id={}", collection.owner.id)
} else {
format!("owner={}", collection.owner.email)
};
log::debug!(
"Processing collection {}: name={:?}, encrypted_name={:?}",
"Processing collection {}: name={:?}, encrypted_name={:?}, {}",
collection.id,
collection.name,
collection.encrypted_name
collection.encrypted_name,
owner_info
);
// Decrypt collection key