knotserver: git/merge: separate applyPatch and checkPatch #527

merged
opened by boltless.me targeting master from boltless.me/core: push-skprtmnmwuqn
Changed files
+62 -60
knotserver
git
+62 -60
knotserver/git/merge.go
··· 143 143 return tmpDir, nil 144 144 } 145 145 146 - func (g *GitRepo) applyPatch(tmpDir, patchFile string, checkOnly bool, opts *MergeOptions) error { 146 + func (g *GitRepo) checkPatch(tmpDir, patchFile string) error { 147 147 var stderr bytes.Buffer 148 - var cmd *exec.Cmd 149 148 150 - if checkOnly { 151 - cmd = exec.Command("git", "-C", tmpDir, "apply", "--check", "-v", patchFile) 152 - } else { 153 - // if patch is a format-patch, apply using 'git am' 154 - if opts.FormatPatch { 155 - amCmd := exec.Command("git", "-C", tmpDir, "am", patchFile) 156 - amCmd.Stderr = &stderr 157 - if err := amCmd.Run(); err != nil { 158 - return fmt.Errorf("patch application failed: %s", stderr.String()) 159 - } 160 - return nil 149 + cmd := exec.Command("git", "-C", tmpDir, "apply", "--check", "-v", patchFile) 150 + cmd.Stderr = &stderr 151 + 152 + if err := cmd.Run(); err != nil { 153 + conflicts := parseGitApplyErrors(stderr.String()) 154 + return &ErrMerge{ 155 + Message: "patch cannot be applied cleanly", 156 + Conflicts: conflicts, 157 + HasConflict: len(conflicts) > 0, 158 + OtherError: err, 161 159 } 160 + } 161 + return nil 162 + } 162 163 163 - // else, apply using 'git apply' and commit it manually 164 - exec.Command("git", "-C", tmpDir, "config", "advice.mergeConflict", "false").Run() 165 - if opts != nil { 166 - applyCmd := exec.Command("git", "-C", tmpDir, "apply", patchFile) 167 - applyCmd.Stderr = &stderr 168 - if err := applyCmd.Run(); err != nil { 169 - return fmt.Errorf("patch application failed: %s", stderr.String()) 170 - } 164 + func (g *GitRepo) applyPatch(tmpDir, patchFile string, opts *MergeOptions) error { 165 + var stderr bytes.Buffer 166 + var cmd *exec.Cmd 171 167 172 - stageCmd := exec.Command("git", "-C", tmpDir, "add", ".") 173 - if err := stageCmd.Run(); err != nil { 174 - return fmt.Errorf("failed to stage changes: %w", err) 175 - } 168 + // if patch is a format-patch, apply using 'git am' 169 + if opts.FormatPatch { 170 + amCmd := exec.Command("git", "-C", tmpDir, "am", patchFile) 171 + amCmd.Stderr = &stderr 172 + if err := amCmd.Run(); err != nil { 173 + return fmt.Errorf("patch application failed: %s", stderr.String()) 174 + } 175 + return nil 176 + } 176 177 177 - commitArgs := []string{"-C", tmpDir, "commit"} 178 + // else, apply using 'git apply' and commit it manually 179 + exec.Command("git", "-C", tmpDir, "config", "advice.mergeConflict", "false").Run() 180 + if opts != nil { 181 + applyCmd := exec.Command("git", "-C", tmpDir, "apply", patchFile) 182 + applyCmd.Stderr = &stderr 183 + if err := applyCmd.Run(); err != nil { 184 + return fmt.Errorf("patch application failed: %s", stderr.String()) 185 + } 178 186 179 - // Set author if provided 180 - authorName := opts.AuthorName 181 - authorEmail := opts.AuthorEmail 187 + stageCmd := exec.Command("git", "-C", tmpDir, "add", ".") 188 + if err := stageCmd.Run(); err != nil { 189 + return fmt.Errorf("failed to stage changes: %w", err) 190 + } 182 191 183 - if authorEmail == "" { 184 - authorEmail = "noreply@tangled.sh" 185 - } 192 + commitArgs := []string{"-C", tmpDir, "commit"} 186 193 187 - if authorName == "" { 188 - authorName = "Tangled" 189 - } 194 + // Set author if provided 195 + authorName := opts.AuthorName 196 + authorEmail := opts.AuthorEmail 190 197 191 - if authorName != "" { 192 - commitArgs = append(commitArgs, "--author", fmt.Sprintf("%s <%s>", authorName, authorEmail)) 193 - } 198 + if authorEmail == "" { 199 + authorEmail = "noreply@tangled.sh" 200 + } 194 201 195 - commitArgs = append(commitArgs, "-m", opts.CommitMessage) 202 + if authorName == "" { 203 + authorName = "Tangled" 204 + } 196 205 197 - if opts.CommitBody != "" { 198 - commitArgs = append(commitArgs, "-m", opts.CommitBody) 199 - } 206 + if authorName != "" { 207 + commitArgs = append(commitArgs, "--author", fmt.Sprintf("%s <%s>", authorName, authorEmail)) 208 + } 209 + 210 + commitArgs = append(commitArgs, "-m", opts.CommitMessage) 200 211 201 - cmd = exec.Command("git", commitArgs...) 202 - } else { 203 - // If no commit message specified, use git-am which automatically creates a commit 204 - cmd = exec.Command("git", "-C", tmpDir, "am", patchFile) 212 + if opts.CommitBody != "" { 213 + commitArgs = append(commitArgs, "-m", opts.CommitBody) 205 214 } 215 + 216 + cmd = exec.Command("git", commitArgs...) 217 + } else { 218 + // If no commit message specified, use git-am which automatically creates a commit 219 + cmd = exec.Command("git", "-C", tmpDir, "am", patchFile) 206 220 } 207 221 208 222 cmd.Stderr = &stderr 209 223 210 224 if err := cmd.Run(); err != nil { 211 - if checkOnly { 212 - conflicts := parseGitApplyErrors(stderr.String()) 213 - return &ErrMerge{ 214 - Message: "patch cannot be applied cleanly", 215 - Conflicts: conflicts, 216 - HasConflict: len(conflicts) > 0, 217 - OtherError: err, 218 - } 219 - } 220 225 return fmt.Errorf("patch application failed: %s", stderr.String()) 221 226 } 222 227 ··· 228 233 return val 229 234 } 230 235 231 - var opts MergeOptions 232 - opts.FormatPatch = patchutil.IsFormatPatch(string(patchData)) 233 - 234 236 patchFile, err := g.createTempFileWithPatch(patchData) 235 237 if err != nil { 236 238 return &ErrMerge{ ··· 249 251 } 250 252 defer os.RemoveAll(tmpDir) 251 253 252 - result := g.applyPatch(tmpDir, patchFile, true, &opts) 254 + result := g.checkPatch(tmpDir, patchFile) 253 255 mergeCheckCache.Set(g, patchData, targetBranch, result) 254 256 return result 255 257 } ··· 277 279 } 278 280 defer os.RemoveAll(tmpDir) 279 281 280 - if err := g.applyPatch(tmpDir, patchFile, false, opts); err != nil { 282 + if err := g.applyPatch(tmpDir, patchFile, opts); err != nil { 281 283 return err 282 284 } 283 285