|
5 | 5 | "encoding/json" |
6 | 6 | "errors" |
7 | 7 | "fmt" |
8 | | - "io" |
9 | 8 | "net/http" |
10 | 9 | "os" |
11 | 10 | "path/filepath" |
@@ -43,64 +42,6 @@ func NewOciClient(credentialStore *CredentialStore) *OciClient { |
43 | 42 | } |
44 | 43 | } |
45 | 44 |
|
46 | | -func formatBytes(b int64) string { |
47 | | - const ( |
48 | | - kb = 1024 |
49 | | - mb = kb * 1024 |
50 | | - gb = mb * 1024 |
51 | | - ) |
52 | | - switch { |
53 | | - case b >= gb: |
54 | | - return fmt.Sprintf("%.2f GB", float64(b)/float64(gb)) |
55 | | - case b >= mb: |
56 | | - return fmt.Sprintf("%.2f MB", float64(b)/float64(mb)) |
57 | | - case b >= kb: |
58 | | - return fmt.Sprintf("%.2f KB", float64(b)/float64(kb)) |
59 | | - default: |
60 | | - return fmt.Sprintf("%d B", b) |
61 | | - } |
62 | | -} |
63 | | - |
64 | | -type progressReader struct { |
65 | | - inner io.Reader |
66 | | - transferred *atomic.Int64 |
67 | | -} |
68 | | - |
69 | | -func (r *progressReader) Read(p []byte) (int, error) { |
70 | | - n, err := r.inner.Read(p) |
71 | | - if n > 0 { |
72 | | - r.transferred.Add(int64(n)) |
73 | | - } |
74 | | - return n, err |
75 | | -} |
76 | | - |
77 | | -func startProgressTicker(direction string, bytesTransferred *atomic.Int64, totalBytes *atomic.Int64, layersDone *atomic.Int64, totalLayers *atomic.Int64) func() { |
78 | | - ticker := time.NewTicker(60 * time.Second) |
79 | | - done := make(chan struct{}) |
80 | | - go func() { |
81 | | - for { |
82 | | - select { |
83 | | - case <-ticker.C: |
84 | | - transferred := bytesTransferred.Load() |
85 | | - total := totalBytes.Load() |
86 | | - layers := layersDone.Load() |
87 | | - layerTotal := totalLayers.Load() |
88 | | - logger.Log().Info(fmt.Sprintf("%s progress", direction), |
89 | | - zap.String("transferred", formatBytes(transferred)), |
90 | | - zap.String("total", formatBytes(total)), |
91 | | - zap.String("layers", fmt.Sprintf("%d/%d", layers, layerTotal)), |
92 | | - ) |
93 | | - case <-done: |
94 | | - return |
95 | | - } |
96 | | - } |
97 | | - }() |
98 | | - return func() { |
99 | | - ticker.Stop() |
100 | | - close(done) |
101 | | - } |
102 | | -} |
103 | | - |
104 | 45 | func (c *OciClient) GetRepo(repoUrl string) (*remote.Repository, error) { |
105 | 46 | repo, err := remote.NewRepository(repoUrl) |
106 | 47 | if err != nil { |
@@ -316,7 +257,7 @@ func (c *OciClient) PullSelective(dir string, artifact string, includeData bool, |
316 | 257 | }, |
317 | 258 | } |
318 | 259 |
|
319 | | - stopProgress := startProgressTicker("Download", &bytesDownloaded, &totalPullBytes, &completed, &totalLayers) |
| 260 | + stopProgress := utils.StartTransferProgressTicker("Download", &bytesDownloaded, &totalPullBytes, &completed, &totalLayers) |
320 | 261 |
|
321 | 262 | // Use a constant destination reference for the local file store so digest references |
322 | 263 | // (which contain ':' and other characters) don't become a tag key. |
@@ -454,7 +395,7 @@ func pushBlobWithRetry(ctx context.Context, src *file.Store, dst *remote.Reposit |
454 | 395 | return false, fmt.Errorf("failed to read local blob: %w", err) |
455 | 396 | } |
456 | 397 |
|
457 | | - pr := &progressReader{inner: rc, transferred: bytesUploaded} |
| 398 | + pr := utils.NewCountingReader(rc, bytesUploaded) |
458 | 399 | err = dst.Push(ctx, desc, pr) |
459 | 400 | rc.Close() |
460 | 401 | if err == nil { |
@@ -503,7 +444,7 @@ func copyToRegistry(ctx context.Context, fs *file.Store, repo *remote.Repository |
503 | 444 | var totalLayers atomic.Int64 |
504 | 445 | totalLayers.Store(int64(len(layers))) |
505 | 446 |
|
506 | | - stopProgress := startProgressTicker("Upload", &bytesUploaded, &totalBytes, &completed, &totalLayers) |
| 447 | + stopProgress := utils.StartTransferProgressTicker("Upload", &bytesUploaded, &totalBytes, &completed, &totalLayers) |
507 | 448 |
|
508 | 449 | for _, desc := range layers { |
509 | 450 | title := desc.Annotations["org.opencontainers.image.title"] |
|
0 commit comments