1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
package main
import (
"crypto/sha1"
_ "embed"
"encoding/hex"
"errors"
"flag"
"io"
"io/fs"
"log"
"os"
"path/filepath"
"text/template"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
const configFile = ".ht_git2html"
//go:embed config.tmpl
var tmpl string
func main() {
var project string
var repo string
var link string
var branches string
var quiet bool
var force bool
flag.StringVar(&project, "p", "My project", "Choose a project name")
flag.StringVar(&repo, "r", "/path/to/repo", "Repository to clone from")
flag.StringVar(&link, "l", "http://host.org/project.git", "Public link to repo")
flag.StringVar(&branches, "b", "all", "List of branches")
flag.BoolVar(&quiet, "q", false, "Be quiet")
flag.BoolVar(&force, "f", false, "Force rebuilding of all pages")
flag.Parse()
log.Printf("%v %v %v %v %v %v", project, repo, link, branches, quiet, force)
args := os.Args
// if len(args) != 2 {
// log.Fatalf("jimmy: please specify a single target path")
// }
targetDir := args[len(args)-1]
if ok := filepath.IsAbs(targetDir); !ok {
cwd, err := os.Getwd()
if err != nil {
log.Fatalf("jimmy: %v", err)
}
targetDir = filepath.Join(cwd, targetDir)
}
// TODO: Look up more mode for 755 or 644.
if err := os.MkdirAll(targetDir, os.ModePerm); err != nil {
log.Fatalf("jimmy: unable to create target directory: %v", err)
}
configTmpl := template.Must(template.New("default").Parse(tmpl))
// TODO: Check file permissions are set to 0666.
// TODO: Read file if it exists.
outFile, err := os.Create(filepath.Join(targetDir, configFile))
if err != nil {
log.Fatalf("jimmy: unable to create config file: %v", err)
}
h := sha1.New()
if _, err := io.Copy(h, outFile); err != nil {
log.Fatal(err)
}
configTmpl.Execute(outFile, struct {
Project string
Repository string
PublicRepository string
Target string
Branches string
// SHA1SUM
Template string
}{
Project: project,
Repository: repo,
PublicRepository: link,
Target: targetDir,
Branches: branches,
Template: hex.EncodeToString(h.Sum(nil)),
})
// Repository
dirs := []string{"branches", "commits", "objects"}
for _, dir := range dirs {
d := filepath.Join(targetDir, dir)
// Clear existing dirs if force true.
if force && dir != "branches" {
if err := os.RemoveAll(d); err != nil {
log.Printf("jimmy: unable to remove directory: %v", err)
}
}
if err := os.MkdirAll(d, os.ModePerm); err != nil {
log.Printf("jimmy: unable to create directory: %v", err)
}
}
var pathError *fs.PathError
repoPath := filepath.Join(targetDir, "repository")
_, err = os.Stat(repoPath)
if errors.As(err, &pathError) {
localRepo, err := git.PlainClone(repoPath, false, &git.CloneOptions{
URL: repo,
Progress: os.Stdout,
})
commitObjects, err := localRepo.CommitObjects()
if err != nil {
log.Printf("%v", err)
}
commitObjects.ForEach(func(c *object.Commit) error {
log.Print(c)
return nil
})
localBranches, err := localRepo.Branches()
if err != nil {
log.Printf("%v", err)
}
branch, err := localBranches.Next()
if err != nil {
log.Printf("jimmy: failed to list branches: %v", err)
}
ref := plumbing.NewHashReference(branch.Name(), branch.Hash())
if err != nil {
log.Printf("jimmy: failed to create ref: %v", err)
}
workTree, err := localRepo.Worktree()
if err != nil {
log.Printf("jimmy: failed to open worktree: %v", err)
}
err = workTree.Checkout(&git.CheckoutOptions{
Hash: ref.Hash(),
})
if err != nil {
log.Printf("jimmy: failed to checkout detached HEAD: %v", err)
}
err = localRepo.Storer.RemoveReference(ref.Name())
if err != nil {
log.Printf("jimmy: failed to delete branch: %v", err)
}
}
}
|