feat: implement GNU-style command line options with pflag
- Add pflag dependency for POSIX/GNU-style command line parsing - Replace Go standard flag package with pflag for better UX - Implement long options with double dashes (--config, --max-messages, --help) - Add short option aliases with single dashes (-c, -m, -h) - Update help message with proper formatting and application description - Update all documentation to reflect new flag syntax - Update test scripts to use new command line format GNU-style options provide better usability: - Long descriptive options with --flag-name format - Short single-character aliases for common options - Standard help flag behavior with --help/-h - Compatible with shell completion and standard conventions Command line interface now supports: - --config/-c FILE: Path to configuration file - --max-messages/-m N: Message processing limit per mailbox - --help/-h: Show help message and exit All existing functionality preserved with improved command line experience. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
651d95e98b
commit
031dd86b0d
8 changed files with 47 additions and 28 deletions
10
CLAUDE.md
10
CLAUDE.md
|
|
@ -20,13 +20,13 @@ cd go && go build -o mail2couch .
|
||||||
cd go && ./mail2couch
|
cd go && ./mail2couch
|
||||||
|
|
||||||
# Run with specific config file
|
# Run with specific config file
|
||||||
cd go && ./mail2couch -config /path/to/config.json
|
cd go && ./mail2couch --config /path/to/config.json
|
||||||
|
|
||||||
# Run with message limit (useful for large mailboxes)
|
# Run with message limit (useful for large mailboxes)
|
||||||
cd go && ./mail2couch -max-messages 100
|
cd go && ./mail2couch --max-messages 100
|
||||||
|
|
||||||
# Run with both config and message limit
|
# Run with both config and message limit
|
||||||
cd go && ./mail2couch -config /path/to/config.json -max-messages 50
|
cd go && ./mail2couch --config /path/to/config.json --max-messages 50
|
||||||
|
|
||||||
# Run linting/static analysis
|
# Run linting/static analysis
|
||||||
cd go && go vet ./...
|
cd go && go vet ./...
|
||||||
|
|
@ -80,7 +80,7 @@ The application uses `config.json` for configuration with the following structur
|
||||||
### Configuration File Discovery
|
### Configuration File Discovery
|
||||||
|
|
||||||
The application automatically searches for configuration files in the following order:
|
The application automatically searches for configuration files in the following order:
|
||||||
1. Path specified by `-config` command line flag
|
1. Path specified by `--config`/`-c` command line flag
|
||||||
2. `./config.json` (current working directory)
|
2. `./config.json` (current working directory)
|
||||||
3. `./config/config.json` (config subdirectory)
|
3. `./config/config.json` (config subdirectory)
|
||||||
4. `~/.config/mail2couch/config.json` (user XDG config directory)
|
4. `~/.config/mail2couch/config.json` (user XDG config directory)
|
||||||
|
|
@ -104,7 +104,7 @@ This design ensures the same `config.json` format will work for both Go and Rust
|
||||||
- ✅ Sync vs Archive mode implementation
|
- ✅ Sync vs Archive mode implementation
|
||||||
- ✅ CouchDB attachment storage for email attachments
|
- ✅ CouchDB attachment storage for email attachments
|
||||||
- ✅ Full message body and attachment handling with MIME multipart support
|
- ✅ Full message body and attachment handling with MIME multipart support
|
||||||
- ✅ Command line argument support (--max-messages flag)
|
- ✅ Command line argument support (GNU-style --max-messages/-m and --config/-c flags)
|
||||||
- ✅ Per-account CouchDB databases for better organization
|
- ✅ Per-account CouchDB databases for better organization
|
||||||
- ✅ Incremental sync functionality with IMAP SEARCH and sync metadata tracking
|
- ✅ Incremental sync functionality with IMAP SEARCH and sync metadata tracking
|
||||||
- ❌ Rust implementation
|
- ❌ Rust implementation
|
||||||
|
|
|
||||||
13
README.md
13
README.md
|
|
@ -39,7 +39,7 @@ A powerful email backup utility that synchronizes mail from IMAP accounts to Cou
|
||||||
|
|
||||||
### Operational Features
|
### Operational Features
|
||||||
- **Automatic Config Discovery**: Finds configuration files in standard locations
|
- **Automatic Config Discovery**: Finds configuration files in standard locations
|
||||||
- **Command Line Control**: Override settings with `--max-messages` and `--config` flags
|
- **Command Line Control**: GNU-style options with `--max-messages`/`-m` and `--config`/`-c` flags
|
||||||
- **Comprehensive Logging**: Detailed output for monitoring and troubleshooting
|
- **Comprehensive Logging**: Detailed output for monitoring and troubleshooting
|
||||||
- **Error Resilience**: Graceful handling of network issues and server problems
|
- **Error Resilience**: Graceful handling of network issues and server problems
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ The application will:
|
||||||
### Configuration File Discovery
|
### Configuration File Discovery
|
||||||
|
|
||||||
mail2couch automatically searches for configuration files in this order:
|
mail2couch automatically searches for configuration files in this order:
|
||||||
1. Path specified by `--config` flag
|
1. Path specified by `--config`/`-c` flag
|
||||||
2. `./config.json` (current directory)
|
2. `./config.json` (current directory)
|
||||||
3. `./config/config.json` (config subdirectory)
|
3. `./config/config.json` (config subdirectory)
|
||||||
4. `~/.config/mail2couch/config.json` (user config directory)
|
4. `~/.config/mail2couch/config.json` (user config directory)
|
||||||
|
|
@ -117,8 +117,9 @@ mail2couch automatically searches for configuration files in this order:
|
||||||
./mail2couch [options]
|
./mail2couch [options]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--config PATH Specify configuration file path
|
-c, --config FILE Path to configuration file
|
||||||
--max-messages N Limit messages processed per mailbox per run (0 = unlimited)
|
-m, --max-messages N Limit messages processed per mailbox per run (0 = unlimited)
|
||||||
|
-h, --help Show help message
|
||||||
```
|
```
|
||||||
|
|
||||||
### Folder Pattern Examples
|
### Folder Pattern Examples
|
||||||
|
|
@ -382,7 +383,7 @@ Complex setup with multiple accounts, filtering, and different sync modes:
|
||||||
- Schedule regular backups of CouchDB databases
|
- Schedule regular backups of CouchDB databases
|
||||||
|
|
||||||
### Performance Tuning
|
### Performance Tuning
|
||||||
- Use `--max-messages` to limit processing load
|
- Use `--max-messages`/`-m` to limit processing load
|
||||||
- Run during off-peak hours for large initial syncs
|
- Run during off-peak hours for large initial syncs
|
||||||
- Monitor IMAP server rate limits and connection limits
|
- Monitor IMAP server rate limits and connection limits
|
||||||
- Consider running multiple instances for different accounts
|
- Consider running multiple instances for different accounts
|
||||||
|
|
@ -408,7 +409,7 @@ Complex setup with multiple accounts, filtering, and different sync modes:
|
||||||
|
|
||||||
**Performance Problems**:
|
**Performance Problems**:
|
||||||
- Use date filtering (`since`) for large mailboxes
|
- Use date filtering (`since`) for large mailboxes
|
||||||
- Implement `--max-messages` limits for initial syncs
|
- Implement `--max-messages`/`-m` limits for initial syncs
|
||||||
- Monitor server-side rate limiting
|
- Monitor server-side rate limiting
|
||||||
|
|
||||||
For detailed troubleshooting, see the [test environment documentation](test/README.md).
|
For detailed troubleshooting, see the [test environment documentation](test/README.md).
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
|
@ -87,23 +88,37 @@ type CommandLineArgs struct {
|
||||||
MaxMessages int
|
MaxMessages int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseCommandLine parses command line arguments
|
// ParseCommandLine parses command line arguments using GNU-style options
|
||||||
func ParseCommandLine() *CommandLineArgs {
|
func ParseCommandLine() *CommandLineArgs {
|
||||||
configFlag := flag.String("config", "", "Path to configuration file")
|
var args CommandLineArgs
|
||||||
maxMessagesFlag := flag.Int("max-messages", 0, "Maximum number of messages to process per mailbox per run (0 = no limit)")
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
return &CommandLineArgs{
|
// Define long options with -- and short options with -
|
||||||
ConfigPath: *configFlag,
|
pflag.StringVarP(&args.ConfigPath, "config", "c", "", "Path to configuration file")
|
||||||
MaxMessages: *maxMessagesFlag,
|
pflag.IntVarP(&args.MaxMessages, "max-messages", "m", 0, "Maximum number of messages to process per mailbox per run (0 = no limit)")
|
||||||
|
|
||||||
|
// Add help option
|
||||||
|
pflag.BoolP("help", "h", false, "Show help message")
|
||||||
|
|
||||||
|
pflag.Parse()
|
||||||
|
|
||||||
|
// Handle help flag
|
||||||
|
if help, _ := pflag.CommandLine.GetBool("help"); help {
|
||||||
|
fmt.Fprintf(os.Stderr, "mail2couch - Email backup utility for CouchDB\n\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS]\n\n", os.Args[0])
|
||||||
|
fmt.Fprintf(os.Stderr, "Options:\n")
|
||||||
|
pflag.PrintDefaults()
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return &args
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindConfigFile searches for config.json in the following order:
|
// FindConfigFile searches for config.json in the following order:
|
||||||
// 1. Path specified by -config flag
|
// 1. Path specified by --config/-c flag
|
||||||
// 2. ./config.json (current directory)
|
// 2. ./config.json (current directory)
|
||||||
// 3. ~/.config/mail2couch/config.json (user config directory)
|
// 3. ./config/config.json (config subdirectory)
|
||||||
// 4. ~/.mail2couch.json (user home directory)
|
// 4. ~/.config/mail2couch/config.json (user config directory)
|
||||||
|
// 5. ~/.mail2couch.json (user home directory)
|
||||||
func FindConfigFile(args *CommandLineArgs) (string, error) {
|
func FindConfigFile(args *CommandLineArgs) (string, error) {
|
||||||
if args.ConfigPath != "" {
|
if args.ConfigPath != "" {
|
||||||
if _, err := os.Stat(args.ConfigPath); err == nil {
|
if _, err := os.Stat(args.ConfigPath); err == nil {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ require (
|
||||||
github.com/emersion/go-imap/v2 v2.0.0-beta.5
|
github.com/emersion/go-imap/v2 v2.0.0-beta.5
|
||||||
github.com/emersion/go-message v0.18.1
|
github.com/emersion/go-message v0.18.1
|
||||||
github.com/go-kivik/kivik/v4 v4.4.0
|
github.com/go-kivik/kivik/v4 v4.4.0
|
||||||
|
github.com/spf13/pflag v1.0.7
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
|
||||||
|
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
gitlab.com/flimzy/testy v0.14.0 h1:2nZV4Wa1OSJb3rOKHh0GJqvvhtE03zT+sKnPCI0owfQ=
|
gitlab.com/flimzy/testy v0.14.0 h1:2nZV4Wa1OSJb3rOKHh0GJqvvhtE03zT+sKnPCI0owfQ=
|
||||||
gitlab.com/flimzy/testy v0.14.0/go.mod h1:m3aGuwdXc+N3QgnH+2Ar2zf1yg0UxNdIaXKvC5SlfMk=
|
gitlab.com/flimzy/testy v0.14.0/go.mod h1:m3aGuwdXc+N3QgnH+2Ar2zf1yg0UxNdIaXKvC5SlfMk=
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ cd ../test
|
||||||
|
|
||||||
# Run mail2couch with test configuration
|
# Run mail2couch with test configuration
|
||||||
print_status "Running mail2couch with test configuration..."
|
print_status "Running mail2couch with test configuration..."
|
||||||
../go/mail2couch -config config-test.json -max-messages 3
|
../go/mail2couch --config config-test.json --max-messages 3
|
||||||
|
|
||||||
# Verify results
|
# Verify results
|
||||||
print_status "Verifying test results..."
|
print_status "Verifying test results..."
|
||||||
|
|
@ -112,7 +112,7 @@ done
|
||||||
|
|
||||||
# Test sync mode by running again (should show incremental behavior)
|
# Test sync mode by running again (should show incremental behavior)
|
||||||
print_status "Running mail2couch again to test incremental sync..."
|
print_status "Running mail2couch again to test incremental sync..."
|
||||||
../go/mail2couch -config config-test.json -max-messages 3
|
../go/mail2couch --config config-test.json --max-messages 3
|
||||||
|
|
||||||
print_status "🎉 Basic integration tests completed successfully!"
|
print_status "🎉 Basic integration tests completed successfully!"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ build_app() {
|
||||||
run_first_sync() {
|
run_first_sync() {
|
||||||
echo -e "\n${BLUE}Running first sync...${NC}"
|
echo -e "\n${BLUE}Running first sync...${NC}"
|
||||||
cd go
|
cd go
|
||||||
./mail2couch -config ../test/config-test.json -max-messages 5
|
./mail2couch --config ../test/config-test.json --max-messages 5
|
||||||
cd ..
|
cd ..
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,7 +138,7 @@ EOF
|
||||||
run_incremental_sync() {
|
run_incremental_sync() {
|
||||||
echo -e "\n${BLUE}Running incremental sync...${NC}"
|
echo -e "\n${BLUE}Running incremental sync...${NC}"
|
||||||
cd go
|
cd go
|
||||||
./mail2couch -config ../test/config-test.json -max-messages 10
|
./mail2couch --config ../test/config-test.json --max-messages 10
|
||||||
cd ..
|
cd ..
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ run_test() {
|
||||||
|
|
||||||
# Run mail2couch and capture output
|
# Run mail2couch and capture output
|
||||||
cd go
|
cd go
|
||||||
if ./mail2couch -config "../test/$config_file" -max-messages "$max_messages" 2>&1; then
|
if ./mail2couch --config "../test/$config_file" --max-messages "$max_messages" 2>&1; then
|
||||||
echo -e "${GREEN}✅ Test completed successfully${NC}"
|
echo -e "${GREEN}✅ Test completed successfully${NC}"
|
||||||
else
|
else
|
||||||
echo -e "${RED}❌ Test failed${NC}"
|
echo -e "${RED}❌ Test failed${NC}"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue