Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ All notable changes to `src-cli` are documented in this file.

### Changed

- `src campaign [apply|preview]` now prints more detailed information about the diffs produced in each repository when run in verbose mode with `-v`. [#390](https://github.com/sourcegraph/src-cli/pull/390)

### Fixed

- If `src campaign [validate|apply|preview]` was aborted while it was downloading repository archives it could leave behind partial ZIP files that would produce an error on the next run. This is now fixed by deleting partial files on abort. [#388](https://github.com/sourcegraph/src-cli/pull/388)
Expand Down
103 changes: 95 additions & 8 deletions cmd/src/campaign_progress_printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import (
"github.com/sourcegraph/src-cli/internal/output"
)

func newCampaignProgressPrinter(out *output.Output, numParallelism int) *campaignProgressPrinter {
func newCampaignProgressPrinter(out *output.Output, verbose bool, numParallelism int) *campaignProgressPrinter {
return &campaignProgressPrinter{
out: out,

verbose: verbose,

numParallelism: numParallelism,

completedTasks: map[string]bool{},
Expand All @@ -26,6 +28,8 @@ func newCampaignProgressPrinter(out *output.Output, numParallelism int) *campaig
type campaignProgressPrinter struct {
out *output.Output

verbose bool

progress output.ProgressWithStatusBars
numStatusBars int

Expand Down Expand Up @@ -134,18 +138,47 @@ func (p *campaignProgressPrinter) PrintStatuses(statuses []*campaigns.TaskStatus
}

for _, ts := range newlyCompleted {
statusText, err := taskStatusText(ts)
if err != nil {
p.progress.Verbosef("%-*s failed to display status: %s", p.maxRepoName, ts.RepoName, err)
continue
var fileDiffs []*diff.FileDiff

if ts.ChangesetSpec != nil {
var err error
fileDiffs, err = diff.ParseMultiFileDiff([]byte(ts.ChangesetSpec.Commits[0].Diff))
if err != nil {
p.progress.Verbosef("%-*s failed to display status: %s", p.maxRepoName, ts.RepoName, err)
continue
}
}

p.progress.Verbosef("%-*s %s", p.maxRepoName, ts.RepoName, statusText)
if p.verbose {
p.progress.WriteLine(output.Linef("", output.StylePending, "%s", ts.RepoName))

if ts.ChangesetSpec == nil {
p.progress.Verbosef(" No changes")
} else {
lines, err := verboseDiffSummary(fileDiffs)
if err != nil {
p.progress.Verbosef("%-*s failed to display status: %s", p.maxRepoName, ts.RepoName, err)
continue
}

for _, line := range lines {
p.progress.Verbose(line)
}
}

p.progress.Verbose("")
}

if idx, ok := p.repoStatusBar[ts.RepoName]; ok {
// Log that this task completed, but only if there is no
// currently executing one in this bar, to avoid flicker.
if _, ok := p.statusBarRepo[idx]; !ok {
statusText, err := taskStatusBarText(ts)
if err != nil {
p.progress.Verbosef("%-*s failed to display status: %s", p.maxRepoName, ts.RepoName, err)
continue
}

if ts.Err != nil {
p.progress.StatusBarFailf(idx, statusText)
} else {
Expand All @@ -163,7 +196,7 @@ func (p *campaignProgressPrinter) PrintStatuses(statuses []*campaigns.TaskStatus
continue
}

statusText, err := taskStatusText(ts)
statusText, err := taskStatusBarText(ts)
if err != nil {
p.progress.Verbosef("%-*s failed to display status: %s", p.maxRepoName, ts.RepoName, err)
continue
Expand All @@ -181,7 +214,7 @@ type statusTexter interface {
StatusText() string
}

func taskStatusText(ts *campaigns.TaskStatus) (string, error) {
func taskStatusBarText(ts *campaigns.TaskStatus) (string, error) {
var statusText string

if ts.IsCompleted() {
Expand Down Expand Up @@ -223,3 +256,57 @@ func taskStatusText(ts *campaigns.TaskStatus) (string, error) {

return statusText, nil
}

func verboseDiffSummary(fileDiffs []*diff.FileDiff) ([]string, error) {
var (
lines []string

maxFilenameLen int
sumInsertions int
sumDeletions int
)

fileStats := make(map[string]string, len(fileDiffs))

for _, f := range fileDiffs {
name := f.NewName
if name == "/dev/null" {
name = f.OrigName
}

if len(name) > maxFilenameLen {
maxFilenameLen = len(name)
}

stat := f.Stat()

sumInsertions += int(stat.Added) + int(stat.Changed)
sumDeletions += int(stat.Deleted) + int(stat.Changed)

num := stat.Added + 2*stat.Changed + stat.Deleted

fileStats[name] = fmt.Sprintf("%d %s", num, diffStatDiagram(stat))
}

for file, stats := range fileStats {
lines = append(lines, fmt.Sprintf("\t%-*s | %s", maxFilenameLen, file, stats))
}

var insertionsPlural string
if sumInsertions != 0 {
insertionsPlural = "s"
}

var deletionsPlural string
if sumDeletions != 1 {
deletionsPlural = "s"
}

lines = append(lines, fmt.Sprintf(" %s, %s, %s",
diffStatDescription(fileDiffs),
fmt.Sprintf("%d insertion%s", sumInsertions, insertionsPlural),
fmt.Sprintf("%d deletion%s", sumDeletions, deletionsPlural),
))

return lines, nil
}
2 changes: 1 addition & 1 deletion cmd/src/campaigns_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ func campaignsExecute(ctx context.Context, out *output.Output, svc *campaigns.Se
campaignsCompletePending(pending, "Resolved repositories")
}

p := newCampaignProgressPrinter(out, opts.Parallelism)
p := newCampaignProgressPrinter(out, *verbose, opts.Parallelism)
specs, err := svc.ExecuteCampaignSpec(ctx, repos, executor, campaignSpec, p.PrintStatuses)
if err != nil {
return "", "", err
Expand Down
9 changes: 4 additions & 5 deletions internal/campaigns/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,10 @@ type ExecutorOpts struct {
Parallelism int
Timeout time.Duration

ClearCache bool
KeepLogs bool
VerboseLogger bool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

TempDir string
CacheDir string
ClearCache bool
KeepLogs bool
TempDir string
CacheDir string
}

func (svc *Service) NewExecutor(opts ExecutorOpts) Executor {
Expand Down