summaryrefslogtreecommitdiff
path: root/src/edit/dir.go
blob: 8315dc01fa68201beca964efc720e10686b0b21b (plain)
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
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os/user"
	"path"
	"strings"
	"time"
)

func ServeGit(out http.ResponseWriter, in *http.Request) {
	PostHack(in)
	upath := in.URL.Path
	if strings.HasPrefix(upath, "/") {
		upath = "/" + upath
	}
	upath = path.Clean(upath)

	errcheck(GitPull())
	tree, err := GitLsTree()
	errcheck(err)
	file, fileExists := tree[upath]
	if file.Type == "tree" && in.Method != http.MethodPut {
		if !strings.HasSuffix(in.URL.Path, "/") {
			out.Header().Set("Location", path.Base(upath)+"/")
			out.WriteHeader(http.StatusMovedPermanently)
			return
		}
		if !strings.HasSuffix(upath, "/") {
			upath = upath + "/"
		}
	}

	switch in.Method {
	case http.MethodGet, http.MethodHead:
		out.Header().Set("Content-Type", "text/html; charset=utf-8")
		if file.Type == "tree" {
			errcheck(renderViewTree(out, upath, tree))
		} else {
			if fileExists {
				errcheck(renderViewBlob(out, upath, &file))
			} else {
				errcheck(renderViewBlob(out, upath, nil))
			}
		}
		if fileExists {
			out.WriteHeader(http.StatusOK)
		} else {
			out.WriteHeader(http.StatusNotFound)
		}
	case http.MethodPut:
		username := in.Header.Get("X-Nginx-User")
		userinfo, err := user.Lookup(username)
		errcheck(err)
		msg := in.Header.Get("X-Commit-Message")
		if msg == "" {
			msg = fmt.Sprintf("web edit: create/modify %q", upath)
		}
		content, err := ioutil.ReadAll(in.Body)
		errcheck(err)
		edit := Edit{
			UserName:  userinfo.Name,
			UserEmail: username + "@edit.team4272.com",
			Time:      time.Now(),
			Message:   msg + "\n",
			Files: map[string][]byte{
				upath[1:]: content,
			},
		}
		errcheck(GitCommit(edit))
		errcheck(GitPush())
		errcheck(renderModified(out, upath))
		if fileExists {
			out.WriteHeader(http.StatusOK)
		} else {
			out.WriteHeader(http.StatusCreated)
		}
	case http.MethodDelete:
		if !fileExists {
			http.NotFound(out, in)
			return
		}
		username := in.Header.Get("X-Nginx-User")
		userinfo, err := user.Lookup(username)
		errcheck(err)
		msg := in.Header.Get("X-Commit-Message")
		if msg == "" {
			msg = fmt.Sprintf("web edit: delete %q", upath)
		}
		edit := Edit{
			UserName:  userinfo.Name,
			UserEmail: username + "@edit.team4272.com",
			Time:      time.Now(),
			Message:   msg + "\n",
			Files: map[string][]byte{
				upath[1:]: nil,
			},
		}
		errcheck(GitCommit(edit))
		errcheck(GitPush())
		errcheck(renderDeleted(out, upath))
		out.WriteHeader(http.StatusOK)
	case http.MethodOptions:
		if !fileExists {
			http.NotFound(out, in)
			return
		}
		// POST because PostHack
		out.Header().Set("Allow", "GET, HEAD, PUT, POST, DELETE, OPTIONS")
		out.WriteHeader(http.StatusOK)
	default:
		if !fileExists {
			http.NotFound(out, in)
			return
		}
		out.Header().Set("Allow", "GET, HEAD, PUT, POST, DELETE, OPTIONS")
		out.WriteHeader(http.StatusMethodNotAllowed)
	}
}