loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

chore: teach `set` module about `iter.Seq` (#6676)

- Add a new `Seq` function to the `Set` type, this returns an iterator over the values.
- Convert some users of the `Values` method to allow for more optimal code.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6676
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Gusted <postmaster@gusted.xyz>

authored by

Gusted
Gusted
and committed by
Earl Warren
443f7d59 46e60ce9

+38 -28
+1 -1
cmd/web.go
··· 195 195 publicFilesSet.Remove(".well-known") 196 196 publicFilesSet.Remove("assets") 197 197 publicFilesSet.Remove("robots.txt") 198 - for _, fn := range publicFilesSet.Values() { 198 + for fn := range publicFilesSet.Seq() { 199 199 log.Error("Found legacy public asset %q in CustomPath. Please move it to %s/public/assets/%s", fn, setting.CustomPath, fn) 200 200 } 201 201 if _, err := os.Stat(filepath.Join(setting.CustomPath, "robots.txt")); err == nil {
+2 -2
models/user/user_test.go
··· 715 715 // no features should be disabled with a plain login type 716 716 assert.LessOrEqual(t, user.LoginType, auth.Plain) 717 717 assert.Empty(t, user_model.DisabledFeaturesWithLoginType(user).Values()) 718 - for _, f := range testValues.Values() { 718 + for f := range testValues.Seq() { 719 719 assert.False(t, user_model.IsFeatureDisabledWithLoginType(user, f)) 720 720 } 721 721 ··· 724 724 725 725 // all features should be disabled 726 726 assert.NotEmpty(t, user_model.DisabledFeaturesWithLoginType(user).Values()) 727 - for _, f := range testValues.Values() { 727 + for f := range testValues.Seq() { 728 728 assert.True(t, user_model.IsFeatureDisabledWithLoginType(user, f)) 729 729 } 730 730 }
+3 -5
modules/assetfs/layered.go
··· 11 11 "net/http" 12 12 "os" 13 13 "path/filepath" 14 - "sort" 14 + "slices" 15 15 "time" 16 16 17 17 "code.gitea.io/gitea/modules/container" ··· 143 143 } 144 144 } 145 145 } 146 - files := fileSet.Values() 147 - sort.Strings(files) 146 + files := slices.Sorted(fileSet.Seq()) 148 147 return files, nil 149 148 } 150 149 ··· 184 183 if err := list(name); err != nil { 185 184 return nil, err 186 185 } 187 - files := fileSet.Values() 188 - sort.Strings(files) 186 + files := slices.Sorted(fileSet.Seq()) 189 187 return files, nil 190 188 } 191 189
+11
modules/container/set.go
··· 3 3 4 4 package container 5 5 6 + import ( 7 + "iter" 8 + "maps" 9 + ) 10 + 6 11 type Set[T comparable] map[T]struct{} 7 12 8 13 // SetOf creates a set and adds the specified elements to it. ··· 63 68 } 64 69 return keys 65 70 } 71 + 72 + // Seq returns a iterator over the elements in the set. 73 + // It returns a single-use iterator. 74 + func (s Set[T]) Seq() iter.Seq[T] { 75 + return maps.Keys(s) 76 + }
+9
modules/container/set_test.go
··· 4 4 package container 5 5 6 6 import ( 7 + "slices" 7 8 "testing" 8 9 9 10 "github.com/stretchr/testify/assert" ··· 28 29 s.AddMultiple("key4", "key5") 29 30 assert.True(t, s.Contains("key4")) 30 31 assert.True(t, s.Contains("key5")) 32 + 33 + values := s.Values() 34 + called := 0 35 + for value := range s.Seq() { 36 + called++ 37 + assert.True(t, slices.Contains(values, value)) 38 + } 39 + assert.EqualValues(t, len(values), called) 31 40 32 41 s = SetOf("key6", "key7") 33 42 assert.False(t, s.Contains("key1"))
-8
modules/util/slice.go
··· 4 4 package util 5 5 6 6 import ( 7 - "cmp" 8 7 "slices" 9 8 "strings" 10 9 ) ··· 45 44 // SliceRemoveAll removes all the target elements from the slice. 46 45 func SliceRemoveAll[T comparable](slice []T, target T) []T { 47 46 return slices.DeleteFunc(slice, func(t T) bool { return t == target }) 48 - } 49 - 50 - // Sorted returns the sorted slice 51 - // Note: The parameter is sorted inline. 52 - func Sorted[S ~[]E, E cmp.Ordered](values S) S { 53 - slices.Sort(values) 54 - return values 55 47 } 56 48 57 49 // TODO: Replace with "maps.Values" once available, current it only in golang.org/x/exp/maps but not in standard library
+10 -10
routers/web/user/package.go
··· 6 6 import ( 7 7 "fmt" 8 8 "net/http" 9 + "slices" 9 10 10 11 "code.gitea.io/gitea/models/db" 11 12 org_model "code.gitea.io/gitea/models/organization" ··· 23 24 debian_module "code.gitea.io/gitea/modules/packages/debian" 24 25 rpm_module "code.gitea.io/gitea/modules/packages/rpm" 25 26 "code.gitea.io/gitea/modules/setting" 26 - "code.gitea.io/gitea/modules/util" 27 27 "code.gitea.io/gitea/modules/web" 28 28 packages_helper "code.gitea.io/gitea/routers/api/packages/helper" 29 29 shared_user "code.gitea.io/gitea/routers/web/shared/user" ··· 200 200 } 201 201 } 202 202 203 - ctx.Data["Branches"] = util.Sorted(branches.Values()) 204 - ctx.Data["Repositories"] = util.Sorted(repositories.Values()) 205 - ctx.Data["Architectures"] = util.Sorted(architectures.Values()) 203 + ctx.Data["Branches"] = slices.Sorted(branches.Seq()) 204 + ctx.Data["Repositories"] = slices.Sorted(repositories.Seq()) 205 + ctx.Data["Architectures"] = slices.Sorted(architectures.Seq()) 206 206 case packages_model.TypeArch: 207 207 ctx.Data["SignMail"] = fmt.Sprintf("%s@noreply.%s", ctx.Package.Owner.Name, setting.Packages.RegistryHost) 208 208 groups := make(container.Set[string]) ··· 213 213 } 214 214 } 215 215 } 216 - ctx.Data["Groups"] = util.Sorted(groups.Values()) 216 + ctx.Data["Groups"] = slices.Sorted(groups.Seq()) 217 217 case packages_model.TypeDebian: 218 218 distributions := make(container.Set[string]) 219 219 components := make(container.Set[string]) ··· 232 232 } 233 233 } 234 234 235 - ctx.Data["Distributions"] = util.Sorted(distributions.Values()) 236 - ctx.Data["Components"] = util.Sorted(components.Values()) 237 - ctx.Data["Architectures"] = util.Sorted(architectures.Values()) 235 + ctx.Data["Distributions"] = slices.Sorted(distributions.Seq()) 236 + ctx.Data["Components"] = slices.Sorted(components.Seq()) 237 + ctx.Data["Architectures"] = slices.Sorted(architectures.Seq()) 238 238 case packages_model.TypeRpm, packages_model.TypeAlt: 239 239 groups := make(container.Set[string]) 240 240 architectures := make(container.Set[string]) ··· 250 250 } 251 251 } 252 252 253 - ctx.Data["Groups"] = util.Sorted(groups.Values()) 254 - ctx.Data["Architectures"] = util.Sorted(architectures.Values()) 253 + ctx.Data["Groups"] = slices.Sorted(groups.Seq()) 254 + ctx.Data["Architectures"] = slices.Sorted(architectures.Seq()) 255 255 } 256 256 257 257 var (
+1 -1
services/packages/alt/repository.go
··· 711 711 architectures.Add(pd.FileMetadata.Architecture) 712 712 } 713 713 714 - for architecture := range architectures { 714 + for architecture := range architectures.Seq() { 715 715 version := time.Now().Unix() 716 716 label := setting.AppName 717 717 data := fmt.Sprintf(`Archive: Alt Linux Team
+1 -1
services/release/release.go
··· 372 372 return err 373 373 } 374 374 375 - for _, uuid := range delAttachmentUUIDs.Values() { 375 + for uuid := range delAttachmentUUIDs.Seq() { 376 376 if err := storage.Attachments.Delete(repo_model.AttachmentRelativePath(uuid)); err != nil { 377 377 // Even delete files failed, but the attachments has been removed from database, so we 378 378 // should not return error but only record the error on logs.