Browse Source

Diff patch (#3345)

* Add support for .diff and .patch

Add the ability to get text-diff and format-patch by adding .diff or
.patch in the end of a commit url. Issue #2641

* models: git_diff: various fixes

* Renames commitId to commitID.
* Writes stderr to a bytes.Buffer and displays proper error message on
command failure.
* Various style changes.

Signed-off-by: Dennis Chen <barracks510@gmail.com>
Dennis Chen 8 years ago
parent
commit
dfab54d5a2
2 changed files with 56 additions and 3 deletions
  1. 46 2
      models/git_diff.go
  2. 10 1
      routers/repo/commit.go

+ 46 - 2
models/git_diff.go

@@ -422,6 +422,50 @@ func GetDiffRange(repoPath, beforeCommitID string, afterCommitID string, maxLine
 	return diff, nil
 }
 
-func GetDiffCommit(repoPath, commitId string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
-	return GetDiffRange(repoPath, "", commitId, maxLines, maxLineCharacteres, maxFiles)
+func GetRawDiff(repoPath, commitID, diffType string) (string, error) {
+	repo, err := git.OpenRepository(repoPath)
+	if err != nil {
+		return "", err
+	}
+
+	commit, err := repo.GetCommit(commitID)
+	if err != nil {
+		return "", err
+	}
+
+	var cmd *exec.Cmd
+	switch diffType {
+	case "diff":
+		if commit.ParentCount() == 0 {
+			cmd = exec.Command("git", "show", commitID)
+		} else {
+			c, _ := commit.Parent(0)
+			cmd = exec.Command("git", "diff", "-M", c.ID.String(), commitID)
+		}
+	case "patch":
+		if commit.ParentCount() == 0 {
+			cmd = exec.Command("git", "format-patch", "--no-signature", "--stdout", "--root", commitID)
+		} else {
+			c, _ := commit.Parent(0)
+			query := fmt.Sprintf("%s...%s", commitID, c.ID.String())
+			cmd = exec.Command("git", "format-patch", "--no-signature", "--stdout", query)
+		}
+	default:
+		return "", fmt.Errorf("Invalid diffType '%s'", diffType)
+	}
+
+	stderr := new(bytes.Buffer)
+
+	cmd.Dir = repoPath
+	cmd.Stderr = stderr
+
+	stdout, err := cmd.Output()
+	if err != nil {
+		return "", fmt.Errorf("%v - %s", err, stderr)
+	}
+	return string(stdout), nil
+}
+
+func GetDiffCommit(repoPath, commitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
+	return GetDiffRange(repoPath, "", commitID, maxLines, maxLineCharacteres, maxFiles)
 }

+ 10 - 1
routers/repo/commit.go

@@ -195,7 +195,16 @@ func Diff(ctx *context.Context) {
 }
 
 func RawDiff(ctx *context.Context) {
-	panic("not implemented")
+	diff, err := models.GetRawDiff(
+		models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name),
+		ctx.Params(":sha"),
+		ctx.Params(":ext"),
+	)
+	if err != nil {
+		ctx.Handle(404, "GetRawDiff", err)
+		return
+	}
+	ctx.HandleText(200, diff)
 }
 
 func CompareDiff(ctx *context.Context) {