package xrpc import ( "bytes" "fmt" "net/http" "os/exec" "strings" "github.com/bluesky-social/indigo/atproto/atclient" "github.com/bluesky-social/indigo/atproto/syntax" ) func (x *Xrpc) FormatPatch(w http.ResponseWriter, r *http.Request) { var ( repoQuery = r.URL.Query().Get("repo") from = r.URL.Query().Get("from") to = r.URL.Query().Get("to") ) repo, err := syntax.ParseDID(repoQuery) if err != nil { writeJson(w, http.StatusBadRequest, atclient.ErrorBody{Name: "BadRequest", Message: fmt.Sprintf("repo parameter invalid: %s", repoQuery)}) return } // reject leading dashes so user input can't be parsed as git flags if from == "" || to == "" || strings.HasPrefix(from, "-") || strings.HasPrefix(to, "-") { writeJson(w, http.StatusBadRequest, atclient.ErrorBody{Name: "BadRequest", Message: "missing or invalid from/to parameter"}) return } l := x.logger.With("method", "git.formatPatch", "repo", repo, "from", from, "to", to) l.Debug("request") ctx := r.Context() repoPath, err := x.makeRepoPath(ctx, repo) if err != nil { writeJson(w, http.StatusNotFound, atclient.ErrorBody{Name: "RepoNotFound", Message: fmt.Sprintf("unknown repository: %q", repo)}) return } cmd := exec.CommandContext(ctx, "git", "-C", repoPath, "format-patch", "--stdout", fmt.Sprintf("%s..%s", from, to)) stderr := new(bytes.Buffer) cmd.Stderr = stderr w.Header().Set("Content-Type", "text/plain; charset=utf-8") cmd.Stdout = w if err := cmd.Run(); err != nil { l.Error("running format-patch", "err", err, "stderr", stderr.String()) w.WriteHeader(http.StatusInternalServerError) } }