Simplifying progress code (#1253)

This commit is contained in:
CyrusNajmabadi 2018-04-22 18:10:19 -07:00 committed by GitHub
parent fe3d854bc5
commit 7807edc166
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 53 deletions

View file

@ -86,7 +86,8 @@ type ProgressDisplay struct {
// a status message to help indicate that things are still working.
currentTick int
rows []Row
headerRow Row
resourceRows []ResourceRow
// A mapping from each resource URN we are told about to its current status.
eventUrnToResourceRow map[resource.URN]ResourceRow
@ -238,20 +239,30 @@ func DisplayProgressEvents(
// Gets the padding necessary to prepend to a message in order to keep it aligned in the
// terminal.
func (display *ProgressDisplay) getMessagePadding(uncolorizedColumns []string, columnIndex int) string {
func (display *ProgressDisplay) getMessagePadding(
id string, maxIDLength int, uncolorizedColumns []string, columnIndex int) string {
extraWhitespace := 1
// In the terminal we try to align the status messages for each resource.
// do not bother with this in the non-terminal case.
if display.isTerminal {
column := uncolorizedColumns[columnIndex]
maxIDLength := display.maxColumnLengths[columnIndex]
extraWhitespace = maxIDLength - len(column)
var column string
var maxLength int
if columnIndex == -1 {
column = id
maxLength = maxIDLength
} else {
column = uncolorizedColumns[columnIndex]
maxLength = display.maxColumnLengths[columnIndex]
}
extraWhitespace = maxLength - len(column)
contract.Assertf(extraWhitespace >= 0, "Neg whitespace. %v %s", maxIDLength, column)
if columnIndex > 0 {
// Place two spaces between all columns (except after the first column). The first
// column already has a ": " so it doesn't need the extra space.
// Place two spaces between all columns (except after the first column). The first
// column already has a ": " so it doesn't need the extra space.
if columnIndex >= 0 {
extraWhitespace += 2
}
}
@ -264,12 +275,12 @@ func (display *ProgressDisplay) getMessagePadding(uncolorizedColumns []string, c
// suffix. Importantly, if there isn't enough room to display all of that on the terminal, then
// the msg will be truncated to try to make it fit.
func (display *ProgressDisplay) getPaddedMessage(
colorizedColumns, uncolorizedColumns []string) string {
id string, maxIDLength int, colorizedColumns, uncolorizedColumns []string) string {
colorizedMessage := ""
for i := 1; i < len(colorizedColumns); i++ {
padding := display.getMessagePadding(uncolorizedColumns, i-1)
for i := 0; i < len(colorizedColumns); i++ {
padding := display.getMessagePadding(id, maxIDLength, uncolorizedColumns, i-1)
colorizedMessage += padding + colorizedColumns[i]
}
@ -278,7 +289,6 @@ func (display *ProgressDisplay) getPaddedMessage(
// msgWithColors having the color code information embedded with it. So we need to get
// the right substring of it, assuming that embedded colors are just markup and do not
// actually contribute to the length
id := uncolorizedColumns[0]
maxMsgLength := display.terminalWidth - len(id) - len(": ") - 1
if maxMsgLength < 0 {
maxMsgLength = 0
@ -310,23 +320,25 @@ func (display *ProgressDisplay) uncolorizeColumns(columns []string) []string {
return uncolorizedColumns
}
func (display *ProgressDisplay) refreshSingleRow(row Row) {
func (display *ProgressDisplay) refreshSingleRow(id string, maxIDLength int, row Row) {
colorizedColumns := row.ColorizedColumns()
colorizedColumns[display.suffixColumn] += row.ColorizedSuffix()
uncolorizedColumns := display.uncolorizeColumns(colorizedColumns)
msg := display.getPaddedMessage(colorizedColumns, uncolorizedColumns)
msg := display.getPaddedMessage(id, maxIDLength, colorizedColumns, uncolorizedColumns)
display.colorizeAndWriteProgress(makeActionProgress(
uncolorizedColumns[0], msg, true /*showID*/))
if display.isTerminal {
display.colorizeAndWriteProgress(makeActionProgress(
id, msg, true /*showID*/))
} else {
display.writeSimpleMessage(msg)
}
}
// Ensure our stored dimension info is up to date. Returns 'true' if the stored dimension info is
// updated.
func (display *ProgressDisplay) updateDimensions() bool {
updated := false
func (display *ProgressDisplay) updateDimensions(rows []Row) {
// don't do any refreshing if we're not in a terminal
if display.isTerminal {
currentTerminalWidth, _, err := terminal.GetSize(int(os.Stdout.Fd()))
@ -335,10 +347,9 @@ func (display *ProgressDisplay) updateDimensions() bool {
if currentTerminalWidth != display.terminalWidth {
// terminal width changed. Refresh everything
display.terminalWidth = currentTerminalWidth
updated = true
}
for _, row := range display.rows {
for _, row := range rows {
colorizedColumns := row.ColorizedColumns()
uncolorizedColumns := display.uncolorizeColumns(colorizedColumns)
@ -354,25 +365,47 @@ func (display *ProgressDisplay) updateDimensions() bool {
if columnLength > display.maxColumnLengths[i] {
display.maxColumnLengths[i] = columnLength
updated = true
}
}
}
}
}
return updated
func (display *ProgressDisplay) allRows() []Row {
result := []Row{}
if display.headerRow != nil {
result = append(result, display.headerRow)
}
for _, row := range display.resourceRows {
result = append(result, row)
}
return result
}
func (display *ProgressDisplay) refreshAllRowsIfInTerminal() {
if display.isTerminal {
if display.isTerminal && display.headerRow != nil {
// make sure our stored dimension info is up to date
display.updateDimensions()
for _, row := range display.rows {
display.refreshSingleRow(row)
rows := display.allRows()
display.updateDimensions(rows)
// tree := display.generateTree()
maxIDLength := len(fmt.Sprintf("%v", len(rows)-1))
for i, row := range rows {
var id string
if i == 0 {
id = "#"
} else {
id = fmt.Sprintf("%v", i)
}
display.refreshSingleRow(id, maxIDLength, row)
}
systemID := len(display.rows)
systemID := len(rows)
printedHeader := false
for _, payload := range display.systemEventPayloads {
@ -421,7 +454,7 @@ func (display *ProgressDisplay) processEndSteps() {
v.SetDone()
if !display.isTerminal {
display.refreshSingleRow(v)
display.refreshSingleRow("", 0, v)
}
} else {
// Explicitly transition the status so that we clear out any cached data for it.
@ -461,7 +494,7 @@ func (display *ProgressDisplay) processEndSteps() {
wroteResourceHeader = true
columns := row.ColorizedColumns()
display.writeSimpleMessage(" " +
columns[idColumn] + ": " +
// columns[idColumn] + ": " +
columns[typeColumn] + ": " +
columns[nameColumn])
}
@ -561,13 +594,10 @@ func (display *ProgressDisplay) processNormalEvent(event engine.Event) {
row, has := display.eventUrnToResourceRow[eventUrn]
if !has {
id := fmt.Sprintf("%v", len(display.eventUrnToResourceRow)+1)
// first time we're hearing about this resource. Create an initial nearly-empty
// status for it, assigning it a nice short ID.
row = &resourceRowData{
display: display,
id: id,
tick: display.currentTick,
diagInfo: &DiagInfo{},
step: engine.StepEventMetadata{Op: deploy.OpSame},
@ -575,7 +605,7 @@ func (display *ProgressDisplay) processNormalEvent(event engine.Event) {
display.eventUrnToResourceRow[eventUrn] = row
display.ensureHeaderRow()
display.rows = append(display.rows, row)
display.resourceRows = append(display.resourceRows, row)
}
if event.Type == engine.ResourcePreEvent {
@ -605,7 +635,7 @@ func (display *ProgressDisplay) processNormalEvent(event engine.Event) {
display.refreshAllRowsIfInTerminal()
} else {
// otherwise, just print out this single row.
display.refreshSingleRow(row)
display.refreshSingleRow("", 0, row)
}
}
@ -626,9 +656,9 @@ func (display *ProgressDisplay) handleSystemEvent(payload engine.StdoutEventPayl
}
func (display *ProgressDisplay) ensureHeaderRow() {
if len(display.rows) == 0 {
if display.headerRow == nil {
// about to make our first status message. make sure we present the header line first.
display.rows = append(display.rows, &headerRowData{display: display})
display.headerRow = &headerRowData{display: display}
}
}

View file

@ -12,7 +12,6 @@ import (
"github.com/pulumi/pulumi/pkg/engine"
"github.com/pulumi/pulumi/pkg/resource"
"github.com/pulumi/pulumi/pkg/resource/deploy"
"github.com/pulumi/pulumi/pkg/util/contract"
)
type Row interface {
@ -61,7 +60,7 @@ func (data *headerRowData) ColorizedColumns() []string {
} else {
statusColumn = header("Status")
}
data.columns = []string{"#", header("Resource Type"), header("Name"), statusColumn, header("Extra Info")}
data.columns = []string{header("Resource Type"), header("Name"), statusColumn, header("Extra Info")}
}
return data.columns
@ -75,10 +74,6 @@ func (data *headerRowData) ColorizedSuffix() string {
type resourceRowData struct {
display *ProgressDisplay
// The simple short ID we have generated for the resource to present it to the user.
// Usually similar to the form: aws.Function("name")
id string
// The change that the engine wants apply to that resource.
step engine.StepEventMetadata
@ -151,11 +146,10 @@ func (data *resourceRowData) RecordDiagEvent(event engine.Event) {
type column int
const (
idColumn column = 0
typeColumn column = 1
nameColumn column = 2
statusColumn column = 3
infoColumn column = 4
typeColumn column = 0
nameColumn column = 1
statusColumn column = 2
infoColumn column = 3
)
func (data *resourceRowData) ColorizedSuffix() string {
@ -171,9 +165,6 @@ func (data *resourceRowData) ColorizedSuffix() string {
func (data *resourceRowData) ColorizedColumns() []string {
step := data.step
if step.Op == "" {
contract.Failf("Finishing a resource we never heard about: '%s'", data.id)
}
var name string
var typ string
@ -185,8 +176,7 @@ func (data *resourceRowData) ColorizedColumns() []string {
typ = simplifyTypeName(data.step.URN.Type())
}
columns := make([]string, 5)
columns[idColumn] = data.id
columns := make([]string, 4)
columns[typeColumn] = typ
columns[nameColumn] = name