Goit

Simple and lightweight Git web server
git clone http://git.omkov.net/Goit
Log | Tree | Refs | README | Download

Goit/src/repo/commit.go (159 lines, 4.2 KiB) -rw-r--r-- file download

c2c5250 Jakob Wakeling 2023-12-12 09:13:37
0
// Copyright (C) 2023, Jakob Wakeling
c2c5250 Jakob Wakeling 2023-12-12 09:13:37
1
// All rights reserved.
c2c5250 Jakob Wakeling 2023-12-12 09:13:37
2
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
3
package repo
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
4
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
5
import (
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
6
	"errors"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
7
	"fmt"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
8
	"html/template"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
9
	"log"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
10
	"net/http"
08dff9a Jakob Wakeling 2023-11-07 21:03:04
11
	"path/filepath"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
12
	"strconv"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
13
	"strings"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
14
	"time"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
15
945fd71 Jakob Wakeling 2023-11-05 15:39:31
16
	"github.com/Jamozed/Goit/src/goit"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
17
	"github.com/buildkite/terminal-to-html/v3"
3f4c3f4 Jakob Wakeling 2023-12-01 23:26:03
18
	"github.com/go-chi/chi/v5"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
19
	"github.com/go-git/go-git/v5"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
20
	"github.com/go-git/go-git/v5/plumbing"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
21
)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
22
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
23
func HandleCommit(w http.ResponseWriter, r *http.Request) {
473d02c Jakob Wakeling 2023-11-28 00:01:06
24
	auth, user, err := goit.Auth(w, r, true)
473d02c Jakob Wakeling 2023-11-28 00:01:06
25
	if err != nil {
473d02c Jakob Wakeling 2023-11-28 00:01:06
26
		log.Println("[/repo/commit]", err.Error())
473d02c Jakob Wakeling 2023-11-28 00:01:06
27
		goit.HttpError(w, http.StatusInternalServerError)
473d02c Jakob Wakeling 2023-11-28 00:01:06
28
	}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
29
3f4c3f4 Jakob Wakeling 2023-12-01 23:26:03
30
	repo, err := goit.GetRepoByName(chi.URLParam(r, "repo"))
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
31
	if err != nil {
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
32
		goit.HttpError(w, http.StatusInternalServerError)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
33
		return
778d467 Jakob Wakeling 2024-01-17 18:29:55
34
	} else if repo == nil || !goit.IsVisible(repo, auth, user) {
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
35
		goit.HttpError(w, http.StatusNotFound)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
36
		return
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
37
	}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
38
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
39
	type stat struct {
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
40
		Name, Path, Status, Num, Plusses, Minuses string
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
41
		IsBinary                                  bool
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
42
	}
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
43
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
44
	data := struct {
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
45
		HeaderFields
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
46
		Title                       string
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
47
		Author, Date, Commit        string
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
48
		Parents                     []string
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
49
		MessageSubject, MessageBody string
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
50
		Stats                       []stat
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
51
		Summary                     string
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
52
		Diff                        template.HTML
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
53
	}{
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
54
		Title:        repo.Name + " - Log",
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
55
		HeaderFields: GetHeaderFields(auth, user, repo, r.Host),
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
56
	}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
57
08dff9a Jakob Wakeling 2023-11-07 21:03:04
58
	gr, err := git.PlainOpen(goit.RepoPath(repo.Name, true))
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
59
	if err != nil {
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
60
		log.Println("[/repo/commit]", err.Error())
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
61
		goit.HttpError(w, http.StatusInternalServerError)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
62
		return
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
63
	}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
64
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
65
	ref, err := gr.Head()
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
66
	if err != nil {
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
67
		if !errors.Is(err, plumbing.ErrReferenceNotFound) {
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
68
			log.Println("[/repo/log]", err.Error())
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
69
			goit.HttpError(w, http.StatusInternalServerError)
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
70
			return
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
71
		}
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
72
	} else {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
73
		if readme, _ := findPattern(gr, ref, readmePattern); readme != "" {
08dff9a Jakob Wakeling 2023-11-07 21:03:04
74
			data.Readme = filepath.Join("/", repo.Name, "file", readme)
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
75
		}
b4b291e Jakob Wakeling 2023-12-23 17:05:01
76
		if licence, _ := findPattern(gr, ref, licencePattern); licence != "" {
08dff9a Jakob Wakeling 2023-11-07 21:03:04
77
			data.Licence = filepath.Join("/", repo.Name, "file", licence)
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
78
		}
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
79
	}
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
80
3f4c3f4 Jakob Wakeling 2023-12-01 23:26:03
81
	commit, err := gr.CommitObject(plumbing.NewHash(chi.URLParam(r, "hash")))
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
82
	if errors.Is(err, plumbing.ErrObjectNotFound) {
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
83
		goit.HttpError(w, http.StatusNotFound)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
84
		return
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
85
	} else if err != nil {
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
86
		log.Println("[/repo/commit]", err.Error())
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
87
		goit.HttpError(w, http.StatusInternalServerError)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
88
		return
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
89
	}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
90
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
91
	data.Author = commit.Author.String()
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
92
	data.Date = commit.Author.When.UTC().Format(time.DateTime)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
93
	data.Commit = commit.Hash.String()
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
94
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
95
	for _, h := range commit.ParentHashes {
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
96
		data.Parents = append(data.Parents, h.String())
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
97
	}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
98
d0367aa Jakob Wakeling 2023-12-24 22:42:16
99
	data.MessageSubject, data.MessageBody, _ = strings.Cut(commit.Message, "\n")
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
100
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
101
	st, err := goit.DiffStats(commit)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
102
	if err != nil {
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
103
		log.Println("[/repo/commit]", err.Error())
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
104
		goit.HttpError(w, http.StatusInternalServerError)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
105
		return
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
106
	}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
107
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
108
	var files, additions, deletions int = len(st), 0, 0
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
109
	for _, s := range st {
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
110
		f := stat{Name: s.Name, Path: s.Name, Status: s.Status}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
111
		f.Num = strconv.FormatInt(int64(s.Addition+s.Deletion), 10)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
112
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
113
		if s.Addition+s.Deletion > 80 {
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
114
			f.Plusses = strings.Repeat("+", (s.Addition*80)/(s.Addition+s.Deletion))
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
115
			f.Minuses = strings.Repeat("-", (s.Deletion*80)/(s.Addition+s.Deletion))
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
116
		} else {
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
117
			f.Plusses = strings.Repeat("+", s.Addition)
b4ad3bf Jakob Wakeling 2023-08-07 17:42:13
118
			f.Minuses = strings.Repeat("-", s.Deletion)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
119
		}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
120
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
121
		if s.Status == "R" {
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
122
			f.Name = s.Prev + " -> " + s.Name
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
123
		}
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
124
		if s.IsBinary {
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
125
			f.IsBinary = true
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
126
		}
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
127
4a22b95 Jakob Wakeling 2023-08-14 20:57:25
128
		data.Stats = append(data.Stats, f)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
129
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
130
		additions += s.Addition
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
131
		deletions += s.Deletion
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
132
	}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
133
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
134
	data.Summary = fmt.Sprintf("%d files changed, %d insertions, %d deletions", files, additions, deletions)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
135
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
136
	var phash string
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
137
	if commit.NumParents() > 0 {
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
138
		phash = commit.ParentHashes[0].String()
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
139
	} else {
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
140
		phash = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
141
	}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
142
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
143
	c := goit.NewGitCommand("diff", "--color=always", "-p", phash, commit.Hash.String())
08dff9a Jakob Wakeling 2023-11-07 21:03:04
144
	c.Dir = goit.RepoPath(repo.Name, true)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
145
	out, _, err := c.Run(nil, nil)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
146
	if err != nil {
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
147
		log.Println("[/repo/commit]", err.Error())
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
148
		goit.HttpError(w, http.StatusInternalServerError)
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
149
		return
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
150
	}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
151
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
152
	data.Diff = template.HTML(terminal.Render(out))
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
153
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
154
	if err := goit.Tmpl.ExecuteTemplate(w, "repo/commit", data); err != nil {
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
155
		log.Println("[/repo/commit]", err.Error())
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
156
	}
3e159d3 Jakob Wakeling 2023-08-06 23:29:48
157
}
158