diff --git a/cmd/s3-genindex/main.go b/cmd/s3-genindex/main.go index 10ac9e1..436393d 100644 --- a/cmd/s3-genindex/main.go +++ b/cmd/s3-genindex/main.go @@ -125,6 +125,11 @@ func processS3Bucket(s3Config *S3Config, opts *indexgen.Options) error { continue } + // Skip index.html files unless ShowIndexFiles is enabled + if !opts.ShowIndexFiles && strings.HasSuffix(keyName, opts.OutputFile) { + continue + } + // Simple glob matching for filter if opts.Filter != "*" && opts.Filter != "" { matched, err := filepath.Match(opts.Filter, keyName) @@ -152,14 +157,14 @@ func processS3Bucket(s3Config *S3Config, opts *indexgen.Options) error { func processS3Hierarchy(objects []S3Object, opts *indexgen.Options, client *s3.Client, s3Config *S3Config) error { // Group objects by directory path dirMap := make(map[string][]indexgen.FileEntry) - + // Track all directory paths we need to create indexes for allDirs := make(map[string]bool) - + for _, obj := range objects { // Split the key into directory parts parts := strings.Split(obj.Key, "/") - + if len(parts) == 1 { // Root level file entry := createFileEntry(obj, obj.Key) @@ -168,11 +173,11 @@ func processS3Hierarchy(objects []S3Object, opts *indexgen.Options, client *s3.C // File in a subdirectory fileName := parts[len(parts)-1] dirPath := strings.Join(parts[:len(parts)-1], "/") - + // Create file entry entry := createFileEntry(obj, fileName) dirMap[dirPath] = append(dirMap[dirPath], entry) - + // Track all parent directories currentPath := "" for i, part := range parts[:len(parts)-1] { @@ -185,7 +190,7 @@ func processS3Hierarchy(objects []S3Object, opts *indexgen.Options, client *s3.C } } } - + // Add directory entries to parent directories for dirPath := range allDirs { parentPath := "" @@ -193,14 +198,14 @@ func processS3Hierarchy(objects []S3Object, opts *indexgen.Options, client *s3.C parts := strings.Split(dirPath, "/") parentPath = strings.Join(parts[:len(parts)-1], "/") } - + dirName := filepath.Base(dirPath) // Build the correct path for S3 dirEntryPath := dirPath + "/" if opts.DirAppend { dirEntryPath += opts.OutputFile } - + dirEntry := indexgen.FileEntry{ Name: dirName, Path: dirEntryPath, @@ -213,13 +218,13 @@ func processS3Hierarchy(objects []S3Object, opts *indexgen.Options, client *s3.C ModTimeISO: time.Now().Format(time.RFC3339), ModTimeHuman: time.Now().Format(time.RFC822), } - + dirMap[parentPath] = append(dirMap[parentPath], dirEntry) } - + // Set TopDir to bucket name for template generation opts.TopDir = s3Config.Bucket - + // Generate index.html for each directory for dirPath, entries := range dirMap { indexKey := dirPath @@ -227,13 +232,13 @@ func processS3Hierarchy(objects []S3Object, opts *indexgen.Options, client *s3.C indexKey += "/" } indexKey += opts.OutputFile - + err := generateS3HTML(entries, opts, client, s3Config, indexKey) if err != nil { return fmt.Errorf("failed to generate index for %s: %w", dirPath, err) } } - + return nil } @@ -271,7 +276,7 @@ func generateS3HTML(entries []indexgen.FileEntry, opts *indexgen.Options, client // Determine if we're at root level (no parent directory) isRoot := (indexKey == opts.OutputFile) // root level index.html - + // Prepare template data (similar to ProcessDir in indexgen) data := struct { DirName string @@ -293,7 +298,7 @@ func generateS3HTML(entries []indexgen.FileEntry, opts *indexgen.Options, client if err != nil { return fmt.Errorf("failed to execute template: %w", err) } - + htmlContent := htmlBuffer.String() if opts.DryRun { @@ -339,6 +344,7 @@ func main() { var directory string var s3URL string var dryRun bool + var showIndexFiles bool // Set defaults opts.DirAppend = true @@ -352,6 +358,7 @@ func main() { flag.BoolVar(&dryRun, "n", false, "dry run: show what would be written without actually writing") flag.StringVar(&excludeRegexStr, "x", "", "exclude files matching regular expression") flag.BoolVar(&opts.Verbose, "v", false, "verbosely list every processed file") + flag.BoolVar(&showIndexFiles, "i", false, "show index.html files in directory listings") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Generate directory index files (recursive is ON, hidden files included by default).\n") @@ -391,8 +398,9 @@ func main() { } } - // Set dry run flag + // Set dry run and show index files flags opts.DryRun = dryRun + opts.ShowIndexFiles = showIndexFiles if s3URL != "" { // Parse S3 URL diff --git a/internal/indexgen/indexgen.go b/internal/indexgen/indexgen.go index c4d4d5f..00cdfa5 100644 --- a/internal/indexgen/indexgen.go +++ b/internal/indexgen/indexgen.go @@ -158,15 +158,16 @@ var ExtensionTypes = map[string]string{ } type Options struct { - TopDir string - Filter string - OutputFile string - DirAppend bool - Recursive bool - IncludeHidden bool - ExcludeRegex *regexp.Regexp - Verbose bool - DryRun bool + TopDir string + Filter string + OutputFile string + DirAppend bool + Recursive bool + IncludeHidden bool + ExcludeRegex *regexp.Regexp + Verbose bool + DryRun bool + ShowIndexFiles bool } type FileEntry struct { @@ -275,7 +276,7 @@ func ReadDirEntries(dirPath string, opts *Options) ([]FileEntry, error) { for _, file := range files { fileName := file.Name() - if strings.EqualFold(fileName, opts.OutputFile) { + if !opts.ShowIndexFiles && strings.EqualFold(fileName, opts.OutputFile) { continue } diff --git a/internal/indexgen/indexgen_test.go b/internal/indexgen/indexgen_test.go index 9877bd9..f7916e1 100644 --- a/internal/indexgen/indexgen_test.go +++ b/internal/indexgen/indexgen_test.go @@ -101,11 +101,13 @@ func TestHTMLTemplate(t *testing.T) { Entries []FileEntry DirAppend bool OutputFile string + IsRoot bool }{ DirName: "test-dir", Entries: []FileEntry{}, DirAppend: false, OutputFile: "index.html", + IsRoot: false, } var buf bytes.Buffer @@ -161,11 +163,13 @@ func TestHTMLTemplateWithEntries(t *testing.T) { Entries []FileEntry DirAppend bool OutputFile string + IsRoot bool }{ DirName: "test-dir", Entries: entries, DirAppend: false, OutputFile: "index.html", + IsRoot: false, } var buf bytes.Buffer diff --git a/internal/indexgen/integration_test.go b/internal/indexgen/integration_test.go index 2798fb7..1cdd81e 100644 --- a/internal/indexgen/integration_test.go +++ b/internal/indexgen/integration_test.go @@ -245,9 +245,9 @@ func TestProcessDirWithDirAppend(t *testing.T) { htmlContent := string(content) - // Check that directory links include index.html (URL escaped) - if !strings.Contains(htmlContent, "subdir%2Findex.html") { - t.Errorf("Directory links should include index.html when DirAppend is true. Expected subdir%%2Findex.html in content") + // Check that directory links include index.html + if !strings.Contains(htmlContent, "subdir/index.html") { + t.Errorf("Directory links should include index.html when DirAppend is true. Expected subdir/index.html in content") } }