04abbd8436
Following on from the changes in PR #4781, we can make additional message strings translatable using the tr.Tr.Get() method. Because this method performs printf(3)-style format string parsing and interpolation, we can simplify some of the surrounding calls, e.g., from fmt.Errorf() to errors.New(), and from fmt.Fprintf() to fmt.Fprintln(). This ensures that if either the translated text or any interpolated arguments happen to contain character sequences that would be interpreted as Go format specifiers (e.g., "%s" or "%d"), these will not result in warnings such as "%!s(MISSING)" in the output text. Note also that we try to remove newlines from the message strings were possible and change the surrounding calls to append them instead, e.g., with fmt.Fprintln().
91 lines
2.2 KiB
Go
91 lines
2.2 KiB
Go
package tasklog
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/git-lfs/git-lfs/v3/tr"
|
|
)
|
|
|
|
// PercentageTask is a task that is performed against a known number of
|
|
// elements.
|
|
type PercentageTask struct {
|
|
// members managed via sync/atomic must be aligned at the top of this
|
|
// structure (see: https://github.com/git-lfs/git-lfs/pull/2880).
|
|
|
|
// n is the number of elements whose work has been completed. It is
|
|
// managed sync/atomic.
|
|
n uint64
|
|
// total is the total number of elements to execute work upon.
|
|
total uint64
|
|
// msg is the task message.
|
|
msg string
|
|
// ch is a channel which is written to when the task state changes and
|
|
// is closed when the task is completed.
|
|
ch chan *Update
|
|
}
|
|
|
|
func NewPercentageTask(msg string, total uint64) *PercentageTask {
|
|
p := &PercentageTask{
|
|
msg: msg,
|
|
total: total,
|
|
ch: make(chan *Update, 1),
|
|
}
|
|
p.Count(0)
|
|
|
|
return p
|
|
}
|
|
|
|
// Count indicates that work has been completed against "n" number of elements,
|
|
// marking the task as complete if the total "n" given to all invocations of
|
|
// this method is equal to total.
|
|
//
|
|
// Count returns the new total number of (atomically managed) elements that have
|
|
// been completed.
|
|
func (c *PercentageTask) Count(n uint64) (new uint64) {
|
|
if new = atomic.AddUint64(&c.n, n); new > c.total {
|
|
panic(fmt.Sprintf("tasklog: %s", tr.Tr.Get("counted too many items")))
|
|
}
|
|
|
|
var percentage float64
|
|
if c.total == 0 {
|
|
percentage = 100
|
|
} else {
|
|
percentage = 100 * float64(new) / float64(c.total)
|
|
}
|
|
|
|
c.ch <- &Update{
|
|
S: fmt.Sprintf("%s: %3.f%% (%d/%d)",
|
|
c.msg, math.Floor(percentage), new, c.total),
|
|
At: time.Now(),
|
|
}
|
|
|
|
if new >= c.total {
|
|
close(c.ch)
|
|
}
|
|
|
|
return new
|
|
}
|
|
|
|
// Entry logs a line-delimited task entry.
|
|
func (t *PercentageTask) Entry(update string) {
|
|
t.ch <- &Update{
|
|
S: fmt.Sprintf("%s\n", update),
|
|
At: time.Now(),
|
|
Force: true,
|
|
}
|
|
}
|
|
|
|
// Updates implements Task.Updates and returns a channel which is written to
|
|
// when the state of this task changes, and closed when the task is completed.
|
|
// has been completed.
|
|
func (c *PercentageTask) Updates() <-chan *Update {
|
|
return c.ch
|
|
}
|
|
|
|
// Throttled implements Task.Throttled and returns true, indicating that this
|
|
// task is throttled.
|
|
func (c *PercentageTask) Throttled() bool { return true }
|