git-lfs/tasklog/percentage_task.go
Chris Darroch 04abbd8436 make additional message strings translatable
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().
2022-01-29 22:36:19 -08:00

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 }