Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Blame · internal/format/format.go

Line attribution on main · 80 line(s)

c5902451
Keenan Nemetz
16d ago
1 // Package format renders values the way Vole's human-facing surfaces show them.
2 //
3 // It is deliberately internal: these are presentation choices for the CLI, the
4 // web UI and hook messages, not part of the API a developer embeds.
5 package format
6
c765ae2e
Keenan Nemetz
13d ago
7 import (
8 "fmt"
9 "time"
10 )
c5902451
Keenan Nemetz
16d ago
11
12 // Bytes renders a byte count in binary units ("1.4 MiB").
13 func Bytes(n int64) string {
14 const unit = 1024
15 if n < unit {
16 return fmt.Sprintf("%d B", n)
17 }
18 div, exp := int64(unit), 0
19 for m := n / unit; m >= unit; m /= unit {
20 div *= unit
21 exp++
22 }
23 return fmt.Sprintf("%.1f %ciB", float64(n)/float64(div), "KMGTPE"[exp])
24 }
25
26 // SHA is the short form of a commit id used in links and log lines.
27 func SHA(s string) string {
28 if len(s) > 8 {
29 return s[:8]
30 }
31 return s
32 }
33
34 // OID is the short form of an object id shown beside an upload.
35 func OID(s string) string {
36 if len(s) > 12 {
37 return s[:12]
38 }
39 return s
40 }
41
42 // ID is the short form of an entity id (issue, request, comment, run).
43 func ID(s string) string {
44 if len(s) > 8 {
45 return s[:8]
46 }
47 return s
48 }
c765ae2e
Keenan Nemetz
13d ago
49
50 // Duration renders a non-negative duration in the compact form the web UI uses:
51 // seconds for short work, minutes and hours once it matters. Sub-second work is
52 // milliseconds, because a step that finished instantly should not read as "0s".
53 func Duration(d time.Duration) string {
54 if d <= 0 {
55 return "0s"
56 }
57 if d < time.Second {
58 return fmt.Sprintf("%dms", d.Milliseconds())
59 }
60 d = d.Round(time.Second)
61 h := d / time.Hour
62 d -= h * time.Hour
63 m := d / time.Minute
64 d -= m * time.Minute
65 s := d / time.Second
66 switch {
67 case h > 0 && m == 0 && s == 0:
68 return fmt.Sprintf("%dh", h)
69 case h > 0 && s == 0:
70 return fmt.Sprintf("%dh %dm", h, m)
71 case h > 0:
72 return fmt.Sprintf("%dh %dm %ds", h, m, s)
73 case m > 0 && s == 0:
74 return fmt.Sprintf("%dm", m)
75 case m > 0:
76 return fmt.Sprintf("%dm %ds", m, s)
77 default:
78 return fmt.Sprintf("%ds", s)
79 }
80 }