Skip to content

Commit c188e31

Browse files
authored
Merge branch 'main' into lunny/missing_translate
2 parents 481b6ae + 30b1394 commit c188e31

File tree

8 files changed

+123
-51
lines changed

8 files changed

+123
-51
lines changed

models/unittest/fixtures_loader.go

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@ import (
1212
"slices"
1313
"strings"
1414

15+
"code.gitea.io/gitea/models/db"
16+
1517
"gopkg.in/yaml.v3"
1618
"xorm.io/xorm"
1719
"xorm.io/xorm/schemas"
1820
)
1921

20-
type fixtureItem struct {
21-
tableName string
22+
type FixtureItem struct {
23+
fileFullPath string
24+
tableName string
25+
2226
tableNameQuoted string
2327
sqlInserts []string
2428
sqlInsertArgs [][]any
@@ -27,10 +31,11 @@ type fixtureItem struct {
2731
}
2832

2933
type fixturesLoaderInternal struct {
34+
xormEngine *xorm.Engine
35+
xormTableNames map[string]bool
3036
db *sql.DB
3137
dbType schemas.DBType
32-
files []string
33-
fixtures map[string]*fixtureItem
38+
fixtures map[string]*FixtureItem
3439
quoteObject func(string) string
3540
paramPlaceholder func(idx int) string
3641
}
@@ -59,29 +64,27 @@ func (f *fixturesLoaderInternal) preprocessFixtureRow(row []map[string]any) (err
5964
return nil
6065
}
6166

62-
func (f *fixturesLoaderInternal) prepareFixtureItem(file string) (_ *fixtureItem, err error) {
63-
fixture := &fixtureItem{}
64-
fixture.tableName, _, _ = strings.Cut(filepath.Base(file), ".")
67+
func (f *fixturesLoaderInternal) prepareFixtureItem(fixture *FixtureItem) (err error) {
6568
fixture.tableNameQuoted = f.quoteObject(fixture.tableName)
6669

6770
if f.dbType == schemas.MSSQL {
6871
fixture.mssqlHasIdentityColumn, err = f.mssqlTableHasIdentityColumn(f.db, fixture.tableName)
6972
if err != nil {
70-
return nil, err
73+
return err
7174
}
7275
}
7376

74-
data, err := os.ReadFile(file)
77+
data, err := os.ReadFile(fixture.fileFullPath)
7578
if err != nil {
76-
return nil, fmt.Errorf("failed to read file %q: %w", file, err)
79+
return fmt.Errorf("failed to read file %q: %w", fixture.fileFullPath, err)
7780
}
7881

7982
var rows []map[string]any
8083
if err = yaml.Unmarshal(data, &rows); err != nil {
81-
return nil, fmt.Errorf("failed to unmarshal yaml data from %q: %w", file, err)
84+
return fmt.Errorf("failed to unmarshal yaml data from %q: %w", fixture.fileFullPath, err)
8285
}
8386
if err = f.preprocessFixtureRow(rows); err != nil {
84-
return nil, fmt.Errorf("failed to preprocess fixture rows from %q: %w", file, err)
87+
return fmt.Errorf("failed to preprocess fixture rows from %q: %w", fixture.fileFullPath, err)
8588
}
8689

8790
var sqlBuf []byte
@@ -107,16 +110,14 @@ func (f *fixturesLoaderInternal) prepareFixtureItem(file string) (_ *fixtureItem
107110
sqlBuf = sqlBuf[:0]
108111
sqlArguments = sqlArguments[:0]
109112
}
110-
return fixture, nil
113+
return nil
111114
}
112115

113-
func (f *fixturesLoaderInternal) loadFixtures(tx *sql.Tx, file string) (err error) {
114-
fixture := f.fixtures[file]
115-
if fixture == nil {
116-
if fixture, err = f.prepareFixtureItem(file); err != nil {
116+
func (f *fixturesLoaderInternal) loadFixtures(tx *sql.Tx, fixture *FixtureItem) (err error) {
117+
if fixture.tableNameQuoted == "" {
118+
if err = f.prepareFixtureItem(fixture); err != nil {
117119
return err
118120
}
119-
f.fixtures[file] = fixture
120121
}
121122

122123
_, err = tx.Exec(fmt.Sprintf("DELETE FROM %s", fixture.tableNameQuoted)) // sqlite3 doesn't support truncate
@@ -147,15 +148,26 @@ func (f *fixturesLoaderInternal) Load() error {
147148
}
148149
defer func() { _ = tx.Rollback() }()
149150

150-
for _, file := range f.files {
151-
if err := f.loadFixtures(tx, file); err != nil {
152-
return fmt.Errorf("failed to load fixtures from %s: %w", file, err)
151+
for _, fixture := range f.fixtures {
152+
if !f.xormTableNames[fixture.tableName] {
153+
continue
154+
}
155+
if err := f.loadFixtures(tx, fixture); err != nil {
156+
return fmt.Errorf("failed to load fixtures from %s: %w", fixture.fileFullPath, err)
153157
}
154158
}
155-
return tx.Commit()
159+
if err = tx.Commit(); err != nil {
160+
return err
161+
}
162+
for xormTableName := range f.xormTableNames {
163+
if f.fixtures[xormTableName] == nil {
164+
_, _ = f.xormEngine.Exec("DELETE FROM `" + xormTableName + "`")
165+
}
166+
}
167+
return nil
156168
}
157169

158-
func FixturesFileFullPaths(dir string, files []string) ([]string, error) {
170+
func FixturesFileFullPaths(dir string, files []string) (map[string]*FixtureItem, error) {
159171
if files != nil && len(files) == 0 {
160172
return nil, nil // load nothing
161173
}
@@ -169,20 +181,25 @@ func FixturesFileFullPaths(dir string, files []string) ([]string, error) {
169181
files = append(files, e.Name())
170182
}
171183
}
172-
for i, file := range files {
173-
if !filepath.IsAbs(file) {
174-
files[i] = filepath.Join(dir, file)
184+
fixtureItems := map[string]*FixtureItem{}
185+
for _, file := range files {
186+
fileFillPath := file
187+
if !filepath.IsAbs(fileFillPath) {
188+
fileFillPath = filepath.Join(dir, file)
175189
}
190+
tableName, _, _ := strings.Cut(filepath.Base(file), ".")
191+
fixtureItems[tableName] = &FixtureItem{fileFullPath: fileFillPath, tableName: tableName}
176192
}
177-
return files, nil
193+
return fixtureItems, nil
178194
}
179195

180196
func NewFixturesLoader(x *xorm.Engine, opts FixturesOptions) (FixturesLoader, error) {
181-
files, err := FixturesFileFullPaths(opts.Dir, opts.Files)
197+
fixtureItems, err := FixturesFileFullPaths(opts.Dir, opts.Files)
182198
if err != nil {
183199
return nil, fmt.Errorf("failed to get fixtures files: %w", err)
184200
}
185-
f := &fixturesLoaderInternal{db: x.DB().DB, dbType: x.Dialect().URI().DBType, files: files, fixtures: map[string]*fixtureItem{}}
201+
202+
f := &fixturesLoaderInternal{xormEngine: x, db: x.DB().DB, dbType: x.Dialect().URI().DBType, fixtures: fixtureItems}
186203
switch f.dbType {
187204
case schemas.SQLITE:
188205
f.quoteObject = func(s string) string { return fmt.Sprintf(`"%s"`, s) }
@@ -197,5 +214,12 @@ func NewFixturesLoader(x *xorm.Engine, opts FixturesOptions) (FixturesLoader, er
197214
f.quoteObject = func(s string) string { return fmt.Sprintf("[%s]", s) }
198215
f.paramPlaceholder = func(idx int) string { return "?" }
199216
}
217+
218+
xormBeans, _ := db.NamesToBean()
219+
f.xormTableNames = map[string]bool{}
220+
for _, bean := range xormBeans {
221+
f.xormTableNames[db.TableName(bean)] = true
222+
}
223+
200224
return f, nil
201225
}

routers/web/feed/profile.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"time"
88

99
activities_model "code.gitea.io/gitea/models/activities"
10+
"code.gitea.io/gitea/models/organization"
1011
"code.gitea.io/gitea/models/renderhelper"
1112
"code.gitea.io/gitea/modules/markup/markdown"
1213
"code.gitea.io/gitea/services/context"
@@ -28,12 +29,23 @@ func ShowUserFeedAtom(ctx *context.Context) {
2829
// showUserFeed show user activity as RSS / Atom feed
2930
func showUserFeed(ctx *context.Context, formatType string) {
3031
includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
32+
isOrganisation := ctx.ContextUser.IsOrganization()
33+
if ctx.IsSigned && isOrganisation && !includePrivate {
34+
// When feed is requested by a member of the organization,
35+
// include the private repo's the member has access to.
36+
isOrgMember, err := organization.IsOrganizationMember(ctx, ctx.ContextUser.ID, ctx.Doer.ID)
37+
if err != nil {
38+
ctx.ServerError("IsOrganizationMember", err)
39+
return
40+
}
41+
includePrivate = isOrgMember
42+
}
3143

3244
actions, _, err := feed_service.GetFeeds(ctx, activities_model.GetFeedsOptions{
3345
RequestedUser: ctx.ContextUser,
3446
Actor: ctx.Doer,
3547
IncludePrivate: includePrivate,
36-
OnlyPerformedBy: !ctx.ContextUser.IsOrganization(),
48+
OnlyPerformedBy: !isOrganisation,
3749
IncludeDeleted: false,
3850
Date: ctx.FormString("date"),
3951
})

routers/web/feed/profile_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
package feed_test
4+
5+
import (
6+
"testing"
7+
8+
"code.gitea.io/gitea/models/unittest"
9+
user_model "code.gitea.io/gitea/models/user"
10+
"code.gitea.io/gitea/routers/web/feed"
11+
"code.gitea.io/gitea/services/contexttest"
12+
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
func TestMain(m *testing.M) {
17+
unittest.MainTest(m)
18+
}
19+
20+
func TestCheckGetOrgFeedsAsOrgMember(t *testing.T) {
21+
unittest.PrepareTestEnv(t)
22+
t.Run("OrgMember", func(t *testing.T) {
23+
ctx, resp := contexttest.MockContext(t, "org3.atom")
24+
ctx.ContextUser = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
25+
contexttest.LoadUser(t, ctx, 2)
26+
ctx.IsSigned = true
27+
feed.ShowUserFeedAtom(ctx)
28+
assert.Contains(t, resp.Body.String(), "<entry>") // Should contain 1 private entry
29+
})
30+
t.Run("NonOrgMember", func(t *testing.T) {
31+
ctx, resp := contexttest.MockContext(t, "org3.atom")
32+
ctx.ContextUser = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
33+
contexttest.LoadUser(t, ctx, 5)
34+
ctx.IsSigned = true
35+
feed.ShowUserFeedAtom(ctx)
36+
assert.NotContains(t, resp.Body.String(), "<entry>") // Should not contain any entries
37+
})
38+
}

services/mirror/mirror_pull.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"code.gitea.io/gitea/modules/git"
1616
giturl "code.gitea.io/gitea/modules/git/url"
1717
"code.gitea.io/gitea/modules/gitrepo"
18+
"code.gitea.io/gitea/modules/globallock"
1819
"code.gitea.io/gitea/modules/lfs"
1920
"code.gitea.io/gitea/modules/log"
2021
"code.gitea.io/gitea/modules/process"
@@ -425,6 +426,10 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
425426
return parseRemoteUpdateOutput(output, m.GetRemoteName()), true
426427
}
427428

429+
func getRepoPullMirrorLockKey(repoID int64) string {
430+
return fmt.Sprintf("repo_pull_mirror_%d", repoID)
431+
}
432+
428433
// SyncPullMirror starts the sync of the pull mirror and schedules the next run.
429434
func SyncPullMirror(ctx context.Context, repoID int64) bool {
430435
log.Trace("SyncMirrors [repo_id: %v]", repoID)
@@ -437,6 +442,13 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool {
437442
log.Error("PANIC whilst SyncMirrors[repo_id: %d] Panic: %v\nStacktrace: %s", repoID, err, log.Stack(2))
438443
}()
439444

445+
releaser, err := globallock.Lock(ctx, getRepoPullMirrorLockKey(repoID))
446+
if err != nil {
447+
log.Error("globallock.Lock(): %v", err)
448+
return false
449+
}
450+
defer releaser()
451+
440452
m, err := repo_model.GetMirrorByRepoID(ctx, repoID)
441453
if err != nil {
442454
log.Error("SyncMirrors [repo_id: %v]: unable to GetMirrorByRepoID: %v", repoID, err)

templates/shared/actions/runner_edit.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
<div class="field">
4242
<button class="ui primary button" data-url="{{.Link}}">{{ctx.Locale.Tr "actions.runners.update_runner"}}</button>
43-
<button class="ui red button delete-button show-modal" data-url="{{.Link}}/delete" data-modal="#runner-delete-modal">
43+
<button class="ui red button delete-button" data-url="{{.Link}}/delete" data-modal="#runner-delete-modal">
4444
{{ctx.Locale.Tr "actions.runners.delete_runner"}}</button>
4545
</div>
4646
</form>

tests/integration/actions_job_test.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,6 @@ jobs:
166166
}
167167
})
168168
}
169-
170-
httpContext := NewAPITestContext(t, user2.Name, apiRepo.Name, auth_model.AccessTokenScopeWriteRepository)
171-
doAPIDeleteRepository(httpContext)(t)
172169
})
173170
}
174171

@@ -348,9 +345,6 @@ jobs:
348345
}
349346
})
350347
}
351-
352-
httpContext := NewAPITestContext(t, user2.Name, apiRepo.Name, auth_model.AccessTokenScopeWriteRepository)
353-
doAPIDeleteRepository(httpContext)(t)
354348
})
355349
}
356350

@@ -434,8 +428,6 @@ jobs:
434428
assert.Equal(t, setting.Actions.DefaultActionsURL.URL(), gtCtx["gitea_default_actions_url"].GetStringValue())
435429
token := gtCtx["token"].GetStringValue()
436430
assert.Equal(t, actionTask.TokenLastEight, token[len(token)-8:])
437-
438-
doAPIDeleteRepository(user2APICtx)(t)
439431
})
440432
}
441433

@@ -543,12 +535,14 @@ jobs:
543535
err = actions_service.CleanupEphemeralRunners(t.Context())
544536
assert.NoError(t, err)
545537

546-
runner.client.runnerServiceClient.UpdateTask(t.Context(), connect.NewRequest(&runnerv1.UpdateTaskRequest{
538+
_, err = runner.client.runnerServiceClient.UpdateTask(t.Context(), connect.NewRequest(&runnerv1.UpdateTaskRequest{
547539
State: &runnerv1.TaskState{
548540
Id: actionTask.ID,
549541
Result: runnerv1.Result_RESULT_SUCCESS,
550542
},
551543
}))
544+
assert.NoError(t, err)
545+
552546
resp, err = runner.client.runnerServiceClient.FetchTask(t.Context(), connect.NewRequest(&runnerv1.FetchTaskRequest{
553547
TasksVersion: 0,
554548
}))
@@ -561,7 +555,7 @@ jobs:
561555
assert.Error(t, err)
562556
assert.Nil(t, resp)
563557

564-
// create an runner that picks a job and get force cancelled
558+
// create a runner that picks a job and get force cancelled
565559
runnerToBeRemoved := newMockRunner()
566560
runnerToBeRemoved.registerAsRepoRunner(t, baseRepo.OwnerName, baseRepo.Name, "mock-runner-to-be-removed", []string{"ubuntu-latest"}, true)
567561

@@ -583,9 +577,6 @@ jobs:
583577
assert.NoError(t, err)
584578

585579
unittest.AssertNotExistsBean(t, &actions_model.ActionRunner{ID: runnerToRemove.ID})
586-
587-
// this cleanup is required to allow further tests to pass
588-
doAPIDeleteRepository(user2APICtx)(t)
589580
})
590581
}
591582

tests/integration/actions_log_test.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestDownloadTaskLogs(t *testing.T) {
3535
{
3636
treePath: ".gitea/workflows/download-task-logs-zstd.yml",
3737
fileContent: `name: download-task-logs-zstd
38-
on:
38+
on:
3939
push:
4040
paths:
4141
- '.gitea/workflows/download-task-logs-zstd.yml'
@@ -67,7 +67,7 @@ jobs:
6767
{
6868
treePath: ".gitea/workflows/download-task-logs-no-zstd.yml",
6969
fileContent: `name: download-task-logs-no-zstd
70-
on:
70+
on:
7171
push:
7272
paths:
7373
- '.gitea/workflows/download-task-logs-no-zstd.yml'
@@ -152,8 +152,5 @@ jobs:
152152
resetFunc()
153153
})
154154
}
155-
156-
httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository)
157-
doAPIDeleteRepository(httpContext)(t)
158155
})
159156
}

tests/integration/api_repo_file_get_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ func TestAPIGetRawFileOrLFS(t *testing.T) {
4444
reqLFS := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/media/"+lfs)
4545
respLFS := MakeRequestNilResponseRecorder(t, reqLFS, http.StatusOK)
4646
assert.Equal(t, testFileSizeSmall, respLFS.Length)
47-
48-
doAPIDeleteRepository(httpContext)
4947
})
5048
})
5149
}

0 commit comments

Comments
 (0)