Add a -i flag to force showing 'index.html' in the output listing; by default do not show them.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user