Goit

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

Goit/src/repo/log.go (156 lines, 3.8 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
64718e1 Jakob Wakeling 2023-07-24 21:56:07
3
package repo
64718e1 Jakob Wakeling 2023-07-24 21:56:07
4
64718e1 Jakob Wakeling 2023-07-24 21:56:07
5
import (
20732d3 Jakob Wakeling 2023-07-26 22:38:15
6
	"errors"
64718e1 Jakob Wakeling 2023-07-24 21:56:07
7
	"fmt"
b4b291e Jakob Wakeling 2023-12-23 17:05:01
8
	"io"
64718e1 Jakob Wakeling 2023-07-24 21:56:07
9
	"log"
64718e1 Jakob Wakeling 2023-07-24 21:56:07
10
	"net/http"
08dff9a Jakob Wakeling 2023-11-07 21:03:04
11
	"path/filepath"
b4b291e Jakob Wakeling 2023-12-23 17:05:01
12
	"strconv"
64718e1 Jakob Wakeling 2023-07-24 21:56:07
13
	"strings"
64718e1 Jakob Wakeling 2023-07-24 21:56:07
14
	"time"
64718e1 Jakob Wakeling 2023-07-24 21:56:07
15
945fd71 Jakob Wakeling 2023-11-05 15:39:31
16
	"github.com/Jamozed/Goit/src/goit"
64718e1 Jakob Wakeling 2023-07-24 21:56:07
17
	"github.com/Jamozed/Goit/src/util"
3f4c3f4 Jakob Wakeling 2023-12-01 23:26:03
18
	"github.com/go-chi/chi/v5"
64718e1 Jakob Wakeling 2023-07-24 21:56:07
19
	"github.com/go-git/go-git/v5"
20732d3 Jakob Wakeling 2023-07-26 22:38:15
20
	"github.com/go-git/go-git/v5/plumbing"
64718e1 Jakob Wakeling 2023-07-24 21:56:07
21
)
b4b291e Jakob Wakeling 2023-12-23 17:05:01
22
b4b291e Jakob Wakeling 2023-12-23 17:05:01
23
const PAGE = 100
64718e1 Jakob Wakeling 2023-07-24 21:56:07
24
64718e1 Jakob Wakeling 2023-07-24 21:56:07
25
func HandleLog(w http.ResponseWriter, r *http.Request) {
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
26
	auth, user, err := goit.Auth(w, r, true)
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
27
	if err != nil {
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
28
		log.Println("[repo/log]", err.Error())
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
29
		goit.HttpError(w, http.StatusInternalServerError)
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
30
		return
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
31
	}
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
32
3f4c3f4 Jakob Wakeling 2023-12-01 23:26:03
33
	tpath := chi.URLParam(r, "*")
64718e1 Jakob Wakeling 2023-07-24 21:56:07
34
3f4c3f4 Jakob Wakeling 2023-12-01 23:26:03
35
	repo, err := goit.GetRepoByName(chi.URLParam(r, "repo"))
64718e1 Jakob Wakeling 2023-07-24 21:56:07
36
	if err != nil {
64718e1 Jakob Wakeling 2023-07-24 21:56:07
37
		goit.HttpError(w, http.StatusInternalServerError)
64718e1 Jakob Wakeling 2023-07-24 21:56:07
38
		return
778d467 Jakob Wakeling 2024-01-17 18:29:55
39
	} else if repo == nil || !goit.IsVisible(repo, auth, user) {
64718e1 Jakob Wakeling 2023-07-24 21:56:07
40
		goit.HttpError(w, http.StatusNotFound)
64718e1 Jakob Wakeling 2023-07-24 21:56:07
41
		return
64718e1 Jakob Wakeling 2023-07-24 21:56:07
42
	}
64718e1 Jakob Wakeling 2023-07-24 21:56:07
43
b4b291e Jakob Wakeling 2023-12-23 17:05:01
44
	offset := int64(0)
b4b291e Jakob Wakeling 2023-12-23 17:05:01
45
	if o := r.URL.Query().Get("o"); o != "" {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
46
		if i, err := strconv.ParseInt(o, 10, 64); err != nil {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
47
			goit.HttpError(w, http.StatusBadRequest)
b4b291e Jakob Wakeling 2023-12-23 17:05:01
48
			return
b4b291e Jakob Wakeling 2023-12-23 17:05:01
49
		} else {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
50
			offset = i
b4b291e Jakob Wakeling 2023-12-23 17:05:01
51
		}
b4b291e Jakob Wakeling 2023-12-23 17:05:01
52
	}
64718e1 Jakob Wakeling 2023-07-24 21:56:07
53
64718e1 Jakob Wakeling 2023-07-24 21:56:07
54
	type row struct{ Hash, Date, Message, Author, Files, Additions, Deletions string }
64718e1 Jakob Wakeling 2023-07-24 21:56:07
55
	data := struct {
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
56
		HeaderFields
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
57
		Title                        string
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
58
		Commits                      []row
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
59
		Page, PrevOffset, NextOffset int64
64718e1 Jakob Wakeling 2023-07-24 21:56:07
60
	}{
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
61
		Title:        repo.Name + " - Log",
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
62
		HeaderFields: GetHeaderFields(auth, user, repo, r.Host),
2e13a8c Jakob Wakeling 2023-12-23 19:40:09
63
b4b291e Jakob Wakeling 2023-12-23 17:05:01
64
		Page:       offset/PAGE + 1,
b4b291e Jakob Wakeling 2023-12-23 17:05:01
65
		PrevOffset: util.Max(offset-PAGE, -1),
b4b291e Jakob Wakeling 2023-12-23 17:05:01
66
		NextOffset: offset + PAGE,
64718e1 Jakob Wakeling 2023-07-24 21:56:07
67
	}
64718e1 Jakob Wakeling 2023-07-24 21:56:07
68
08dff9a Jakob Wakeling 2023-11-07 21:03:04
69
	gr, err := git.PlainOpen(goit.RepoPath(repo.Name, true))
64718e1 Jakob Wakeling 2023-07-24 21:56:07
70
	if err != nil {
64718e1 Jakob Wakeling 2023-07-24 21:56:07
71
		log.Println("[/repo/log]", err.Error())
64718e1 Jakob Wakeling 2023-07-24 21:56:07
72
		goit.HttpError(w, http.StatusInternalServerError)
64718e1 Jakob Wakeling 2023-07-24 21:56:07
73
		return
64718e1 Jakob Wakeling 2023-07-24 21:56:07
74
	}
64718e1 Jakob Wakeling 2023-07-24 21:56:07
75
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
76
	ref, err := gr.Head()
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
77
	if errors.Is(err, plumbing.ErrReferenceNotFound) {
43a7c2c Jakob Wakeling 2023-12-25 21:16:12
78
		data.NextOffset = 0
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
79
		goto execute
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
80
	} else if err != nil {
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
81
		log.Println("[/repo/log]", err.Error())
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
82
		goit.HttpError(w, http.StatusInternalServerError)
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
83
		return
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
84
	}
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
85
b4b291e Jakob Wakeling 2023-12-23 17:05:01
86
	if readme, _ := findPattern(gr, ref, readmePattern); readme != "" {
08dff9a Jakob Wakeling 2023-11-07 21:03:04
87
		data.Readme = filepath.Join("/", repo.Name, "file", readme)
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
88
	}
b4b291e Jakob Wakeling 2023-12-23 17:05:01
89
	if licence, _ := findPattern(gr, ref, licencePattern); licence != "" {
08dff9a Jakob Wakeling 2023-11-07 21:03:04
90
		data.Licence = filepath.Join("/", repo.Name, "file", licence)
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
91
	}
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
92
b4b291e Jakob Wakeling 2023-12-23 17:05:01
93
	if iter, err := gr.Log(&git.LogOptions{
b4b291e Jakob Wakeling 2023-12-23 17:05:01
94
		From: ref.Hash(), Order: git.LogOrderCommitterTime, PathFilter: func(s string) bool {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
95
			return tpath == "" || s == tpath || strings.HasPrefix(s, tpath+"/")
b4b291e Jakob Wakeling 2023-12-23 17:05:01
96
		},
b4b291e Jakob Wakeling 2023-12-23 17:05:01
97
	}); err != nil {
64718e1 Jakob Wakeling 2023-07-24 21:56:07
98
		log.Println("[/repo/log]", err.Error())
64718e1 Jakob Wakeling 2023-07-24 21:56:07
99
		goit.HttpError(w, http.StatusInternalServerError)
64718e1 Jakob Wakeling 2023-07-24 21:56:07
100
		return
b4b291e Jakob Wakeling 2023-12-23 17:05:01
101
	} else {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
102
		for i := int64(0); i < offset; i += 1 {
43a7c2c Jakob Wakeling 2023-12-25 21:16:12
103
			if _, err := iter.Next(); err != nil {
43a7c2c Jakob Wakeling 2023-12-25 21:16:12
104
				if errors.Is(err, io.EOF) {
43a7c2c Jakob Wakeling 2023-12-25 21:16:12
105
					data.NextOffset = 0
43a7c2c Jakob Wakeling 2023-12-25 21:16:12
106
					goto execute
43a7c2c Jakob Wakeling 2023-12-25 21:16:12
107
				}
43a7c2c Jakob Wakeling 2023-12-25 21:16:12
108
b4b291e Jakob Wakeling 2023-12-23 17:05:01
109
				log.Println("[/repo/log]", err.Error())
b4b291e Jakob Wakeling 2023-12-23 17:05:01
110
				goit.HttpError(w, http.StatusInternalServerError)
b4b291e Jakob Wakeling 2023-12-23 17:05:01
111
				return
b4b291e Jakob Wakeling 2023-12-23 17:05:01
112
			}
b4b291e Jakob Wakeling 2023-12-23 17:05:01
113
		}
b4b291e Jakob Wakeling 2023-12-23 17:05:01
114
b4b291e Jakob Wakeling 2023-12-23 17:05:01
115
		for i := 0; i < PAGE; i += 1 {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
116
			c, err := iter.Next()
b4b291e Jakob Wakeling 2023-12-23 17:05:01
117
			if errors.Is(err, io.EOF) {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
118
				data.NextOffset = 0
43a7c2c Jakob Wakeling 2023-12-25 21:16:12
119
				goto execute
b4b291e Jakob Wakeling 2023-12-23 17:05:01
120
			} else if err != nil {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
121
				log.Println("[/repo/log]", err.Error())
b4b291e Jakob Wakeling 2023-12-23 17:05:01
122
				goit.HttpError(w, http.StatusInternalServerError)
b4b291e Jakob Wakeling 2023-12-23 17:05:01
123
				return
b4b291e Jakob Wakeling 2023-12-23 17:05:01
124
			}
64718e1 Jakob Wakeling 2023-07-24 21:56:07
125
b4b291e Jakob Wakeling 2023-12-23 17:05:01
126
			var files, additions, deletions int
b4b291e Jakob Wakeling 2023-12-23 17:05:01
127
b4b291e Jakob Wakeling 2023-12-23 17:05:01
128
			if stats, err := goit.DiffStats(c); err != nil {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
129
				log.Println("[/repo/log]", err.Error())
b4b291e Jakob Wakeling 2023-12-23 17:05:01
130
			} else {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
131
				files = len(stats)
b4b291e Jakob Wakeling 2023-12-23 17:05:01
132
				for _, s := range stats {
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
133
					additions += s.Addition
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
134
					deletions += s.Deletion
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
135
				}
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
136
			}
35fbf5f Jakob Wakeling 2023-11-16 22:50:47
137
b4b291e Jakob Wakeling 2023-12-23 17:05:01
138
			data.Commits = append(data.Commits, row{
b4b291e Jakob Wakeling 2023-12-23 17:05:01
139
				Hash: c.Hash.String(), Date: c.Author.When.UTC().Format(time.DateTime),
b4b291e Jakob Wakeling 2023-12-23 17:05:01
140
				Message: strings.SplitN(c.Message, "\n", 2)[0], Author: c.Author.Name, Files: fmt.Sprint(files),
b4b291e Jakob Wakeling 2023-12-23 17:05:01
141
				Additions: "+" + fmt.Sprint(additions), Deletions: "-" + fmt.Sprint(deletions),
b4b291e Jakob Wakeling 2023-12-23 17:05:01
142
			})
64718e1 Jakob Wakeling 2023-07-24 21:56:07
143
		}
64718e1 Jakob Wakeling 2023-07-24 21:56:07
144
b4b291e Jakob Wakeling 2023-12-23 17:05:01
145
		if _, err := iter.Next(); errors.Is(err, io.EOF) {
b4b291e Jakob Wakeling 2023-12-23 17:05:01
146
			data.NextOffset = 0
b4b291e Jakob Wakeling 2023-12-23 17:05:01
147
		}
64718e1 Jakob Wakeling 2023-07-24 21:56:07
148
	}
64718e1 Jakob Wakeling 2023-07-24 21:56:07
149
7ba1b21 Jakob Wakeling 2023-08-02 21:44:07
150
execute:
64718e1 Jakob Wakeling 2023-07-24 21:56:07
151
	if err := goit.Tmpl.ExecuteTemplate(w, "repo/log", data); err != nil {
64718e1 Jakob Wakeling 2023-07-24 21:56:07
152
		log.Println("[/repo/log]", err.Error())
64718e1 Jakob Wakeling 2023-07-24 21:56:07
153
	}
64718e1 Jakob Wakeling 2023-07-24 21:56:07
154
}
155