make -d and -s3 mutually exclusive

This commit is contained in:
Pim van Pelt
2025-12-03 00:14:15 +01:00
parent 36e5d33c49
commit 62db5b2008
2 changed files with 30 additions and 20 deletions

View File

@@ -215,8 +215,8 @@ func generateS3HTML(entries []indexgen.FileEntry, opts *indexgen.Options) error
func main() { func main() {
var opts indexgen.Options var opts indexgen.Options
var excludeRegexStr string var excludeRegexStr string
var s3Mode bool
var directory string var directory string
var s3URL string
// Set defaults // Set defaults
opts.DirAppend = true opts.DirAppend = true
@@ -224,33 +224,38 @@ func main() {
opts.Recursive = true opts.Recursive = true
opts.IncludeHidden = true opts.IncludeHidden = true
flag.StringVar(&directory, "d", "", "directory or S3 URL to process (required)") flag.StringVar(&directory, "d", "", "local directory to process")
flag.StringVar(&s3URL, "s3", "", "S3 URL to process")
flag.StringVar(&opts.Filter, "f", "*", "only include files matching glob") flag.StringVar(&opts.Filter, "f", "*", "only include files matching glob")
flag.StringVar(&excludeRegexStr, "x", "", "exclude files matching regular expression") flag.StringVar(&excludeRegexStr, "x", "", "exclude files matching regular expression")
flag.BoolVar(&opts.Verbose, "v", false, "verbosely list every processed file") flag.BoolVar(&opts.Verbose, "v", false, "verbosely list every processed file")
flag.BoolVar(&s3Mode, "s3", false, "treat -d argument as S3 URL")
flag.Usage = func() { flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Generate directory index files (recursive is ON, hidden files included by default).\n") fmt.Fprintf(os.Stderr, "Generate directory index files (recursive is ON, hidden files included by default).\n")
fmt.Fprintf(os.Stderr, "Output file is 'index.html', directory href appending is enabled.\n") fmt.Fprintf(os.Stderr, "Output file is 'index.html', directory href appending is enabled.\n")
fmt.Fprintf(os.Stderr, "Directory must be specified with -d flag.\n") fmt.Fprintf(os.Stderr, "Specify either -d <directory> OR -s3 <url> (mutually exclusive).\n")
fmt.Fprintf(os.Stderr, "For S3 mode, use -s3 flag with S3 URL in -d.\n")
fmt.Fprintf(os.Stderr, "S3 URLs: http://host:port/bucket or https://host/bucket\n") fmt.Fprintf(os.Stderr, "S3 URLs: http://host:port/bucket or https://host/bucket\n")
fmt.Fprintf(os.Stderr, "For S3, set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.\n") fmt.Fprintf(os.Stderr, "For S3, set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.\n")
fmt.Fprintf(os.Stderr, "Optionally filter by file types with -f \"*.py\".\n\n") fmt.Fprintf(os.Stderr, "Optionally filter by file types with -f \"*.py\".\n\n")
fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS]\n\n", os.Args[0]) fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS]\n\n", os.Args[0])
fmt.Fprintf(os.Stderr, "Examples:\n") fmt.Fprintf(os.Stderr, "Examples:\n")
fmt.Fprintf(os.Stderr, " %s -d /path/to/dir\n", os.Args[0]) fmt.Fprintf(os.Stderr, " %s -d /path/to/dir\n", os.Args[0])
fmt.Fprintf(os.Stderr, " %s -d http://minio.example.com:9000/bucket -s3\n", os.Args[0]) fmt.Fprintf(os.Stderr, " %s -s3 http://minio.example.com:9000/bucket\n", os.Args[0])
fmt.Fprintf(os.Stderr, " %s -v -f \"*.log\" -d https://s3.amazonaws.com/logs -s3\n\n", os.Args[0]) fmt.Fprintf(os.Stderr, " %s -v -f \"*.log\" -s3 https://s3.amazonaws.com/logs\n\n", os.Args[0])
flag.PrintDefaults() flag.PrintDefaults()
} }
flag.Parse() flag.Parse()
// Check if directory flag is provided // Check mutual exclusion and that exactly one option is provided
if directory == "" { if directory == "" && s3URL == "" {
fmt.Fprintf(os.Stderr, "Error: Directory must be specified with -d flag.\n\n") fmt.Fprintf(os.Stderr, "Error: Either -d <directory> or -s3 <url> must be specified.\n\n")
flag.Usage()
os.Exit(1)
}
if directory != "" && s3URL != "" {
fmt.Fprintf(os.Stderr, "Error: -d and -s3 flags are mutually exclusive. Use only one.\n\n")
flag.Usage() flag.Usage()
os.Exit(1) os.Exit(1)
} }
@@ -263,9 +268,9 @@ func main() {
} }
} }
if s3Mode { if s3URL != "" {
// Parse S3 URL // Parse S3 URL
s3Config, err := parseS3URL(directory) s3Config, err := parseS3URL(s3URL)
if err != nil { if err != nil {
log.Fatal("Failed to parse S3 URL:", err) log.Fatal("Failed to parse S3 URL:", err)
} }

View File

@@ -117,14 +117,14 @@ func TestS3FlagHandling(t *testing.T) {
}{ }{
{ {
name: "s3 flag with URL", name: "s3 flag with URL",
args: []string{"s3-genindex", "-s3", "-d", "http://minio.example.com:9000/bucket"}, args: []string{"s3-genindex", "-s3", "http://minio.example.com:9000/bucket"},
}, },
{ {
name: "s3 flag with verbose", name: "s3 flag with verbose",
args: []string{"s3-genindex", "-v", "-s3", "-d", "https://s3.amazonaws.com/logs"}, args: []string{"s3-genindex", "-v", "-s3", "https://s3.amazonaws.com/logs"},
}, },
{ {
name: "local directory without s3 flag", name: "local directory flag",
args: []string{"s3-genindex", "-d", "/tmp"}, args: []string{"s3-genindex", "-d", "/tmp"},
}, },
} }
@@ -148,25 +148,30 @@ func TestS3FlagHandling(t *testing.T) {
} }
} }
func TestMandatoryDirectoryArgument(t *testing.T) { func TestMutualExclusionAndRequiredFlags(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
args []string args []string
shouldExitWithError bool shouldExitWithError bool
}{ }{
{ {
name: "no directory flag", name: "no flags provided",
args: []string{"s3-genindex"}, args: []string{"s3-genindex"},
shouldExitWithError: true, shouldExitWithError: true,
}, },
{ {
name: "with directory flag", name: "directory flag only",
args: []string{"s3-genindex", "-d", "/tmp"}, args: []string{"s3-genindex", "-d", "/tmp"},
shouldExitWithError: false, shouldExitWithError: false,
}, },
{ {
name: "with s3 flag but no directory", name: "s3 flag only",
args: []string{"s3-genindex", "-s3"}, args: []string{"s3-genindex", "-s3", "http://example.com/bucket"},
shouldExitWithError: false,
},
{
name: "both flags provided (mutual exclusion)",
args: []string{"s3-genindex", "-d", "/tmp", "-s3", "http://example.com/bucket"},
shouldExitWithError: true, shouldExitWithError: true,
}, },
} }