func GetDiffRange(repoPath, beforeCommitId string, afterCommitId string, maxlines int) (*Diff, error) { repo, err := git.OpenRepository(repoPath) if err != nil { return nil, err } commit, err := repo.GetCommit(afterCommitId) if err != nil { return nil, err } rd, wr := io.Pipe() var cmd *exec.Cmd // if "after" commit given if beforeCommitId == "" { // First commit of repository. if commit.ParentCount() == 0 { cmd = exec.Command("git", "show", afterCommitId) } else { c, _ := commit.Parent(0) cmd = exec.Command("git", "diff", c.Id.String(), afterCommitId) } } else { cmd = exec.Command("git", "diff", beforeCommitId, afterCommitId) } cmd.Dir = repoPath cmd.Stdout = wr cmd.Stdin = os.Stdin cmd.Stderr = os.Stderr done := make(chan error) go func() { cmd.Start() done <- cmd.Wait() wr.Close() }() defer rd.Close() desc := fmt.Sprintf("GetDiffRange(%s)", repoPath) pid := process.Add(desc, cmd) go func() { // In case process became zombie. select { case <-time.After(5 * time.Minute): if errKill := process.Kill(pid); errKill != nil { log.Error(4, "git_diff.ParsePatch(Kill): %v", err) } <-done // return "", ErrExecTimeout.Error(), ErrExecTimeout case err = <-done: process.Remove(pid) } }() return ParsePatch(pid, maxlines, cmd, rd) }
func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) { gitRepo, err := git.OpenRepository(repoPath) if err != nil { return nil, err } commit, err := gitRepo.GetCommit(afterCommitID) if err != nil { return nil, err } var cmd *exec.Cmd // if "after" commit given if len(beforeCommitID) == 0 { // First commit of repository. if commit.ParentCount() == 0 { cmd = exec.Command("git", "show", afterCommitID) } else { c, _ := commit.Parent(0) cmd = exec.Command("git", "diff", "-M", c.ID.String(), afterCommitID) } } else { cmd = exec.Command("git", "diff", "-M", beforeCommitID, afterCommitID) } cmd.Dir = repoPath cmd.Stderr = os.Stderr stdout, err := cmd.StdoutPipe() if err != nil { return nil, fmt.Errorf("StdoutPipe: %v", err) } if err = cmd.Start(); err != nil { return nil, fmt.Errorf("Start: %v", err) } pid := process.Add(fmt.Sprintf("GetDiffRange [repo_path: %s]", repoPath), cmd) defer process.Remove(pid) diff, err := ParsePatch(maxLines, maxLineCharacteres, maxFiles, stdout) if err != nil { return nil, fmt.Errorf("ParsePatch: %v", err) } if err = cmd.Wait(); err != nil { return nil, fmt.Errorf("Wait: %v", err) } return diff, nil }
// GetDiffPreview produces and returns diff result of a file which is not yet committed. func (repo *Repository) GetDiffPreview(branch, treePath, content string) (diff *Diff, err error) { repoWorkingPool.CheckIn(com.ToStr(repo.ID)) defer repoWorkingPool.CheckOut(com.ToStr(repo.ID)) if err = repo.DiscardLocalRepoBranchChanges(branch); err != nil { return nil, fmt.Errorf("DiscardLocalRepoBranchChanges [branch: %s]: %v", branch, err) } else if err = repo.UpdateLocalCopyBranch(branch); err != nil { return nil, fmt.Errorf("UpdateLocalCopyBranch [branch: %s]: %v", branch, err) } localPath := repo.LocalCopyPath() filePath := path.Join(localPath, treePath) os.MkdirAll(filepath.Dir(filePath), os.ModePerm) if err = ioutil.WriteFile(filePath, []byte(content), 0666); err != nil { return nil, fmt.Errorf("WriteFile: %v", err) } cmd := exec.Command("git", "diff", treePath) cmd.Dir = localPath cmd.Stderr = os.Stderr stdout, err := cmd.StdoutPipe() if err != nil { return nil, fmt.Errorf("StdoutPipe: %v", err) } if err = cmd.Start(); err != nil { return nil, fmt.Errorf("Start: %v", err) } pid := process.Add(fmt.Sprintf("GetDiffPreview [repo_path: %s]", repo.RepoPath()), cmd) defer process.Remove(pid) diff, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdout) if err != nil { return nil, fmt.Errorf("ParsePatch: %v", err) } if err = cmd.Wait(); err != nil { return nil, fmt.Errorf("Wait: %v", err) } return diff, nil }