Skip to content

Commit 050259a

Browse files
committed
Compute usage from the sizes in the manifest.
This is a more accurate calculation of the files that were supplied by the user. In particular, it avoids counting the sizes of extra files that were added by the application, e.g., non-gobbler-related dotfiles.
1 parent 5d1edb7 commit 050259a

8 files changed

+106
-38
lines changed

delete.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func deleteAssetHandler(reqpath string, globals *globalConfiguration) error {
109109
if _, err := os.Stat(asset_dir); errors.Is(err, os.ErrNotExist) {
110110
return nil
111111
}
112-
to_free, err := computeUsage(asset_dir)
112+
to_free, err := computeAssetUsage(asset_dir)
113113
if err != nil {
114114
return fmt.Errorf("failed to compute usage for %s; %v", asset_dir, err)
115115
}
@@ -206,7 +206,7 @@ func deleteVersionHandler(reqpath string, globals *globalConfiguration) error {
206206
if _, err := os.Stat(version_dir); errors.Is(err, os.ErrNotExist) {
207207
return nil
208208
}
209-
to_free, err := computeUsage(version_dir)
209+
to_free, err := computeVersionUsage(version_dir)
210210
if err != nil {
211211
return fmt.Errorf("failed to compute usage for %s; %v", version_dir, err)
212212
}

delete_test.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ func mockRegistryForDeletion(project, asset string, versions []string) (string,
5353
return "", fmt.Errorf("failed to write a placeholder file; %w", err)
5454
}
5555
expected_size += len(message)
56+
57+
err = reindexDirectory(reg, project, asset, v)
58+
if err != nil {
59+
return "", fmt.Errorf("failed to reindex the directory; %w", err)
60+
}
5661
}
5762

5863
err = os.WriteFile(filepath.Join(project_dir, usageFileName), []byte(fmt.Sprintf(`{ "total": %d }`, expected_size)), 0644)
@@ -334,7 +339,7 @@ func TestDeleteVersion(t *testing.T) {
334339
if err != nil {
335340
t.Fatalf("failed to read usage after deletion; %v", err)
336341
}
337-
expected, err := computeUsage(filepath.Join(asset_dir, survivor))
342+
expected, err := computeVersionUsage(filepath.Join(asset_dir, survivor))
338343
if err != nil {
339344
t.Fatalf("failed to compute usage for the survivor; %v", err)
340345
}

probation.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ func baseProbationHandler(reqpath string, globals *globalConfiguration, approve
144144
}
145145

146146
} else {
147-
freed, err := computeUsage(version_dir)
147+
freed, err := computeVersionUsage(version_dir)
148148
if err != nil {
149149
return fmt.Errorf("failed to compute usage for %q; %w", version_dir, err)
150150
}

probation_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ func mockProbationVersion(reg, project, asset, version string) error {
5858
return fmt.Errorf("failed to create some mock files; %w", err)
5959
}
6060

61+
err = reindexDirectory(reg, project, asset, version)
62+
if err != nil {
63+
return fmt.Errorf("failed to reindex the directory; %w", err)
64+
}
65+
6166
err = os.WriteFile(filepath.Join(project_dir, usageFileName), []byte(fmt.Sprintf(`{ "total": %d }`, len(contents))), 0644)
6267
if err != nil {
6368
return fmt.Errorf("failed to create mock usage; %w", err)

upload.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ func uploadHandler(reqpath string, globals *globalConfiguration) error {
198198
}
199199

200200
{
201-
extra, err := computeUsage(version_dir)
201+
extra, err := computeVersionUsage(version_dir)
202202
if err != nil {
203203
return fmt.Errorf("failed to compute usage for the new version at %q; %w", version_dir, err)
204204
}

upload_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func TestUploadHandlerSimple(t *testing.T) {
128128
if err != nil {
129129
t.Fatalf("failed to read the usage; %v", err)
130130
}
131-
expected_usage, err := computeUsage(project_dir)
131+
expected_usage, err := computeProjectUsage(project_dir)
132132
if err != nil {
133133
t.Fatalf("failed to compute the expected usage; %v", err)
134134
}
@@ -382,7 +382,7 @@ func TestUploadHandlerUpdate(t *testing.T) {
382382
if err != nil {
383383
t.Fatalf("failed to read the usage; %v", err)
384384
}
385-
expected_usage, err := computeUsage(project_dir)
385+
expected_usage, err := computeProjectUsage(project_dir)
386386
if err != nil {
387387
t.Fatalf("failed to compute the expected usage; %v", err)
388388
}

usage.go

+55-22
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import (
44
"os"
55
"encoding/json"
66
"fmt"
7-
"io/fs"
8-
"strings"
97
"path/filepath"
108
"time"
119
"net/http"
@@ -34,37 +32,72 @@ func readUsage(path string) (*usageMetadata, error) {
3432
return &output, nil
3533
}
3634

37-
func computeUsage(dir string) (int64, error) {
35+
func computeProjectUsage(path string) (int64, error) {
3836
var total int64
3937
total = 0
4038

41-
err := filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
42-
if err != nil {
43-
return fmt.Errorf("failed to walk into %q; %w", path, err)
39+
assets, err := os.ReadDir(path)
40+
if err != nil {
41+
return total, fmt.Errorf("failed to list assets; %w", err)
42+
}
43+
44+
for _, aentry := range assets {
45+
if !aentry.IsDir() {
46+
continue
4447
}
4548

46-
if info.IsDir() {
47-
return nil
49+
asset := aentry.Name()
50+
asize, err := computeAssetUsage(filepath.Join(path, asset))
51+
if err != nil {
52+
return total, fmt.Errorf("failed to get usage for asset %q; %w", asset, err)
4853
}
4954

50-
// Skipping internal files.
51-
base := filepath.Base(path)
52-
if strings.HasPrefix(base, "..") {
53-
return nil
55+
total += asize
56+
}
57+
58+
return total, nil
59+
}
60+
61+
func computeAssetUsage(path string) (int64, error) {
62+
var total int64
63+
total = 0
64+
65+
versions, err := os.ReadDir(path)
66+
if err != nil {
67+
return total, fmt.Errorf("failed to list versions; %w", err)
68+
}
69+
70+
for _, ventry := range versions {
71+
if !ventry.IsDir() {
72+
continue
5473
}
5574

56-
// Skipping symlinks.
57-
restat, err := info.Info()
75+
version := ventry.Name()
76+
vsize, err := computeVersionUsage(filepath.Join(path, version))
5877
if err != nil {
59-
return fmt.Errorf("failed to stat %q; %w", path, err)
60-
}
61-
if restat.Mode() & os.ModeSymlink == os.ModeSymlink {
62-
return nil
78+
return total, fmt.Errorf("failed to get usage for version %q; %w", version, err)
6379
}
6480

65-
total += restat.Size()
66-
return nil
67-
})
81+
total += vsize
82+
}
83+
84+
return total, nil
85+
}
86+
87+
func computeVersionUsage(path string) (int64, error) {
88+
var total int64
89+
total = 0
90+
91+
man, err := readManifest(path)
92+
if err != nil {
93+
return total, fmt.Errorf("failed to open manifest; %w", err)
94+
}
95+
96+
for _, mm := range man {
97+
if mm.Link == nil {
98+
total += mm.Size
99+
}
100+
}
68101

69102
return total, err
70103
}
@@ -111,7 +144,7 @@ func refreshUsageHandler(reqpath string, globals *globalConfiguration) (*usageMe
111144
}
112145
defer globals.Locks.Unlock(project_dir)
113146

114-
new_usage, err := computeUsage(project_dir)
147+
new_usage, err := computeProjectUsage(project_dir)
115148
if err != nil {
116149
return nil, fmt.Errorf("failed to compute usage for %q; %w", *(incoming.Project), err)
117150
}

usage_test.go

+34-9
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,29 @@ func TestComputeUsage(t *testing.T) {
8282
t.Fatalf("failed to create mock file; %v", err)
8383
}
8484

85-
// Actually running some tests.
86-
total, err := computeUsage(src)
85+
// Executing the transfer and computing the size.
86+
reg, err := os.MkdirTemp("", "")
87+
if err != nil {
88+
t.Fatalf("failed to create the registry; %v", err)
89+
}
90+
91+
project := "pokemon"
92+
asset := "pikachu"
93+
version := "yellow"
94+
err = transferDirectory(src, reg, project, asset, version)
95+
if err != nil {
96+
t.Fatalf("failed to perform the transfer; %v", err)
97+
}
98+
99+
total, err := computeProjectUsage(filepath.Join(reg, project))
87100
if err != nil {
88101
t.Fatalf("failed to create compute usage; %v", err)
89102
}
90103
if total != int64(expected_size) {
91104
t.Fatalf("sum of file sizes is different from expected (%d, got %d)", expected_size, total)
92105
}
93106

107+
// Symlinks are ignored.
94108
err = os.Symlink(
95109
filepath.Join(src, "moves", "grass", "razor_leaf"),
96110
filepath.Join(src, "moves", "grass", "vine_whip"),
@@ -99,12 +113,19 @@ func TestComputeUsage(t *testing.T) {
99113
t.Fatalf("failed to create mock file; %v", err)
100114
}
101115

102-
total, err = computeUsage(src)
116+
version = "green"
117+
err = transferDirectory(src, reg, project, asset, version)
118+
if err != nil {
119+
t.Fatalf("failed to perform the transfer; %v", err)
120+
}
121+
122+
combined_total, err := computeProjectUsage(filepath.Join(reg, project))
103123
if err != nil {
104124
t.Fatalf("failed to create compute usage; %v", err)
105125
}
106-
if total != int64(expected_size) {
107-
t.Fatalf("sum of file sizes is different from expected (%d, got %d) when ignoring soft links", expected_size, total)
126+
total_added := combined_total - total
127+
if total_added != int64(expected_size) {
128+
t.Fatalf("sum of file sizes is different from expected (%d, got %d)", expected_size, total_added)
108129
}
109130
}
110131

@@ -125,18 +146,22 @@ func TestRefreshUsageHandler(t *testing.T) {
125146

126147
expected_size := int64(0)
127148
for _, asset := range []string{ "WHEE", "STUFF", "BLAH" } {
128-
version_dir := filepath.Join(project_dir, asset)
129-
err := os.Mkdir(version_dir, 0755)
149+
src, err := os.MkdirTemp("", "test-")
130150
if err != nil {
131-
t.Fatalf("failed to create asset directory; %v", err)
151+
t.Fatalf("failed to create tempdir; %v", err)
132152
}
133153

134154
message := "I am " + asset
135-
err = os.WriteFile(filepath.Join(version_dir, "thingy"), []byte(message), 0644)
155+
err = os.WriteFile(filepath.Join(src, "thingy"), []byte(message), 0644)
136156
if err != nil {
137157
t.Fatalf("failed to write a mock file; %v", err)
138158
}
139159

160+
err = transferDirectory(src, reg, project_name, asset, "v1")
161+
if err != nil {
162+
t.Fatalf("failed to perform the transfer; %v", err)
163+
}
164+
140165
expected_size += int64(len(message))
141166
}
142167

0 commit comments

Comments
 (0)