Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
162 commits
Select commit Hold shift + click to select a range
4830bfb
begin work on base subfeatures
GamerGirlandCo Aug 13, 2025
b9e3192
add group model
GamerGirlandCo Dec 25, 2024
8e9f511
create GroupList type and methods
GamerGirlandCo Dec 25, 2024
f9d91d0
add `Group` methods and helper functions
GamerGirlandCo Dec 25, 2024
0b2f0b8
add avatar to group
GamerGirlandCo Dec 28, 2024
ddf4bab
add `ParentGroup` field and related `LoadParentGroup` method to `Grou…
GamerGirlandCo Dec 28, 2024
1f7df59
add `GroupTeam` and `GroupUnit` structs and helpers
GamerGirlandCo Dec 28, 2024
802294e
add condition and builder functions to be used when searching for groups
GamerGirlandCo Dec 28, 2024
d721ba3
add `OwnerName` field to `Group` struct
GamerGirlandCo Dec 28, 2024
aea2cb6
rename `DisplayName` -> `FullName` for consistency
GamerGirlandCo Dec 28, 2024
4d8a4f5
add `IsPrivate` and `Visibility` fields to `Group` struct
GamerGirlandCo Dec 28, 2024
5d8163d
add `FindGroupsByCond` helper function
GamerGirlandCo Dec 28, 2024
98e1c40
fix nonexistent variable reference in `GetGroupByID` function
GamerGirlandCo Dec 28, 2024
2eed3df
add `GroupLink` method to `Group` struct
GamerGirlandCo Dec 28, 2024
f2d5ba4
add helper functions for dealing with group hierarchies
GamerGirlandCo Dec 28, 2024
4f12815
refactor subgroup loading, add method to load only groups accessible …
GamerGirlandCo Dec 28, 2024
4715355
register `GroupTeam` and `GroupUnit` models
GamerGirlandCo Dec 28, 2024
58fa0c3
add condition and builder functions to be used when searching for groups
GamerGirlandCo Dec 28, 2024
4bfd45c
changes
GamerGirlandCo Jan 9, 2025
d532525
update group model
GamerGirlandCo Jan 9, 2025
41a69b2
add `UserOrgTeamPermCond` function
GamerGirlandCo Jan 9, 2025
73450ed
add new fields and methods to `GroupTeam` model
GamerGirlandCo Jan 9, 2025
9c85531
update group_unit.go
GamerGirlandCo Jan 9, 2025
6417304
remove unused parameter from `Group.relAvatarLink` method
GamerGirlandCo Jan 9, 2025
2ffd043
[models] update repo model
GamerGirlandCo Jan 9, 2025
397776a
update repo_permission.go
GamerGirlandCo Jan 9, 2025
ac35709
add conversion functions for repository groups
GamerGirlandCo Jan 9, 2025
668c69f
add file with functions relating to organization teams and repo groups
GamerGirlandCo Jan 9, 2025
5a8dcff
update `team_list.go`
GamerGirlandCo Jan 9, 2025
962bb96
add group-related url segments to list of reserved usernames
GamerGirlandCo Jan 9, 2025
064410d
[models/search-options] add `GroupID` to `SearchRepoOptions`
GamerGirlandCo Jan 9, 2025
5f7ca5d
[models/conds] add functions returning builders to help find repos ma…
GamerGirlandCo Jan 10, 2025
985d433
[models/conds] update some repo conditions to check for access provid…
GamerGirlandCo Jan 10, 2025
ab1c7c7
[models] update `GetTeamRepositories` to also return repositories acc…
GamerGirlandCo Jan 10, 2025
3731740
[services] ensure `OwnerName` field is updated in groups owned by an …
GamerGirlandCo Jan 10, 2025
ea116e5
[misc] update avatar utils to handle group avatars
GamerGirlandCo Jan 10, 2025
8e0f17f
fix duplicate teams being returned by `GetTeamsWithAccessToGroup`
GamerGirlandCo Jul 20, 2025
26e2d2b
fix bug where all repos are returned even when `opts.GroupID` == 0
GamerGirlandCo Jul 20, 2025
9ffa9da
remove unused/redundant `IsPrivate` field from Group struct
GamerGirlandCo Aug 11, 2025
ec26ed0
add `UpdateGroup` function
GamerGirlandCo Aug 11, 2025
60e9c4e
[services] update `MoveGroupItem` function to set `newPos` to the len…
GamerGirlandCo Aug 11, 2025
51242fe
add missing nil check before `IsErrGroupNotExist` call
GamerGirlandCo Aug 13, 2025
c33292c
add test fixtures
GamerGirlandCo Aug 13, 2025
5095bfa
fix `no columns found to update` error when recalculating group access
GamerGirlandCo Aug 13, 2025
c6ad42f
add some unit tests for group service
GamerGirlandCo Aug 13, 2025
0f5b014
fix deadlock caused by differing contexts when retrieving group ances…
GamerGirlandCo Aug 13, 2025
0cac5be
add `GroupID` field to `CreateRepoOptions`
GamerGirlandCo Aug 13, 2025
8f9a764
fix build error caused by changed function name
GamerGirlandCo Aug 13, 2025
99663a0
add `GroupID` and `GroupSortOrder` fields to `Repository` api struct
GamerGirlandCo Aug 13, 2025
bbf16bd
fix more build errors
GamerGirlandCo Aug 13, 2025
07d5fd9
add api types for groups
GamerGirlandCo Aug 13, 2025
f63b092
fix a few more build errors
GamerGirlandCo Aug 13, 2025
6104973
regenerate swagger definitions
GamerGirlandCo Aug 13, 2025
42fb3bd
format files
GamerGirlandCo Aug 13, 2025
cb49e11
reapply changes wiped out by conflict resolution
GamerGirlandCo Aug 13, 2025
31159a4
add ownership check when moving repository to a new group
GamerGirlandCo Aug 13, 2025
c5b1603
apply simple linting changes
GamerGirlandCo Aug 13, 2025
36b48fc
apply simple linting changes
GamerGirlandCo Aug 13, 2025
f4d98d1
update repo service to check that `GroupID` is owned by the repo owne…
GamerGirlandCo Aug 14, 2025
bd52e2b
move parameters of the `MoveGroup` function into a struct, `MoveGroup…
GamerGirlandCo Aug 14, 2025
782cf2b
rename tables in group-related query conditions
GamerGirlandCo Aug 14, 2025
374605e
add api routes and functions for repository groups
GamerGirlandCo Aug 14, 2025
ee585c6
add `doer` parameter to `MoveGroupItem` describing the user trying to…
GamerGirlandCo Aug 14, 2025
d69d133
update `AccessibleGroupCondition` function to take a minimum `perm.Ac…
GamerGirlandCo Aug 14, 2025
b37e96a
remove bare return
GamerGirlandCo Aug 14, 2025
f1c6971
run formatter
GamerGirlandCo Aug 14, 2025
436150f
move group routes that don't depend on the `org` path parameter out o…
GamerGirlandCo Aug 14, 2025
bbe6b2b
add appropriate swagger definitions
GamerGirlandCo Aug 14, 2025
d8da055
refactor group creation such that we know the owner ID ahead of time,…
GamerGirlandCo Aug 14, 2025
8fe832d
fix swagger definition references to nonexistent `CreateGroupOption`
GamerGirlandCo Aug 14, 2025
06dbe0f
add api routes and functions to get a repository group's subgroups an…
GamerGirlandCo Aug 14, 2025
d8fd5a5
fix build errors
GamerGirlandCo Aug 14, 2025
91b804a
fix build and lint errors
GamerGirlandCo Aug 14, 2025
ba78004
fix failing tests ?
GamerGirlandCo Aug 14, 2025
a9b1ee8
ensure we return early if there was an error loading group units
GamerGirlandCo Aug 16, 2025
15accfc
fix bug where `builder.In` cond for groups and teams was not placed i…
GamerGirlandCo Aug 16, 2025
b235846
remove `UNIQUE` constraint on `Group.LowerName`
GamerGirlandCo Aug 16, 2025
5f57c39
add explicit `TEXT` type to `Group.LowerName` tag
GamerGirlandCo Aug 16, 2025
842767e
add/remove more constraints for mssql/mysql compatibility
GamerGirlandCo Aug 16, 2025
34a5589
rename test fixture files for group units and teams
GamerGirlandCo Aug 16, 2025
29f4bfb
fix more failing tests
GamerGirlandCo Aug 16, 2025
2d237cd
add indices to group_id and group_sort_order column
GamerGirlandCo Aug 17, 2025
0917cf9
add `AvatarURL` field to api groups (in `modules/structs` package)
GamerGirlandCo Aug 16, 2025
eac2684
update repository storage layout as per https://github.com/go-gitea/g…
GamerGirlandCo Aug 17, 2025
45e1ba5
update API routes as well
GamerGirlandCo Aug 17, 2025
28c9cd4
fix optional path segments not working out as planned
GamerGirlandCo Aug 18, 2025
dd93f76
update `FullName` method to show group id if it's non-zero
GamerGirlandCo Aug 18, 2025
4a5c502
add group ID column to repository table's unique constraint
GamerGirlandCo Aug 18, 2025
c569b0e
add group id segment to repository's `Link` method
GamerGirlandCo Aug 18, 2025
b19f535
fix broken hooks
GamerGirlandCo Aug 18, 2025
90f5812
make it more apparent in URLs that a repo is part of a group
GamerGirlandCo Aug 18, 2025
fdc11b1
fix broken hooks (again)
GamerGirlandCo Aug 18, 2025
4ec7e39
ensure that repository is moved on disk in `MoveGroupItem` function
GamerGirlandCo Aug 18, 2025
be3b1ae
fix moving items to the root-level (`GroupID` <= 0)
GamerGirlandCo Aug 18, 2025
448b72b
fix bug where a repo's group id and group sort order are zero in API …
GamerGirlandCo Aug 22, 2025
45285b3
ensure visited repo's group owner is the same as the repo's owner, ot…
GamerGirlandCo Aug 22, 2025
9bb8131
chore: update makefile and add new tool
GamerGirlandCo Nov 21, 2025
47730bc
sync with main
GamerGirlandCo Nov 22, 2025
4341844
fix compile errors in migrations
GamerGirlandCo Nov 22, 2025
5865ced
update `serv` command to recognize group ids in urls
GamerGirlandCo Nov 22, 2025
e7b4182
update integration test utilities to tage group id as argument
GamerGirlandCo Nov 22, 2025
8133dff
update calls to `GetRepositoryByName` to use new signature
GamerGirlandCo Nov 22, 2025
f5ef932
update swagger definitions
GamerGirlandCo Nov 22, 2025
6b9e5c7
fix swagger comments in repo adoption routes
GamerGirlandCo Nov 22, 2025
2765699
add missing group id parameters to test function calls
GamerGirlandCo Nov 22, 2025
bdedab3
run formatter
GamerGirlandCo Nov 22, 2025
1d9147a
remove references to `db.DefaultContext`
GamerGirlandCo Nov 22, 2025
54817d4
appease the linter
GamerGirlandCo Nov 22, 2025
6862b13
fix `groupSegmentWithTrailingSlash` to return an empty string if gid …
GamerGirlandCo Nov 22, 2025
6688d0c
update activity actions to return paths/links with a repo's group
GamerGirlandCo Nov 23, 2025
d8e1fb9
add trailing newline when generating swagger group routes
GamerGirlandCo Nov 23, 2025
9fb36bf
update v1_groups.json
GamerGirlandCo Nov 23, 2025
4854e5f
fix wrong group in issue xref test
GamerGirlandCo Nov 23, 2025
87b7dfb
update group swagger definitions
GamerGirlandCo Nov 23, 2025
8cd5495
fix determinism of repo group swagger output
GamerGirlandCo Nov 23, 2025
ba15053
fix issue reference regex
GamerGirlandCo Nov 23, 2025
2b58fbc
move dummy repositories to proper subgroup directories
GamerGirlandCo Nov 23, 2025
2c641ee
fix mssql migrations
GamerGirlandCo Nov 23, 2025
0f388e3
fix repo url parsing
GamerGirlandCo Nov 23, 2025
eeb24e1
add missing repo meta for group unit tests
GamerGirlandCo Nov 23, 2025
f662e8d
remove redundant return value from `fillPathParts`
GamerGirlandCo Nov 23, 2025
c51ee50
fix repo url parsing (again)
GamerGirlandCo Nov 23, 2025
0e97e12
fix moving repos to a different subgroup
GamerGirlandCo Nov 23, 2025
bb38e71
fix transfers of repos in subgroups
GamerGirlandCo Nov 23, 2025
93a543f
fix more regex patterns
GamerGirlandCo Nov 23, 2025
1410bac
fix failing test in issue_xref_test.go
GamerGirlandCo Nov 24, 2025
4201734
fix integration test api urls
GamerGirlandCo Nov 24, 2025
f005a36
fix artifact download endpoint urls
GamerGirlandCo Nov 24, 2025
fda4f6a
add missing copyright
GamerGirlandCo Nov 24, 2025
64487cb
fix `maybeGroupSegment` func, run formatter
GamerGirlandCo Nov 24, 2025
b5f4d42
fix unique constraints for repos and subgroups
GamerGirlandCo Nov 24, 2025
f21a2c4
fix helm package test
GamerGirlandCo Nov 24, 2025
18a9cb8
sync csv test with upstream
GamerGirlandCo Nov 24, 2025
69cfcff
add GroupID field to IssueMeta struct
GamerGirlandCo Nov 24, 2025
2241edb
fix issue dependency tests
GamerGirlandCo Nov 24, 2025
6220463
add team-related routes for repos in subgroups
GamerGirlandCo Nov 24, 2025
6f25ae8
fix repository renaming
GamerGirlandCo Nov 24, 2025
f2b3042
fix more tests
GamerGirlandCo Nov 24, 2025
99aed1b
fix go-get import paths
GamerGirlandCo Nov 24, 2025
0aecfd0
update swagger definitions
GamerGirlandCo Nov 24, 2025
cd53ff8
fix hook url
GamerGirlandCo Nov 25, 2025
993d5db
add missing serv route
GamerGirlandCo Nov 25, 2025
69c630d
set hooks to be executable
GamerGirlandCo Nov 25, 2025
90127fc
reorder serv routes
GamerGirlandCo Nov 25, 2025
9b89d9c
fix permissions on some test repos
GamerGirlandCo Nov 25, 2025
9aee0f0
fix more tests
GamerGirlandCo Nov 25, 2025
72286bf
use a custom ordered map to create group swagger mixin
GamerGirlandCo Nov 26, 2025
d776a9c
fix repo api url
GamerGirlandCo Nov 26, 2025
0df6308
fix remaining tests
GamerGirlandCo Nov 26, 2025
3f19a50
update swagger definitions
GamerGirlandCo Nov 26, 2025
5fac8cc
fix remaining tests
GamerGirlandCo Nov 26, 2025
fd0a44b
fix repo api url
GamerGirlandCo Nov 26, 2025
401c487
fix a couple more tests
GamerGirlandCo Nov 26, 2025
7ef7355
update swagger tool
GamerGirlandCo Nov 26, 2025
2656444
more test fixes
GamerGirlandCo Nov 26, 2025
e4a97b8
fix permissions on web issue routes
GamerGirlandCo Nov 26, 2025
7695c7c
fix org test
GamerGirlandCo Nov 26, 2025
4b061a1
add group id to file comparison urls
GamerGirlandCo Nov 26, 2025
9afaef7
fix more test urls
GamerGirlandCo Nov 26, 2025
4f447bf
move test repo 21 to different subgroup
GamerGirlandCo Nov 26, 2025
245d33e
fix org repo test
GamerGirlandCo Nov 26, 2025
a0edeb8
revert changes to cases in `org_test.go`
GamerGirlandCo Nov 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ endif

SWAGGER_SPEC := templates/swagger/v1_json.tmpl
SWAGGER_SPEC_INPUT := templates/swagger/v1_input.json
SWAGGER_SPEC_GROUP_INPUT := templates/swagger/v1_groups.json
SWAGGER_EXCLUDE := code.gitea.io/sdk

TEST_MYSQL_HOST ?= mysql:3306
Expand Down Expand Up @@ -293,6 +294,8 @@ generate-swagger: $(SWAGGER_SPEC) ## generate the swagger spec from code comment

$(SWAGGER_SPEC): $(GO_SOURCES) $(SWAGGER_SPEC_INPUT)
$(GO) run $(SWAGGER_PACKAGE) generate spec --exclude "$(SWAGGER_EXCLUDE)" --input "$(SWAGGER_SPEC_INPUT)" --output './$(SWAGGER_SPEC)'
$(GO) generate -v ./build_tools/...
$(GO) run $(SWAGGER_PACKAGE) mixin -o './$(SWAGGER_SPEC)' $(SWAGGER_SPEC) $(SWAGGER_SPEC_GROUP_INPUT)

.PHONY: swagger-check
swagger-check: generate-swagger
Expand Down
306 changes: 306 additions & 0 deletions build_tools/swagger/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:generate go run main.go ../../

package main

import (
"bytes"
encjson "encoding/json" //nolint:depguard // this package wraps it
"errors"
"fmt"
"iter"
"log"
"os"
"path/filepath"
"regexp"

"code.gitea.io/gitea/modules/json"
)

type Pair struct {
Key string
Value any
}

type OrderedMap struct {
Pairs []Pair
indices map[string]int
}

func (o OrderedMap) Get(key string) (any, bool) {
if _, ok := o.indices[key]; ok {
return o.Pairs[o.indices[key]].Value, true
}
return nil, false
}

func (o *OrderedMap) Set(key string, value any) {
if _, ok := o.indices[key]; ok {
o.Pairs[o.indices[key]] = Pair{key, value}
} else {
o.Pairs = append(o.Pairs, Pair{key, value})
o.indices[key] = len(o.Pairs) - 1
}
}

func (o OrderedMap) Iter() iter.Seq2[string, any] {
return func(yield func(string, any) bool) {
for _, it := range o.Pairs {
yield(it.Key, it.Value)
}
}
}

func (o *OrderedMap) UnmarshalJSON(data []byte) error {
trimmed := bytes.TrimSpace(data)
if bytes.Equal(trimmed, []byte("null")) {
o.Pairs = nil
o.indices = nil
return nil
}

dec := encjson.NewDecoder(bytes.NewReader(data))
dec.UseNumber()

tok, err := dec.Token()
if err != nil {
return err
}
delim, ok := tok.(encjson.Delim)
if !ok || delim != '{' {
return errors.New("OrderedMap: expected '{' at start of object")
}

// Reset storage
if o.indices == nil {
o.indices = make(map[string]int)
} else {
for k := range o.indices {
delete(o.indices, k)
}
}
o.Pairs = o.Pairs[:0]

for dec.More() {
tk, err := dec.Token()
if err != nil {
return err
}
key, ok := tk.(string)
if !ok {
return fmt.Errorf(
"OrderedMap: expected string key, got %T (%v)",
tk,
tk,
)
}

var raw encjson.RawMessage
if err := dec.Decode(&raw); err != nil {
return fmt.Errorf("OrderedMap: decode value for %q: %w", key, err)
}

val, err := decodeJSONValue(raw)
if err != nil {
return fmt.Errorf("OrderedMap: unmarshal value for %q: %w", key, err)
}

if idx, exists := o.indices[key]; exists {
o.Pairs[idx].Value = val
} else {
o.indices[key] = len(o.Pairs)
o.Pairs = append(o.Pairs, Pair{Key: key, Value: val})
}
}

end, err := dec.Token()
if err != nil {
return err
}
if d, ok := end.(encjson.Delim); !ok || d != '}' {
return errors.New("OrderedMap: expected '}' at end of object")
}

return nil
}

func decodeJSONValue(raw encjson.RawMessage) (any, error) {
t := bytes.TrimSpace(raw)
if bytes.Equal(t, []byte("null")) {
return nil, nil
}

d := encjson.NewDecoder(bytes.NewReader(raw))
d.UseNumber()

tok, err := d.Token()
if err != nil {
return nil, err
}

switch tt := tok.(type) {
case encjson.Delim:
switch tt {
case '{':
var inner OrderedMap
if err := inner.UnmarshalJSON(raw); err != nil {
return nil, err
}
return inner, nil
case '[':
var arr []any
for d.More() {
var elemRaw encjson.RawMessage
if err := d.Decode(&elemRaw); err != nil {
return nil, err
}
v, err := decodeJSONValue(elemRaw)
if err != nil {
return nil, err
}
arr = append(arr, v)
}
if end, err := d.Token(); err != nil {
return nil, err
} else if end != encjson.Delim(']') {
return nil, errors.New("expected ']'")
}
return arr, nil
default:
return nil, fmt.Errorf("unexpected delimiter %q", tt)
}
default:
var v any
d = encjson.NewDecoder(bytes.NewReader(raw))
d.UseNumber()
if err := d.Decode(&v); err != nil {
return nil, err
}
return v, nil
}
}

func (o OrderedMap) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer

buf.WriteString("{")
for i, kv := range o.Pairs {
if i != 0 {
buf.WriteString(",")
}
key, err := json.Marshal(kv.Key)
if err != nil {
return nil, err
}
buf.Write(key)
buf.WriteString(":")
val, err := json.Marshal(kv.Value)
if err != nil {
return nil, err
}
buf.Write(val)
}

buf.WriteString("}")
return buf.Bytes(), nil
}

var rxPath = regexp.MustCompile(`(?m)^(/repos/\{owner})/(\{repo})`)

func generatePaths(root string) *OrderedMap {
pathData := &OrderedMap{
indices: make(map[string]int),
}
endpoints := &OrderedMap{
indices: make(map[string]int),
}
fileToRead, err := filepath.Rel(root, "./templates/swagger/v1_json.tmpl")
if err != nil {
log.Fatal(err)
}
swaggerBytes, err := os.ReadFile(fileToRead)
if err != nil {
log.Fatal(err)
}
raw := OrderedMap{
indices: make(map[string]int),
}
err = json.Unmarshal(swaggerBytes, &raw)
if err != nil {
log.Fatal(err)
}
rpaths, has := raw.Get("paths")
if !has {
log.Fatal("paths not found")
}
paths := rpaths.(OrderedMap)
for k, v := range paths.Iter() {
if !rxPath.MatchString(k) {
// skip if this endpoint does not start with `/repos/{owner}/{repo}`
continue
}
// generate new endpoint path with `/group/{group_id}` in between the `owner` and `repo` params
nk := rxPath.ReplaceAllString(k, "$1/group/{group_id}/$2")
methodMap := v.(OrderedMap)

for method, methodSpec := range methodMap.Iter() {
specMap := methodSpec.(OrderedMap)
var params []OrderedMap
aparams, has := specMap.Get("parameters")
if !has {
continue
}
rparams := aparams.([]any)
for _, rparam := range rparams {
params = append(params, rparam.(OrderedMap))
}
param := OrderedMap{
indices: make(map[string]int),
}
param.Set("description", "group ID of the repo")
param.Set("name", "group_id")
param.Set("type", "integer")
param.Set("format", "int64")
param.Set("required", true)
param.Set("in", "path")
params = append(params, param)
// i believe for...range loops create copies of each item that's iterated over,
// so we need to take extra care to ensure we're mutating the original map entry
specMap.Set("parameters", params)
methodMap.Set(method, specMap)
//(methodMap[method].(map[string]any))["parameters"] = params
}
endpoints.Set(nk, methodMap)
}
pathData.Set("paths", endpoints)
return pathData
}

func writeMapToFile(filename string, data *OrderedMap) {
bytes, err := json.MarshalIndent(data, "", " ")
if err != nil {
log.Fatal(err)
}
bytes = append(bytes, '\n')
err = os.WriteFile(filename, bytes, 0o666)
if err != nil {
log.Fatal(err)
}
}

func main() {
var err error
root := "../../"
if len(os.Args) > 1 {
root = os.Args[1]
}
err = os.Chdir(root)
if err != nil {
log.Fatal(err)
}

pathData := generatePaths(".")
out := "./templates/swagger/v1_groups.json"
writeMapToFile(out, pathData)
}
Loading