Monorepo for Tangled
at master 94 lines 2.4 kB view raw
1package xrpc 2 3import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "net/http" 8 9 "tangled.org/core/api/tangled" 10 "tangled.org/core/knotserver/git" 11 "tangled.org/core/patchutil" 12 xrpcerr "tangled.org/core/xrpc/errors" 13) 14 15func (x *Xrpc) MergeCheck(w http.ResponseWriter, r *http.Request) { 16 l := x.Logger.With("handler", "MergeCheck") 17 fail := func(e xrpcerr.XrpcError) { 18 l.Error("failed", "kind", e.Tag, "error", e.Message) 19 writeError(w, e, http.StatusBadRequest) 20 } 21 22 var data tangled.RepoMergeCheck_Input 23 if err := json.NewDecoder(r.Body).Decode(&data); err != nil { 24 fail(xrpcerr.GenericError(err)) 25 return 26 } 27 28 did := data.Did 29 name := data.Name 30 31 if did == "" || name == "" { 32 fail(xrpcerr.GenericError(fmt.Errorf("did and name are required"))) 33 return 34 } 35 36 repoDid, err := x.Db.GetRepoDid(did, name) 37 if err != nil { 38 fail(xrpcerr.RepoNotFoundError) 39 return 40 } 41 repoPath, _, _, err := x.Db.ResolveRepoDIDOnDisk(x.Config.Repo.ScanPath, repoDid) 42 if err != nil { 43 fail(xrpcerr.RepoNotFoundError) 44 return 45 } 46 47 gr, err := git.Open(repoPath, data.Branch) 48 if err != nil { 49 fail(xrpcerr.GenericError(fmt.Errorf("failed to open repository: %w", err))) 50 return 51 } 52 53 mo := git.MergeOptions{} 54 mo.CommitMessage = "merge check" 55 mo.CommitterName = x.Config.Git.UserName 56 mo.CommitterEmail = x.Config.Git.UserEmail 57 mo.FormatPatch = patchutil.IsFormatPatch(data.Patch) 58 59 err = gr.MergeCheckWithOptions(data.Patch, data.Branch, mo) 60 61 response := tangled.RepoMergeCheck_Output{ 62 Is_conflicted: false, 63 } 64 65 if err != nil { 66 var mergeErr *git.ErrMerge 67 if errors.As(err, &mergeErr) { 68 response.Is_conflicted = true 69 70 conflicts := make([]*tangled.RepoMergeCheck_ConflictInfo, len(mergeErr.Conflicts)) 71 for i, conflict := range mergeErr.Conflicts { 72 conflicts[i] = &tangled.RepoMergeCheck_ConflictInfo{ 73 Filename: conflict.Filename, 74 Reason: conflict.Reason, 75 } 76 } 77 response.Conflicts = conflicts 78 79 if mergeErr.Message != "" { 80 response.Message = &mergeErr.Message 81 } 82 } else { 83 response.Is_conflicted = true 84 errMsg := err.Error() 85 response.Error = &errMsg 86 } 87 } 88 89 l.Debug("merge check response", "isConflicted", response.Is_conflicted, "err", response.Error, "conflicts", response.Conflicts) 90 91 w.Header().Set("Content-Type", "application/json") 92 w.WriteHeader(http.StatusOK) 93 json.NewEncoder(w).Encode(response) 94}