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) } }