package main import ( "errors" "fmt" "os" "path/filepath" "strings" "mokhan.ca/xlgmokha/gitmal/internal/generator" "mokhan.ca/xlgmokha/gitmal/internal/git" flag "github.com/spf13/pflag" ) var flagOutput string func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, "error:", err) os.Exit(1) } } func run() error { flag.StringVar(&flagOutput, "output", "output", "Output directory") flag.Usage = usage flag.Parse() input := "." args := flag.Args() if len(args) == 1 { input = args[0] } if len(args) > 1 { return errors.New("multiple repos not supported yet") } outputDir, err := filepath.Abs(flagOutput) if err != nil { return err } absInput, err := filepath.Abs(input) if err != nil { return err } input = absInput name := filepath.Base(input) name = strings.TrimSuffix(name, ".git") branches, err := git.Branches(input) if err != nil { return err } tags, err := git.Tags(input) if err != nil { return err } var defaultBranch string if generator.ContainsBranch(branches, "master") { defaultBranch = "master" } else if generator.ContainsBranch(branches, "main") { defaultBranch = "main" } else { return errors.New("no default branch found (expected 'main' or 'master')") } if yes, a, b := generator.HasConflictingBranchNames(branches); yes { return fmt.Errorf("conflicting branches %q and %q, both want to use %q dir name", a, b, a.DirName()) } params := generator.Params{ Name: name, RepoDir: input, OutputDir: outputDir, DefaultRef: git.NewRef(defaultBranch), } commits := make(map[string]git.Commit) commitsFor := make(map[git.Ref][]git.Commit, len(branches)) for _, branch := range branches { commitsFor[branch], err = git.Commits(branch, params.RepoDir) if err != nil { return err } for _, commit := range commitsFor[branch] { if alreadyExisting, ok := commits[commit.Hash]; ok && alreadyExisting.Branch == params.DefaultRef { continue } commit.Branch = branch commits[commit.Hash] = commit } } for _, tag := range tags { commitsForTag, err := git.Commits(git.NewRef(tag.Name), params.RepoDir) if err != nil { return err } for _, commit := range commitsForTag { if alreadyExisting, ok := commits[commit.Hash]; ok && !alreadyExisting.Branch.IsEmpty() { continue } commits[commit.Hash] = commit } } generator.Echo(fmt.Sprintf("> %s: %d branches, %d tags, %d commits", params.Name, len(branches), len(tags), len(commits))) if err := generator.GenerateCSS(params); err != nil { return err } if err := generator.GenerateBranches(branches, defaultBranch, params); err != nil { return err } if err := generator.GenerateBranchesJSON(branches, commitsFor, params); err != nil { return err } var defaultBranchFiles []git.Blob for i, branch := range branches { generator.Echo(fmt.Sprintf("> [%d/%d] %s@%s", i+1, len(branches), params.Name, branch)) params.Ref = branch files, err := git.Files(params.Ref, params.RepoDir) if err != nil { return err } if branch.String() == defaultBranch { defaultBranchFiles = files } if err := generator.GenerateBlobs(files, params); err != nil { return err } if err := generator.GenerateLists(files, params); err != nil { return err } if err := generator.GenerateLogForBranch(commitsFor[branch], params); err != nil { return err } if err := generator.GenerateCommitsJSON(commitsFor[branch], params); err != nil { return err } if err := generator.GenerateCommitsAtom(commitsFor[branch], params); err != nil { return err } } params.Ref = git.NewRef(defaultBranch) generator.Echo("> generating commits...") if err := generator.GenerateCommits(commits, params); err != nil { return err } if err := generator.GenerateTags(tags, params); err != nil { return err } if err := generator.GenerateTagsAtom(tags, params); err != nil { return err } if err := generator.GenerateReleasesAtom(tags, params); err != nil { return err } generator.Echo("> generating compare pages...") if err := generator.GenerateComparePages(tags, branches, params); err != nil { return err } if len(defaultBranchFiles) == 0 { return errors.New("no files found for default branch") } if err := generator.GenerateIndex(defaultBranchFiles, params); err != nil { return err } return nil } func usage() { fmt.Fprintf(os.Stderr, "Usage: gitmal [options] [path ...]\n") flag.PrintDefaults() }