|
|
|
@ -234,71 +234,73 @@ func parseDiffStat(stdout string) (numFiles, totalAdditions, totalDeletions int, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GetDiffOrPatch generates either diff or formatted patch data between given revisions
|
|
|
|
|
func (repo *Repository) GetDiffOrPatch(base, head string, w io.Writer, patch, binary bool) error { |
|
|
|
|
func (repo *Repository) GetDiffOrPatch(compareString string, w io.Writer, patch, binary bool) error { |
|
|
|
|
if patch { |
|
|
|
|
return repo.GetPatch(base, head, w) |
|
|
|
|
return repo.GetPatch(compareString, w) |
|
|
|
|
} |
|
|
|
|
if binary { |
|
|
|
|
return repo.GetDiffBinary(base, head, w) |
|
|
|
|
return repo.GetDiffBinary(compareString, w) |
|
|
|
|
} |
|
|
|
|
return repo.GetDiff(base, head, w) |
|
|
|
|
return repo.GetDiff(compareString, w) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func parseCompareArgs(compareArgs string) (args []string) { |
|
|
|
|
parts := strings.Split(compareArgs, "...") |
|
|
|
|
if len(parts) == 2 { |
|
|
|
|
return []string{compareArgs} |
|
|
|
|
} |
|
|
|
|
parts = strings.Split(compareArgs, "..") |
|
|
|
|
if len(parts) == 2 { |
|
|
|
|
return parts |
|
|
|
|
} |
|
|
|
|
parts = strings.Fields(compareArgs) |
|
|
|
|
if len(parts) == 2 { |
|
|
|
|
return parts |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GetDiff generates and returns patch data between given revisions, optimized for human readability
|
|
|
|
|
func (repo *Repository) GetDiff(base, head string, w io.Writer) error { |
|
|
|
|
func (repo *Repository) GetDiff(compareArgs string, w io.Writer) error { |
|
|
|
|
args := parseCompareArgs(compareArgs) |
|
|
|
|
if len(args) == 0 { |
|
|
|
|
return fmt.Errorf("invalid compareArgs: %s", compareArgs) |
|
|
|
|
} |
|
|
|
|
stderr := new(bytes.Buffer) |
|
|
|
|
err := NewCommand(repo.Ctx, "diff", "-p").AddDynamicArguments(base + "..." + head). |
|
|
|
|
return NewCommand(repo.Ctx, "diff", "-p").AddDynamicArguments(args...). |
|
|
|
|
Run(&RunOpts{ |
|
|
|
|
Dir: repo.Path, |
|
|
|
|
Stdout: w, |
|
|
|
|
Stderr: stderr, |
|
|
|
|
}) |
|
|
|
|
if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) { |
|
|
|
|
return NewCommand(repo.Ctx, "diff", "-p").AddDynamicArguments(base, head). |
|
|
|
|
Run(&RunOpts{ |
|
|
|
|
Dir: repo.Path, |
|
|
|
|
Stdout: w, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GetDiffBinary generates and returns patch data between given revisions, including binary diffs.
|
|
|
|
|
func (repo *Repository) GetDiffBinary(base, head string, w io.Writer) error { |
|
|
|
|
stderr := new(bytes.Buffer) |
|
|
|
|
err := NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram").AddDynamicArguments(base + "..." + head). |
|
|
|
|
Run(&RunOpts{ |
|
|
|
|
Dir: repo.Path, |
|
|
|
|
Stdout: w, |
|
|
|
|
Stderr: stderr, |
|
|
|
|
}) |
|
|
|
|
if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) { |
|
|
|
|
return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram").AddDynamicArguments(base, head). |
|
|
|
|
Run(&RunOpts{ |
|
|
|
|
Dir: repo.Path, |
|
|
|
|
Stdout: w, |
|
|
|
|
}) |
|
|
|
|
func (repo *Repository) GetDiffBinary(compareArgs string, w io.Writer) error { |
|
|
|
|
args := parseCompareArgs(compareArgs) |
|
|
|
|
if len(args) == 0 { |
|
|
|
|
return fmt.Errorf("invalid compareArgs: %s", compareArgs) |
|
|
|
|
} |
|
|
|
|
return err |
|
|
|
|
return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram").AddDynamicArguments(args...).Run(&RunOpts{ |
|
|
|
|
Dir: repo.Path, |
|
|
|
|
Stdout: w, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GetPatch generates and returns format-patch data between given revisions, able to be used with `git apply`
|
|
|
|
|
func (repo *Repository) GetPatch(base, head string, w io.Writer) error { |
|
|
|
|
func (repo *Repository) GetPatch(compareArgs string, w io.Writer) error { |
|
|
|
|
args := parseCompareArgs(compareArgs) |
|
|
|
|
if len(args) == 0 { |
|
|
|
|
return fmt.Errorf("invalid compareArgs: %s", compareArgs) |
|
|
|
|
} |
|
|
|
|
stderr := new(bytes.Buffer) |
|
|
|
|
err := NewCommand(repo.Ctx, "format-patch", "--binary", "--stdout").AddDynamicArguments(base + "..." + head). |
|
|
|
|
return NewCommand(repo.Ctx, "format-patch", "--binary", "--stdout").AddDynamicArguments(args...). |
|
|
|
|
Run(&RunOpts{ |
|
|
|
|
Dir: repo.Path, |
|
|
|
|
Stdout: w, |
|
|
|
|
Stderr: stderr, |
|
|
|
|
}) |
|
|
|
|
if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) { |
|
|
|
|
return NewCommand(repo.Ctx, "format-patch", "--binary", "--stdout").AddDynamicArguments(base, head). |
|
|
|
|
Run(&RunOpts{ |
|
|
|
|
Dir: repo.Path, |
|
|
|
|
Stdout: w, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GetFilesChangedBetween returns a list of all files that have been changed between the given commits
|
|
|
|
@ -329,21 +331,6 @@ func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, err |
|
|
|
|
return split, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GetDiffFromMergeBase generates and return patch data from merge base to head
|
|
|
|
|
func (repo *Repository) GetDiffFromMergeBase(base, head string, w io.Writer) error { |
|
|
|
|
stderr := new(bytes.Buffer) |
|
|
|
|
err := NewCommand(repo.Ctx, "diff", "-p", "--binary").AddDynamicArguments(base + "..." + head). |
|
|
|
|
Run(&RunOpts{ |
|
|
|
|
Dir: repo.Path, |
|
|
|
|
Stdout: w, |
|
|
|
|
Stderr: stderr, |
|
|
|
|
}) |
|
|
|
|
if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) { |
|
|
|
|
return repo.GetDiffBinary(base, head, w) |
|
|
|
|
} |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ReadPatchCommit will check if a diff patch exists and return stats
|
|
|
|
|
func (repo *Repository) ReadPatchCommit(prID int64) (commitSHA string, err error) { |
|
|
|
|
// Migrated repositories download patches to "pulls" location
|
|
|
|
|