First go at adding the README file to the output. - staticgit - A git static site generator, the site you are viewing now!
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit a2c64544c939d0a4e67743423be339c672bc5c50
 (DIR) parent 77288e9e0a99e1f8737172b46894a5dbde5cc722
 (HTM) Author: Jay Scott <me@jay.scot>
       Date:   Thu, 11 Jul 2024 11:53:37 +0100
       
       First go at adding the README file to the output.
       
       Diffstat:
         M .gitignore                          |       5 +++--
         M Makefile                            |       2 +-
         M cmd/sealgit/main.go                 |      64 +++++++++++++++++++++++++++++--
         M internal/repo/repo.go               |      62 +++++++++++++++++++++++++++++++
         A templates/readme.html               |      16 ++++++++++++++++
       
       5 files changed, 142 insertions(+), 7 deletions(-)
       ---
 (DIR) diff --git a/.gitignore b/.gitignore
       @@ -1 +1,2 @@
       -build/
       -\ No newline at end of file
       +build/
       +tmp/
       +\ No newline at end of file
 (DIR) diff --git a/Makefile b/Makefile
       @@ -13,7 +13,7 @@ all: run
        
        run:
                @echo "Running $(APP_NAME)..."
       -        @go run $(MAIN_PATH)
       +        @go run $(MAIN_PATH) -g -p /tmp/git -o tmp
        
        build:
                @echo "Building $(APP_NAME) for local architecture..."
 (DIR) diff --git a/cmd/sealgit/main.go b/cmd/sealgit/main.go
       @@ -15,11 +15,13 @@ import (
        func main() {
                var cfg config.Config
                var ignoreDirs string
       +        var outputRoot string
        
                flag.StringVar(&cfg.ReposPath, "p", "", "Path to the git repositories (required)")
                flag.StringVar(&cfg.TemplatePath, "t", "", "Directory where HTML templates are stored")
                flag.BoolVar(&cfg.GroupFlag, "g", false, "Group repositories based on description tags")
                flag.StringVar(&ignoreDirs, "i", "", "Directories to ignore (space-separated)")
       +        flag.StringVar(&outputRoot, "o", ".", "Root path where output directories will be created")
                flag.Parse()
        
                if cfg.ReposPath == "" {
       @@ -34,6 +36,19 @@ func main() {
                        log.Fatalf("Failed to read repos directory: %v", err)
                }
        
       +        // var repoInfos []repo.RepoInfo
       +        // for _, r := range repos {
       +        //         if r.IsDir() && !cfg.IgnoreDirs[r.Name()] {
       +        //                 repoPath := filepath.Join(cfg.ReposPath, r.Name())
       +        //                 repoInfo, err := repo.GetRepoInfo(repoPath, cfg.GroupFlag)
       +        //                 if err != nil {
       +        //                         log.Printf("Failed to get info for repo %s: %v", r.Name(), err)
       +        //                         continue
       +        //                 }
       +        //                 repoInfos = append(repoInfos, repoInfo)
       +        //         }
       +        // }
       +
                var repoInfos []repo.RepoInfo
                for _, r := range repos {
                        if r.IsDir() && !cfg.IgnoreDirs[r.Name()] {
       @@ -44,13 +59,54 @@ func main() {
                                        continue
                                }
                                repoInfos = append(repoInfos, repoInfo)
       +
       +                        // Retrieve README content
       +                        readme, err := repo.GetReadme(repoPath)
       +                        if err != nil {
       +                                log.Printf("Failed to get README for repo %s: %v", r.Name(), err)
       +                        } else {
       +                                readmeData := struct {
       +                                        RepoName      string
       +                                        ReadmeContent string
       +                                }{
       +                                        RepoName:      r.Name(),
       +                                        ReadmeContent: readme,
       +                                }
       +
       +                                readmeTmpl := template.ParseTemplate(cfg.TemplatePath, "readme.html")
       +                                outputPath := filepath.Join(outputRoot, r.Name(), "README.html")
       +
       +                                // Ensure the parent directory exists
       +                                if err := os.MkdirAll(filepath.Dir(outputPath), 0755); err != nil {
       +                                        log.Fatalf("Failed to create parent directory: %v", err)
       +                                }
       +
       +                                f, err := os.Create(outputPath)
       +                                if err != nil {
       +                                        log.Fatalf("Failed to create README HTML file: %v", err)
       +                                }
       +                                defer f.Close()
       +
       +                                if err := readmeTmpl.Execute(f, readmeData); err != nil {
       +                                        log.Fatalf("Failed to execute README template: %v", err)
       +                                }
       +                                fmt.Printf("README HTML for repo %s saved to %s\n", r.Name(), outputPath)
       +                        }
                        }
                }
        
       -        // only generate an index for now.
                groupedRepos := repo.GroupRepos(repoInfos, cfg.GroupFlag)
       -        tmpl := template.ParseTemplate(cfg.TemplatePath, "index.html")
       -        if err := tmpl.Execute(os.Stdout, groupedRepos); err != nil {
       -                log.Fatalf("Failed to execute template: %v", err)
       +        indexTmpl := template.ParseTemplate(cfg.TemplatePath, "index.html")
       +        indexOutputPath := filepath.Join(outputRoot, "index.html")
       +        indexFile, err := os.Create(indexOutputPath)
       +        if err != nil {
       +                log.Fatalf("Failed to create index HTML file: %v", err)
                }
       +        defer indexFile.Close()
       +
       +        if err := indexTmpl.Execute(indexFile, groupedRepos); err != nil {
       +                log.Fatalf("Failed to execute index template: %v", err)
       +        }
       +        fmt.Printf("Index HTML saved to %s\n", indexOutputPath)
       +
        }
 (DIR) diff --git a/internal/repo/repo.go b/internal/repo/repo.go
       @@ -1,6 +1,8 @@
        package repo
        
        import (
       +        "fmt"
       +        "io"
                "os"
                "path/filepath"
                "regexp"
       @@ -17,6 +19,66 @@ type RepoInfo struct {
                Group       string
        }
        
       +// GetReadme reads the README file from a bare git repository.
       +func GetReadme(repoPath string) (string, error) {
       +        // Open the git repository
       +        repo, err := git.PlainOpen(repoPath)
       +        if err != nil {
       +                return "", fmt.Errorf("failed to open git repository: %v", err)
       +        }
       +
       +        // Get the HEAD reference
       +        headRef, err := repo.Head()
       +        if err != nil {
       +                return "", fmt.Errorf("failed to get HEAD reference: %v", err)
       +        }
       +
       +        // Get the commit object for the HEAD
       +        commit, err := repo.CommitObject(headRef.Hash())
       +        if err != nil {
       +                return "", fmt.Errorf("failed to get commit object: %v", err)
       +        }
       +
       +        // Get the tree for the commit
       +        tree, err := commit.Tree()
       +        if err != nil {
       +                return "", fmt.Errorf("failed to get tree: %v", err)
       +        }
       +
       +        // Common README file names
       +        readmeFiles := []string{"README.md", "README.txt", "README"}
       +
       +        for _, fileName := range readmeFiles {
       +                // Find the file entry in the tree
       +                entry, err := tree.FindEntry(fileName)
       +                if err != nil {
       +                        continue // Try the next possible README file
       +                }
       +
       +                // Get the blob for the file entry
       +                blob, err := repo.BlobObject(entry.Hash)
       +                if err != nil {
       +                        return "", fmt.Errorf("failed to get blob object: %v", err)
       +                }
       +
       +                // Read the blob content
       +                reader, err := blob.Reader()
       +                if err != nil {
       +                        return "", fmt.Errorf("failed to get blob reader: %v", err)
       +                }
       +                defer reader.Close()
       +
       +                content, err := io.ReadAll(reader)
       +                if err != nil {
       +                        return "", fmt.Errorf("failed to read blob content: %v", err)
       +                }
       +
       +                return string(content), nil
       +        }
       +
       +        return "No README found!", nil
       +}
       +
        func GetRepoInfo(repoPath string, groupFlag bool) (RepoInfo, error) {
                repo, err := git.PlainOpen(repoPath)
                if err != nil {
 (DIR) diff --git a/templates/readme.html b/templates/readme.html
       @@ -0,0 +1,15 @@
       +<!DOCTYPE html>
       +<html>
       +<head>
       +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
       +<meta name="viewport" content="width=device-width, initial-scale=1" />
       +<title>{{.RepoName}} - README</title>
       +<link rel="stylesheet" type="text/css" href="style.css" />
       +</head>
       +<body>
       +<h1>{{.RepoName}}</h1>
       +<div id="readme">
       +<pre>{{.ReadmeContent}}</pre>
       +</div>
       +</body>
       +</html>
       +\ No newline at end of file