Compare commits

..

8 Commits

Author SHA1 Message Date
wxiaoguang
7a5af25592
Fix incorrect checkbox behaviors in the dashboard repolist's filter (#23147)
Co-author: yp05327 , this PR is based on yp05327's #22813.

The problems of the old DashboardRepoList / repolist.tmpl: 

* It mixes many different frameworks together
* It "just works", bug on bug
* It uses many anti-pattern of Vue

This PR:

* Fix bugs and close #22800
* Decouple the "checkbox" elements from Fomantic UI (only use CSS
styles)
* Simplify the HTML layout
* Simplify JS logic
* Make it easier to refactor the DashboardRepoList into a pure Vue
component in the future.

### Screenshots

#### Default

![image](https://user-images.githubusercontent.com/2114189/221355768-a3eb5b23-85b4-4e3d-b906-844d8b15539d.png)

####  Click "Archived" to make it checked

![image](https://user-images.githubusercontent.com/2114189/221355777-9a104ddf-52a7-4504-869a-43a73827d802.png)

####  Click "Archived" to make it intermediate

![image](https://user-images.githubusercontent.com/2114189/221355802-0f67a073-67ad-4e92-84a6-558c432103a5.png)

####  Click "Archived" to make it unchecked

![image](https://user-images.githubusercontent.com/2114189/221355810-acf1d9d8-ccce-47fe-a02e-70cf4e666331.png)

---------

Co-authored-by: yp05327 <576951401@qq.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-03-01 10:22:14 +08:00
GiteaBot
3e426bba78 [skip ci] Updated translations via Crowdin 2023-03-01 00:16:03 +00:00
zeripath
27e49cd01c
Properly flush unique queues on startup (#23154)
There have been a number of reports of PRs being blocked whilst being
checked which have been difficult to debug. In investigating #23050 I
have realised that whilst the Warn there is somewhat of a miscall there
was a real bug in the way that the LevelUniqueQueue was being restored
on start-up of the PersistableChannelUniqueQueue.

Next there is a conflict in the setting of the internal leveldb queue
name - This wasn't being set so it was being overridden by other unique
queues.

This PR fixes these bugs and adds a testcase.

Thanks to @brechtvl  for noticing the second issue.

Fix #23050
and others

---------

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2023-02-28 17:55:43 -05:00
Jason Song
04347eb810
Use context parameter in services/repository (#23186)
Use context parameter in `services/repository`.

And use `cache.WithCacheContext(ctx)` to generate push action history
feeds.

Fix #23160
2023-02-28 16:17:51 -06:00
Philip Peterson
cbbd3726b4
Pass --global when calling git config --get, for consistency with git config --set (#23157)
This arose out of #22451; it seems we are checking using non-global
settings to see if a config value is set, in order to decide whether to
call another global(-indeed) configuration command. This PR changes it
so that both the check and the set are for global configuration.
2023-02-28 15:26:19 -06:00
wxiaoguang
f5987c24e2
Make gitea serv respect git binary home (#23138)
Close #23137

The old code is too old (8-9 years ago)

Let's try to execute the git commands from git bin home directly.

The verb has been checked above, it could only be:
* git-upload-pack
* git-upload-archive
* git-receive-pack
* git-lfs-authenticate
2023-02-28 14:33:10 -06:00
Yarden Shoham
443dcc2db0
Write Gitpod app.ini only once (#23192)
Before this change, the `app.ini` would get overwritten on each
workspace start, confusing Gitea. It asked for reinstallation each time.
This makes sure the file is written only once by checking it does not
exist before creating it.

---
[Review without whitespace
diff](https://github.com/go-gitea/gitea/pull/23192/files?w=1)

---------

Co-authored-by: delvh <dev.lh@web.de>
2023-02-28 23:30:43 +08:00
Jason Song
cbc9a0fe47
Avoid too long names for actions (#23162)
The name of the job or step comes from the workflow file, while the name
of the runner comes from its registration. If the strings used for these
names are too long, they could cause db issues.
2023-02-28 18:20:36 +08:00
46 changed files with 596 additions and 253 deletions

View File

@ -10,9 +10,12 @@ tasks:
- name: Run backend - name: Run backend
command: | command: |
gp sync-await setup gp sync-await setup
mkdir -p custom/conf/ if [ ! -f custom/conf/app.ini ]
echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini then
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini mkdir -p custom/conf/
echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
fi
export TAGS="sqlite sqlite_unlock_notify" export TAGS="sqlite sqlite_unlock_notify"
make watch-backend make watch-backend
- name: Run frontend - name: Run frontend

View File

@ -11,6 +11,7 @@ import (
"net/url" "net/url"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@ -290,17 +291,21 @@ func runServ(c *cli.Context) error {
return nil return nil
} }
// Special handle for Windows.
if setting.IsWindows {
verb = strings.Replace(verb, "-", " ", 1)
}
var gitcmd *exec.Cmd var gitcmd *exec.Cmd
verbs := strings.Split(verb, " ") gitBinPath := filepath.Dir(git.GitExecutable) // e.g. /usr/bin
if len(verbs) == 2 { gitBinVerb := filepath.Join(gitBinPath, verb) // e.g. /usr/bin/git-upload-pack
gitcmd = exec.CommandContext(ctx, verbs[0], verbs[1], repoPath) if _, err := os.Stat(gitBinVerb); err != nil {
} else { // if the command "git-upload-pack" doesn't exist, try to split "git-upload-pack" to use the sub-command with git
gitcmd = exec.CommandContext(ctx, verb, repoPath) // ps: Windows only has "git.exe" in the bin path, so Windows always uses this way
verbFields := strings.SplitN(verb, "-", 2)
if len(verbFields) == 2 {
// use git binary with the sub-command part: "C:\...\bin\git.exe", "upload-pack", ...
gitcmd = exec.CommandContext(ctx, git.GitExecutable, verbFields[1], repoPath)
}
}
if gitcmd == nil {
// by default, use the verb (it has been checked above by allowedCommands)
gitcmd = exec.CommandContext(ctx, gitBinVerb, repoPath)
} }
process.SetSysProcAttribute(gitcmd) process.SetSysProcAttribute(gitcmd)

View File

@ -192,6 +192,7 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork
if len(needs) > 0 || run.NeedApproval { if len(needs) > 0 || run.NeedApproval {
status = StatusBlocked status = StatusBlocked
} }
job.Name, _ = util.SplitStringAtByteN(job.Name, 255)
runJobs = append(runJobs, &ActionRunJob{ runJobs = append(runJobs, &ActionRunJob{
RunID: run.ID, RunID: run.ID,
RepoID: run.RepoID, RepoID: run.RepoID,

View File

@ -298,8 +298,9 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
if len(workflowJob.Steps) > 0 { if len(workflowJob.Steps) > 0 {
steps := make([]*ActionTaskStep, len(workflowJob.Steps)) steps := make([]*ActionTaskStep, len(workflowJob.Steps))
for i, v := range workflowJob.Steps { for i, v := range workflowJob.Steps {
name, _ := util.SplitStringAtByteN(v.String(), 255)
steps[i] = &ActionTaskStep{ steps[i] = &ActionTaskStep{
Name: v.String(), Name: name,
TaskID: task.ID, TaskID: task.ID,
Index: int64(i), Index: int64(i),
RepoID: task.RepoID, RepoID: task.RepoID,

View File

@ -312,7 +312,7 @@ func CheckGitVersionAtLeast(atLeast string) error {
} }
func configSet(key, value string) error { func configSet(key, value string) error {
stdout, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key).RunStdString(nil) stdout, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key).RunStdString(nil)
if err != nil && !err.IsExitCode(1) { if err != nil && !err.IsExitCode(1) {
return fmt.Errorf("failed to get git config %s, err: %w", key, err) return fmt.Errorf("failed to get git config %s, err: %w", key, err)
} }
@ -331,7 +331,7 @@ func configSet(key, value string) error {
} }
func configSetNonExist(key, value string) error { func configSetNonExist(key, value string) error {
_, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key).RunStdString(nil) _, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key).RunStdString(nil)
if err == nil { if err == nil {
// already exist // already exist
return nil return nil
@ -349,7 +349,7 @@ func configSetNonExist(key, value string) error {
} }
func configAddNonExist(key, value string) error { func configAddNonExist(key, value string) error {
_, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(nil) _, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(nil)
if err == nil { if err == nil {
// already exist // already exist
return nil return nil
@ -366,7 +366,7 @@ func configAddNonExist(key, value string) error {
} }
func configUnsetAll(key, value string) error { func configUnsetAll(key, value string) error {
_, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key).RunStdString(nil) _, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key).RunStdString(nil)
if err == nil { if err == nil {
// exist, need to remove // exist, need to remove
_, _, err = NewCommand(DefaultContext, "config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(nil) _, _, err = NewCommand(DefaultContext, "config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(nil)

View File

@ -124,7 +124,10 @@ func (q *ChannelQueue) Shutdown() {
log.Trace("ChannelQueue: %s Flushing", q.name) log.Trace("ChannelQueue: %s Flushing", q.name)
// We can't use Cleanup here because that will close the channel // We can't use Cleanup here because that will close the channel
if err := q.FlushWithContext(q.terminateCtx); err != nil { if err := q.FlushWithContext(q.terminateCtx); err != nil {
log.Warn("ChannelQueue: %s Terminated before completed flushing", q.name) count := atomic.LoadInt64(&q.numInQueue)
if count > 0 {
log.Warn("ChannelQueue: %s Terminated before completed flushing", q.name)
}
return return
} }
log.Debug("ChannelQueue: %s Flushed", q.name) log.Debug("ChannelQueue: %s Flushed", q.name)

View File

@ -94,7 +94,8 @@ func NewPersistableChannelQueue(handle HandlerFunc, cfg, exemplar interface{}) (
}, },
Workers: 0, Workers: 0,
}, },
DataDir: config.DataDir, DataDir: config.DataDir,
QueueName: config.Name + "-level",
} }
levelQueue, err := NewLevelQueue(wrappedHandle, levelCfg, exemplar) levelQueue, err := NewLevelQueue(wrappedHandle, levelCfg, exemplar)
@ -172,16 +173,18 @@ func (q *PersistableChannelQueue) Run(atShutdown, atTerminate func(func())) {
atShutdown(q.Shutdown) atShutdown(q.Shutdown)
atTerminate(q.Terminate) atTerminate(q.Terminate)
if lq, ok := q.internal.(*LevelQueue); ok && lq.byteFIFO.Len(lq.shutdownCtx) != 0 { if lq, ok := q.internal.(*LevelQueue); ok && lq.byteFIFO.Len(lq.terminateCtx) != 0 {
// Just run the level queue - we shut it down once it's flushed // Just run the level queue - we shut it down once it's flushed
go q.internal.Run(func(_ func()) {}, func(_ func()) {}) go q.internal.Run(func(_ func()) {}, func(_ func()) {})
go func() { go func() {
for !q.IsEmpty() { for !lq.IsEmpty() {
_ = q.internal.Flush(0) _ = lq.Flush(0)
select { select {
case <-time.After(100 * time.Millisecond): case <-time.After(100 * time.Millisecond):
case <-q.internal.(*LevelQueue).shutdownCtx.Done(): case <-lq.shutdownCtx.Done():
log.Warn("LevelQueue: %s shut down before completely flushed", q.internal.(*LevelQueue).Name()) if lq.byteFIFO.Len(lq.terminateCtx) > 0 {
log.Warn("LevelQueue: %s shut down before completely flushed", q.internal.(*LevelQueue).Name())
}
return return
} }
} }
@ -316,10 +319,22 @@ func (q *PersistableChannelQueue) Shutdown() {
// Redirect all remaining data in the chan to the internal channel // Redirect all remaining data in the chan to the internal channel
log.Trace("PersistableChannelQueue: %s Redirecting remaining data", q.delayedStarter.name) log.Trace("PersistableChannelQueue: %s Redirecting remaining data", q.delayedStarter.name)
close(q.channelQueue.dataChan) close(q.channelQueue.dataChan)
countOK, countLost := 0, 0
for data := range q.channelQueue.dataChan { for data := range q.channelQueue.dataChan {
_ = q.internal.Push(data) err := q.internal.Push(data)
if err != nil {
log.Error("PersistableChannelQueue: %s Unable redirect %v due to: %v", q.delayedStarter.name, data, err)
countLost++
} else {
countOK++
}
atomic.AddInt64(&q.channelQueue.numInQueue, -1) atomic.AddInt64(&q.channelQueue.numInQueue, -1)
} }
if countLost > 0 {
log.Warn("PersistableChannelQueue: %s %d will be restored on restart, %d lost", q.delayedStarter.name, countOK, countLost)
} else if countOK > 0 {
log.Warn("PersistableChannelQueue: %s %d will be restored on restart", q.delayedStarter.name, countOK)
}
log.Trace("PersistableChannelQueue: %s Done Redirecting remaining data", q.delayedStarter.name) log.Trace("PersistableChannelQueue: %s Done Redirecting remaining data", q.delayedStarter.name)
log.Debug("PersistableChannelQueue: %s Shutdown", q.delayedStarter.name) log.Debug("PersistableChannelQueue: %s Shutdown", q.delayedStarter.name)

View File

@ -39,7 +39,7 @@ func TestPersistableChannelQueue(t *testing.T) {
Workers: 1, Workers: 1,
BoostWorkers: 0, BoostWorkers: 0,
MaxWorkers: 10, MaxWorkers: 10,
Name: "first", Name: "test-queue",
}, &testData{}) }, &testData{})
assert.NoError(t, err) assert.NoError(t, err)
@ -135,7 +135,7 @@ func TestPersistableChannelQueue(t *testing.T) {
Workers: 1, Workers: 1,
BoostWorkers: 0, BoostWorkers: 0,
MaxWorkers: 10, MaxWorkers: 10,
Name: "second", Name: "test-queue",
}, &testData{}) }, &testData{})
assert.NoError(t, err) assert.NoError(t, err)
@ -227,7 +227,7 @@ func TestPersistableChannelQueue_Pause(t *testing.T) {
Workers: 1, Workers: 1,
BoostWorkers: 0, BoostWorkers: 0,
MaxWorkers: 10, MaxWorkers: 10,
Name: "first", Name: "test-queue",
}, &testData{}) }, &testData{})
assert.NoError(t, err) assert.NoError(t, err)
@ -433,7 +433,7 @@ func TestPersistableChannelQueue_Pause(t *testing.T) {
Workers: 1, Workers: 1,
BoostWorkers: 0, BoostWorkers: 0,
MaxWorkers: 10, MaxWorkers: 10,
Name: "second", Name: "test-queue",
}, &testData{}) }, &testData{})
assert.NoError(t, err) assert.NoError(t, err)
pausable, ok = queue.(Pausable) pausable, ok = queue.(Pausable)

View File

@ -177,7 +177,9 @@ func (q *ChannelUniqueQueue) Shutdown() {
go func() { go func() {
log.Trace("ChannelUniqueQueue: %s Flushing", q.name) log.Trace("ChannelUniqueQueue: %s Flushing", q.name)
if err := q.FlushWithContext(q.terminateCtx); err != nil { if err := q.FlushWithContext(q.terminateCtx); err != nil {
log.Warn("ChannelUniqueQueue: %s Terminated before completed flushing", q.name) if !q.IsEmpty() {
log.Warn("ChannelUniqueQueue: %s Terminated before completed flushing", q.name)
}
return return
} }
log.Debug("ChannelUniqueQueue: %s Flushed", q.name) log.Debug("ChannelUniqueQueue: %s Flushed", q.name)

View File

@ -8,10 +8,13 @@ import (
"testing" "testing"
"time" "time"
"code.gitea.io/gitea/modules/log"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestChannelUniqueQueue(t *testing.T) { func TestChannelUniqueQueue(t *testing.T) {
_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
handleChan := make(chan *testData) handleChan := make(chan *testData)
handle := func(data ...Data) []Data { handle := func(data ...Data) []Data {
for _, datum := range data { for _, datum := range data {
@ -52,6 +55,8 @@ func TestChannelUniqueQueue(t *testing.T) {
} }
func TestChannelUniqueQueue_Batch(t *testing.T) { func TestChannelUniqueQueue_Batch(t *testing.T) {
_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
handleChan := make(chan *testData) handleChan := make(chan *testData)
handle := func(data ...Data) []Data { handle := func(data ...Data) []Data {
for _, datum := range data { for _, datum := range data {
@ -98,6 +103,8 @@ func TestChannelUniqueQueue_Batch(t *testing.T) {
} }
func TestChannelUniqueQueue_Pause(t *testing.T) { func TestChannelUniqueQueue_Pause(t *testing.T) {
_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
lock := sync.Mutex{} lock := sync.Mutex{}
var queue Queue var queue Queue
var err error var err error

View File

@ -94,7 +94,8 @@ func NewPersistableChannelUniqueQueue(handle HandlerFunc, cfg, exemplar interfac
}, },
Workers: 0, Workers: 0,
}, },
DataDir: config.DataDir, DataDir: config.DataDir,
QueueName: config.Name + "-level",
} }
queue.channelQueue = channelUniqueQueue.(*ChannelUniqueQueue) queue.channelQueue = channelUniqueQueue.(*ChannelUniqueQueue)
@ -209,17 +210,29 @@ func (q *PersistableChannelUniqueQueue) Run(atShutdown, atTerminate func(func())
atTerminate(q.Terminate) atTerminate(q.Terminate)
_ = q.channelQueue.AddWorkers(q.channelQueue.workers, 0) _ = q.channelQueue.AddWorkers(q.channelQueue.workers, 0)
if luq, ok := q.internal.(*LevelUniqueQueue); ok && luq.ByteFIFOUniqueQueue.byteFIFO.Len(luq.shutdownCtx) != 0 { if luq, ok := q.internal.(*LevelUniqueQueue); ok && !luq.IsEmpty() {
// Just run the level queue - we shut it down once it's flushed // Just run the level queue - we shut it down once it's flushed
go q.internal.Run(func(_ func()) {}, func(_ func()) {}) go luq.Run(func(_ func()) {}, func(_ func()) {})
go func() { go func() {
_ = q.internal.Flush(0) _ = luq.Flush(0)
log.Debug("LevelUniqueQueue: %s flushed so shutting down", q.internal.(*LevelUniqueQueue).Name()) for !luq.IsEmpty() {
q.internal.(*LevelUniqueQueue).Shutdown() _ = luq.Flush(0)
GetManager().Remove(q.internal.(*LevelUniqueQueue).qid) select {
case <-time.After(100 * time.Millisecond):
case <-luq.shutdownCtx.Done():
if luq.byteFIFO.Len(luq.terminateCtx) > 0 {
log.Warn("LevelUniqueQueue: %s shut down before completely flushed", luq.Name())
}
return
}
}
log.Debug("LevelUniqueQueue: %s flushed so shutting down", luq.Name())
luq.Shutdown()
GetManager().Remove(luq.qid)
}() }()
} else { } else {
log.Debug("PersistableChannelUniqueQueue: %s Skipping running the empty level queue", q.delayedStarter.name) log.Debug("PersistableChannelUniqueQueue: %s Skipping running the empty level queue", q.delayedStarter.name)
_ = q.internal.Flush(0)
q.internal.(*LevelUniqueQueue).Shutdown() q.internal.(*LevelUniqueQueue).Shutdown()
GetManager().Remove(q.internal.(*LevelUniqueQueue).qid) GetManager().Remove(q.internal.(*LevelUniqueQueue).qid)
} }
@ -285,8 +298,20 @@ func (q *PersistableChannelUniqueQueue) Shutdown() {
// Redirect all remaining data in the chan to the internal channel // Redirect all remaining data in the chan to the internal channel
close(q.channelQueue.dataChan) close(q.channelQueue.dataChan)
log.Trace("PersistableChannelUniqueQueue: %s Redirecting remaining data", q.delayedStarter.name) log.Trace("PersistableChannelUniqueQueue: %s Redirecting remaining data", q.delayedStarter.name)
countOK, countLost := 0, 0
for data := range q.channelQueue.dataChan { for data := range q.channelQueue.dataChan {
_ = q.internal.Push(data) err := q.internal.(*LevelUniqueQueue).Push(data)
if err != nil {
log.Error("PersistableChannelUniqueQueue: %s Unable redirect %v due to: %v", q.delayedStarter.name, data, err)
countLost++
} else {
countOK++
}
}
if countLost > 0 {
log.Warn("PersistableChannelUniqueQueue: %s %d will be restored on restart, %d lost", q.delayedStarter.name, countOK, countLost)
} else if countOK > 0 {
log.Warn("PersistableChannelUniqueQueue: %s %d will be restored on restart", q.delayedStarter.name, countOK)
} }
log.Trace("PersistableChannelUniqueQueue: %s Done Redirecting remaining data", q.delayedStarter.name) log.Trace("PersistableChannelUniqueQueue: %s Done Redirecting remaining data", q.delayedStarter.name)

View File

@ -0,0 +1,259 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package queue
import (
"fmt"
"strconv"
"sync"
"testing"
"time"
"code.gitea.io/gitea/modules/log"
"github.com/stretchr/testify/assert"
)
func TestPersistableChannelUniqueQueue(t *testing.T) {
tmpDir := t.TempDir()
fmt.Printf("TempDir %s\n", tmpDir)
_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
// Common function to create the Queue
newQueue := func(name string, handle func(data ...Data) []Data) Queue {
q, err := NewPersistableChannelUniqueQueue(handle,
PersistableChannelUniqueQueueConfiguration{
Name: name,
DataDir: tmpDir,
QueueLength: 200,
MaxWorkers: 1,
BlockTimeout: 1 * time.Second,
BoostTimeout: 5 * time.Minute,
BoostWorkers: 1,
Workers: 0,
}, "task-0")
assert.NoError(t, err)
return q
}
// runs the provided queue and provides some timer function
type channels struct {
readyForShutdown chan struct{} // closed when shutdown functions have been assigned
readyForTerminate chan struct{} // closed when terminate functions have been assigned
signalShutdown chan struct{} // Should close to signal shutdown
doneShutdown chan struct{} // closed when shutdown function is done
queueTerminate []func() // list of atTerminate functions to call atTerminate - need to be accessed with lock
}
runQueue := func(q Queue, lock *sync.Mutex) *channels {
chans := &channels{
readyForShutdown: make(chan struct{}),
readyForTerminate: make(chan struct{}),
signalShutdown: make(chan struct{}),
doneShutdown: make(chan struct{}),
}
go q.Run(func(atShutdown func()) {
go func() {
lock.Lock()
select {
case <-chans.readyForShutdown:
default:
close(chans.readyForShutdown)
}
lock.Unlock()
<-chans.signalShutdown
atShutdown()
close(chans.doneShutdown)
}()
}, func(atTerminate func()) {
lock.Lock()
defer lock.Unlock()
select {
case <-chans.readyForTerminate:
default:
close(chans.readyForTerminate)
}
chans.queueTerminate = append(chans.queueTerminate, atTerminate)
})
return chans
}
// call to shutdown and terminate the queue associated with the channels
doTerminate := func(chans *channels, lock *sync.Mutex) {
<-chans.readyForTerminate
lock.Lock()
callbacks := []func(){}
callbacks = append(callbacks, chans.queueTerminate...)
lock.Unlock()
for _, callback := range callbacks {
callback()
}
}
mapLock := sync.Mutex{}
executedInitial := map[string][]string{}
hasInitial := map[string][]string{}
fillQueue := func(name string, done chan struct{}) {
t.Run("Initial Filling: "+name, func(t *testing.T) {
lock := sync.Mutex{}
startAt100Queued := make(chan struct{})
stopAt20Shutdown := make(chan struct{}) // stop and shutdown at the 20th item
handle := func(data ...Data) []Data {
<-startAt100Queued
for _, datum := range data {
s := datum.(string)
mapLock.Lock()
executedInitial[name] = append(executedInitial[name], s)
mapLock.Unlock()
if s == "task-20" {
close(stopAt20Shutdown)
}
}
return nil
}
q := newQueue(name, handle)
// add 100 tasks to the queue
for i := 0; i < 100; i++ {
_ = q.Push("task-" + strconv.Itoa(i))
}
close(startAt100Queued)
chans := runQueue(q, &lock)
<-chans.readyForShutdown
<-stopAt20Shutdown
close(chans.signalShutdown)
<-chans.doneShutdown
_ = q.Push("final")
// check which tasks are still in the queue
for i := 0; i < 100; i++ {
if has, _ := q.(UniqueQueue).Has("task-" + strconv.Itoa(i)); has {
mapLock.Lock()
hasInitial[name] = append(hasInitial[name], "task-"+strconv.Itoa(i))
mapLock.Unlock()
}
}
if has, _ := q.(UniqueQueue).Has("final"); has {
mapLock.Lock()
hasInitial[name] = append(hasInitial[name], "final")
mapLock.Unlock()
} else {
assert.Fail(t, "UnqueQueue %s should have \"final\"", name)
}
doTerminate(chans, &lock)
mapLock.Lock()
assert.Equal(t, 101, len(executedInitial[name])+len(hasInitial[name]))
mapLock.Unlock()
})
close(done)
}
doneA := make(chan struct{})
doneB := make(chan struct{})
go fillQueue("QueueA", doneA)
go fillQueue("QueueB", doneB)
<-doneA
<-doneB
executedEmpty := map[string][]string{}
hasEmpty := map[string][]string{}
emptyQueue := func(name string, done chan struct{}) {
t.Run("Empty Queue: "+name, func(t *testing.T) {
lock := sync.Mutex{}
stop := make(chan struct{})
// collect the tasks that have been executed
handle := func(data ...Data) []Data {
lock.Lock()
for _, datum := range data {
mapLock.Lock()
executedEmpty[name] = append(executedEmpty[name], datum.(string))
mapLock.Unlock()
if datum.(string) == "final" {
close(stop)
}
}
lock.Unlock()
return nil
}
q := newQueue(name, handle)
chans := runQueue(q, &lock)
<-chans.readyForShutdown
<-stop
close(chans.signalShutdown)
<-chans.doneShutdown
// check which tasks are still in the queue
for i := 0; i < 100; i++ {
if has, _ := q.(UniqueQueue).Has("task-" + strconv.Itoa(i)); has {
mapLock.Lock()
hasEmpty[name] = append(hasEmpty[name], "task-"+strconv.Itoa(i))
mapLock.Unlock()
}
}
doTerminate(chans, &lock)
mapLock.Lock()
assert.Equal(t, 101, len(executedInitial[name])+len(executedEmpty[name]))
assert.Equal(t, 0, len(hasEmpty[name]))
mapLock.Unlock()
})
close(done)
}
doneA = make(chan struct{})
doneB = make(chan struct{})
go emptyQueue("QueueA", doneA)
go emptyQueue("QueueB", doneB)
<-doneA
<-doneB
mapLock.Lock()
t.Logf("TestPersistableChannelUniqueQueue executedInitiallyA=%v, executedInitiallyB=%v, executedToEmptyA=%v, executedToEmptyB=%v",
len(executedInitial["QueueA"]), len(executedInitial["QueueB"]), len(executedEmpty["QueueA"]), len(executedEmpty["QueueB"]))
// reset and rerun
executedInitial = map[string][]string{}
hasInitial = map[string][]string{}
executedEmpty = map[string][]string{}
hasEmpty = map[string][]string{}
mapLock.Unlock()
doneA = make(chan struct{})
doneB = make(chan struct{})
go fillQueue("QueueA", doneA)
go fillQueue("QueueB", doneB)
<-doneA
<-doneB
doneA = make(chan struct{})
doneB = make(chan struct{})
go emptyQueue("QueueA", doneA)
go emptyQueue("QueueB", doneB)
<-doneA
<-doneB
mapLock.Lock()
t.Logf("TestPersistableChannelUniqueQueue executedInitiallyA=%v, executedInitiallyB=%v, executedToEmptyA=%v, executedToEmptyB=%v",
len(executedInitial["QueueA"]), len(executedInitial["QueueB"]), len(executedEmpty["QueueA"]), len(executedEmpty["QueueB"]))
mapLock.Unlock()
}

View File

@ -248,6 +248,7 @@ no_reply_address_helper=Nome de domínio para usuários com um endereço de e-ma
password_algorithm=Algoritmo Hash de Senha password_algorithm=Algoritmo Hash de Senha
password_algorithm_helper=Escolha o algoritmo de hash para as senhas. Diferentes algoritmos têm requerimentos e forças diversos. O `Argon2` possui boa qualidade, porém usa muita memória e pode ser inapropriado para sistemas com menos recursos. password_algorithm_helper=Escolha o algoritmo de hash para as senhas. Diferentes algoritmos têm requerimentos e forças diversos. O `Argon2` possui boa qualidade, porém usa muita memória e pode ser inapropriado para sistemas com menos recursos.
enable_update_checker=Habilitar Verificador de Atualizações enable_update_checker=Habilitar Verificador de Atualizações
enable_update_checker_helper=Procura por novas versões periodicamente conectando-se ao gitea.io.
[home] [home]
uname_holder=Usuário ou e-mail uname_holder=Usuário ou e-mail
@ -283,7 +284,9 @@ organizations=Organizações
search=Pesquisar search=Pesquisar
code=Código code=Código
search.fuzzy=Similar search.fuzzy=Similar
search.fuzzy.tooltip=Incluir resultados que sejam próximos ao termo de busca
search.match=Correspondência search.match=Correspondência
search.match.tooltip=Incluir somente resultados que correspondam exatamente ao termo de busca
code_search_unavailable=A pesquisa por código não está disponível no momento. Entre em contato com o administrador do site. code_search_unavailable=A pesquisa por código não está disponível no momento. Entre em contato com o administrador do site.
repo_no_results=Nenhum repositório correspondente foi encontrado. repo_no_results=Nenhum repositório correspondente foi encontrado.
user_no_results=Nenhum usuário correspondente foi encontrado. user_no_results=Nenhum usuário correspondente foi encontrado.
@ -365,6 +368,7 @@ password_pwned_err=Não foi possível concluir a requisição ao HaveIBeenPwned
[mail] [mail]
view_it_on=Veja em %s view_it_on=Veja em %s
reply=ou responda diretamente a este email
link_not_working_do_paste=Não está funcionando? Tente copiá-lo e colá-lo no seu navegador. link_not_working_do_paste=Não está funcionando? Tente copiá-lo e colá-lo no seu navegador.
hi_user_x=Olá <b>%s</b>, hi_user_x=Olá <b>%s</b>,
@ -423,6 +427,10 @@ repo.transfer.body=Para o aceitar ou rejeitar visite %s, ou simplesmente o ignor
repo.collaborator.added.subject=%s adicionou você a %s repo.collaborator.added.subject=%s adicionou você a %s
repo.collaborator.added.text=Você foi adicionado como um colaborador do repositório: repo.collaborator.added.text=Você foi adicionado como um colaborador do repositório:
team_invite.subject=%[1]s convidou você para participar da organização %[2]s
team_invite.text_1=%[1]s convidou você para participar da equipe %[2]s na organização %[3]s.
team_invite.text_2=Por favor, clique no seguinte link para se juntar à equipe:
team_invite.text_3=Nota: este convite foi destinado a %[1]s. Se você não estava esperando este convite, você pode ignorar este e-mail.
[modal] [modal]
yes=Sim yes=Sim
@ -503,6 +511,7 @@ cannot_add_org_to_team=Uma organização não pode ser adicionada como membro de
invalid_ssh_key=Não é possível verificar sua chave SSH: %s invalid_ssh_key=Não é possível verificar sua chave SSH: %s
invalid_gpg_key=Não é possível verificar sua chave GPG: %s invalid_gpg_key=Não é possível verificar sua chave GPG: %s
invalid_ssh_principal=Nome principal inválido: %s invalid_ssh_principal=Nome principal inválido: %s
must_use_public_key=A chave que você forneceu é uma chave privada. Por favor, não envie sua chave privada em nenhum lugar. Use sua chave pública em vez disso.
unable_verify_ssh_key=Não é possível verificar sua chave SSH unable_verify_ssh_key=Não é possível verificar sua chave SSH
auth_failed=Autenticação falhou: %v auth_failed=Autenticação falhou: %v
@ -1200,6 +1209,7 @@ projects.type.uncategorized=Sem categoria
projects.column.edit_title=Nome projects.column.edit_title=Nome
projects.column.new_title=Nome projects.column.new_title=Nome
projects.column.new=Nova Coluna projects.column.new=Nova Coluna
projects.column.delete=Excluir coluna
projects.column.color=Colorido projects.column.color=Colorido
projects.open=Abrir projects.open=Abrir
projects.close=Fechar projects.close=Fechar
@ -1773,7 +1783,9 @@ activity.git_stats_deletion_n=%d exclusões
search=Pesquisar search=Pesquisar
search.search_repo=Pesquisar no repositório... search.search_repo=Pesquisar no repositório...
search.fuzzy=Aproximada search.fuzzy=Aproximada
search.fuzzy.tooltip=Incluir resultados que sejam próximos ao termo de busca
search.match=Corresponde search.match=Corresponde
search.match.tooltip=Incluir somente resultados que correspondam exatamente ao termo de busca
search.results=Resultados da pesquisa para "%s" em <a href="%s">%s</a> search.results=Resultados da pesquisa para "%s" em <a href="%s">%s</a>
search.code_no_results=Nenhum código-fonte correspondente ao seu termo de pesquisa foi encontrado. search.code_no_results=Nenhum código-fonte correspondente ao seu termo de pesquisa foi encontrado.
search.code_search_unavailable=A pesquisa por código não está disponível no momento. Entre em contato com o administrador do site. search.code_search_unavailable=A pesquisa por código não está disponível no momento. Entre em contato com o administrador do site.

View File

@ -57,6 +57,7 @@ new_mirror=Nova réplica
new_fork=Nova derivação do repositório new_fork=Nova derivação do repositório
new_org=Nova organização new_org=Nova organização
new_project=Novo planeamento new_project=Novo planeamento
new_project_column=Nova coluna
manage_org=Gerir organizações manage_org=Gerir organizações
admin_panel=Administração do sítio admin_panel=Administração do sítio
account_settings=Configurações da conta account_settings=Configurações da conta
@ -90,6 +91,7 @@ disabled=Desabilitado
copy=Copiar copy=Copiar
copy_url=Copiar URL copy_url=Copiar URL
copy_content=Copiar conteúdo
copy_branch=Copiar nome do ramo copy_branch=Copiar nome do ramo
copy_success=Copiado! copy_success=Copiado!
copy_error=Falha ao copiar copy_error=Falha ao copiar
@ -109,6 +111,10 @@ never=Nunca
rss_feed=Fonte RSS rss_feed=Fonte RSS
[aria] [aria]
navbar=Barra de navegação
footer=Rodapé
footer.software=Sobre o Software
footer.links=Ligações
[filter] [filter]
string.asc=A - Z string.asc=A - Z
@ -364,6 +370,7 @@ password_pwned_err=Não foi possível completar o pedido ao HaveIBeenPwned
[mail] [mail]
view_it_on=Ver em %s view_it_on=Ver em %s
reply=ou responda a este email imediatamente
link_not_working_do_paste=Não está a funcionar? Tente copiar e colar no seu navegador. link_not_working_do_paste=Não está a funcionar? Tente copiar e colar no seu navegador.
hi_user_x=Olá <b>%s</b>, hi_user_x=Olá <b>%s</b>,
@ -467,6 +474,8 @@ url_error=`'%s' não é um URL válido.`
include_error=` tem que conter o texto '%s'.` include_error=` tem que conter o texto '%s'.`
glob_pattern_error=` o padrão glob é inválido: %s.` glob_pattern_error=` o padrão glob é inválido: %s.`
regex_pattern_error=` o padrão regex é inválido: %s.` regex_pattern_error=` o padrão regex é inválido: %s.`
username_error=` só pode conter caracteres alfanuméricos ('0-9','a-z','A-Z'), hífen ('-'), sublinhado ('_') e ponto ('.') Não pode começar nem terminar com caracteres não alfanuméricos, e caracteres não alfanuméricos consecutivos também são proibidos.`
invalid_group_team_map_error=` o mapeamento é inválido: %s`
unknown_error=Erro desconhecido: unknown_error=Erro desconhecido:
captcha_incorrect=O código CAPTCHA está errado. captcha_incorrect=O código CAPTCHA está errado.
password_not_match=As senhas não coincidem. password_not_match=As senhas não coincidem.
@ -503,10 +512,12 @@ team_not_exist=A equipa não existe.
last_org_owner=Não pode remover o último utilizador da equipa 'proprietários'. Tem que haver pelo menos um proprietário numa organização. last_org_owner=Não pode remover o último utilizador da equipa 'proprietários'. Tem que haver pelo menos um proprietário numa organização.
cannot_add_org_to_team=Uma organização não pode ser adicionada como membro de uma equipa. cannot_add_org_to_team=Uma organização não pode ser adicionada como membro de uma equipa.
duplicate_invite_to_team=O(A) utilizador(a) já tinha sido convidado(a) para ser membro da equipa. duplicate_invite_to_team=O(A) utilizador(a) já tinha sido convidado(a) para ser membro da equipa.
organization_leave_success=Você deixou a organização %s com sucesso.
invalid_ssh_key=Não é possível validar a sua chave SSH: %s invalid_ssh_key=Não é possível validar a sua chave SSH: %s
invalid_gpg_key=Não é possível validar a sua chave GPG: %s invalid_gpg_key=Não é possível validar a sua chave GPG: %s
invalid_ssh_principal=Protagonista inválido: %s invalid_ssh_principal=Protagonista inválido: %s
must_use_public_key=A chave que você forneceu é privada. Não carregue a sua chave em lugar nenhum, em vez disso use a sua chave pública.
unable_verify_ssh_key=Não é possível validar a chave SSH unable_verify_ssh_key=Não é possível validar a chave SSH
auth_failed=Falhou a autenticação: %v auth_failed=Falhou a autenticação: %v
@ -743,6 +754,8 @@ access_token_deletion_cancel_action=Cancelar
access_token_deletion_confirm_action=Eliminar access_token_deletion_confirm_action=Eliminar
access_token_deletion_desc=Eliminar um código revoga o acesso à sua conta nas aplicações que o usem. Esta operação não poderá ser revertida. Quer continuar? access_token_deletion_desc=Eliminar um código revoga o acesso à sua conta nas aplicações que o usem. Esta operação não poderá ser revertida. Quer continuar?
delete_token_success=O código foi eliminado. Aplicações que o usavam deixaram de ter acesso à sua conta. delete_token_success=O código foi eliminado. Aplicações que o usavam deixaram de ter acesso à sua conta.
select_scopes=Escolha os âmbitos
scopes_list=Âmbitos:
manage_oauth2_applications=Gerir aplicações OAuth2 manage_oauth2_applications=Gerir aplicações OAuth2
edit_oauth2_application=Editar aplicação OAuth2 edit_oauth2_application=Editar aplicação OAuth2
@ -1015,10 +1028,12 @@ unstar=Tirar dos favoritos
star=Juntar aos favoritos star=Juntar aos favoritos
fork=Derivar fork=Derivar
download_archive=Descarregar repositório download_archive=Descarregar repositório
more_operations=Mais operações
no_desc=Sem descrição no_desc=Sem descrição
quick_guide=Guia rápido quick_guide=Guia rápido
clone_this_repo=Clonar este repositório clone_this_repo=Clonar este repositório
cite_this_repo=Citar este repositório
create_new_repo_command=Criando um novo repositório na linha de comandos create_new_repo_command=Criando um novo repositório na linha de comandos
push_exist_repo=Enviando, pela linha de comandos, um repositório existente push_exist_repo=Enviando, pela linha de comandos, um repositório existente
empty_message=Este repositório não contém qualquer conteúdo. empty_message=Este repositório não contém qualquer conteúdo.
@ -1117,6 +1132,7 @@ editor.commit_directly_to_this_branch=Cometer imediatamente no ramo <strong clas
editor.create_new_branch=Crie um <strong>novo ramo</strong> para este cometimento e inicie um pedido de integração. editor.create_new_branch=Crie um <strong>novo ramo</strong> para este cometimento e inicie um pedido de integração.
editor.create_new_branch_np=Criar um <strong>novo ramo</strong> para este cometimento. editor.create_new_branch_np=Criar um <strong>novo ramo</strong> para este cometimento.
editor.propose_file_change=Propor modificação do ficheiro editor.propose_file_change=Propor modificação do ficheiro
editor.new_branch_name=Dê um nome ao novo ramo para este cometimento
editor.new_branch_name_desc=Nome do novo ramo… editor.new_branch_name_desc=Nome do novo ramo…
editor.cancel=Cancelar editor.cancel=Cancelar
editor.filename_cannot_be_empty=O nome do ficheiro não pode estar em branco. editor.filename_cannot_be_empty=O nome do ficheiro não pode estar em branco.
@ -1168,6 +1184,7 @@ commits.signed_by_untrusted_user_unmatched=Assinado por um utilizador não fiáv
commits.gpg_key_id=ID da chave GPG commits.gpg_key_id=ID da chave GPG
commits.ssh_key_fingerprint=Identificação digital da chave SSH commits.ssh_key_fingerprint=Identificação digital da chave SSH
commit.operations=Operações
commit.revert=Reverter commit.revert=Reverter
commit.revert-header=Reverter: %s commit.revert-header=Reverter: %s
commit.revert-content=Escolha o ramo para onde vai reverter: commit.revert-content=Escolha o ramo para onde vai reverter:
@ -1200,11 +1217,22 @@ projects.type.bug_triage=Triagem de erros
projects.template.desc=Modelo de planeamento projects.template.desc=Modelo de planeamento
projects.template.desc_helper=Escolha um modelo de planeamento para começar projects.template.desc_helper=Escolha um modelo de planeamento para começar
projects.type.uncategorized=Sem categoria projects.type.uncategorized=Sem categoria
projects.column.edit=Editar coluna
projects.column.edit_title=Nome projects.column.edit_title=Nome
projects.column.new_title=Nome projects.column.new_title=Nome
projects.column.new_submit=Criar coluna
projects.column.new=Nova coluna
projects.column.set_default=Definir como padrão
projects.column.set_default_desc=Defina esta coluna como padrão para questões e pedidos de integração não categorizados
projects.column.delete=Eliminar coluna
projects.column.deletion_desc=Eliminar uma coluna de um planeamento faz com que todas as questões que nela constam sejam movidas para a coluna 'Sem categoria'. Continuar?
projects.column.color=Colorido projects.column.color=Colorido
projects.open=Abrir projects.open=Abrir
projects.close=Fechar projects.close=Fechar
projects.column.assigned_to=Atribuída a
projects.card_type.desc=Previsão dos cartões
projects.card_type.images_and_text=Imagens e texto
projects.card_type.text_only=Apenas texto
issues.desc=Organize relatórios de erros, tarefas e etapas. issues.desc=Organize relatórios de erros, tarefas e etapas.
issues.filter_assignees=Filtrar encarregado issues.filter_assignees=Filtrar encarregado
@ -1281,6 +1309,7 @@ issues.filter_label_no_select=Todos os rótulos
issues.filter_milestone=Etapa issues.filter_milestone=Etapa
issues.filter_milestone_no_select=Todas as etapas issues.filter_milestone_no_select=Todas as etapas
issues.filter_project=Planeamento issues.filter_project=Planeamento
issues.filter_project_all=Todos os planeamentos
issues.filter_project_none=Nenhum planeamento issues.filter_project_none=Nenhum planeamento
issues.filter_assignee=Encarregado issues.filter_assignee=Encarregado
issues.filter_assginee_no_select=Todos os encarregados issues.filter_assginee_no_select=Todos os encarregados
@ -1292,6 +1321,7 @@ issues.filter_type.assigned_to_you=Atribuídas a si
issues.filter_type.created_by_you=Criadas por si issues.filter_type.created_by_you=Criadas por si
issues.filter_type.mentioning_you=Mencionando a si issues.filter_type.mentioning_you=Mencionando a si
issues.filter_type.review_requested=Revisão solicitada issues.filter_type.review_requested=Revisão solicitada
issues.filter_type.reviewed_by_you=Revistos por si
issues.filter_sort=Ordem issues.filter_sort=Ordem
issues.filter_sort.latest=Mais recentes issues.filter_sort.latest=Mais recentes
issues.filter_sort.oldest=Mais antigas issues.filter_sort.oldest=Mais antigas
@ -1313,6 +1343,8 @@ issues.action_milestone=Etapa
issues.action_milestone_no_select=Sem etapa issues.action_milestone_no_select=Sem etapa
issues.action_assignee=Encarregado issues.action_assignee=Encarregado
issues.action_assignee_no_select=Sem encarregado issues.action_assignee_no_select=Sem encarregado
issues.action_check=Marcar/desmarcar
issues.action_check_all=Marcar/desmarcar todos os itens
issues.opened_by=aberta %[1]s por <a href="%[2]s">%[3]s</a> issues.opened_by=aberta %[1]s por <a href="%[2]s">%[3]s</a>
pulls.merged_by=por <a href="%[2]s">%[3]s</a> foi executado %[1]s pulls.merged_by=por <a href="%[2]s">%[3]s</a> foi executado %[1]s
pulls.merged_by_fake=por %[2]s foi executado %[1]s pulls.merged_by_fake=por %[2]s foi executado %[1]s
@ -1366,6 +1398,9 @@ issues.save=Guardar
issues.label_title=Nome do rótulo issues.label_title=Nome do rótulo
issues.label_description=Descrição do rótulo issues.label_description=Descrição do rótulo
issues.label_color=Cor do rótulo issues.label_color=Cor do rótulo
issues.label_exclusive=Exclusivo
issues.label_exclusive_desc=Nomeie o rótulo <code>âmbito/item</code> para torná-lo mutuamente exclusivo com outros rótulos do <code>âmbito/</code>.
issues.label_exclusive_warning=Quaisquer rótulos com âmbito que estejam em conflito irão ser removidos ao editar os rótulos de uma questão ou de um pedido de integração.
issues.label_count=%d rótulos issues.label_count=%d rótulos
issues.label_open_issues=%d questões abertas issues.label_open_issues=%d questões abertas
issues.label_edit=Editar issues.label_edit=Editar
@ -1619,6 +1654,8 @@ pulls.reopened_at=`reabriu este pedido de integração <a id="%[1]s" href="#%[1]
pulls.merge_instruction_hint=`Também pode ver as <a class="show-instruction">instruções para a linha de comandos</a>.` pulls.merge_instruction_hint=`Também pode ver as <a class="show-instruction">instruções para a linha de comandos</a>.`
pulls.merge_instruction_step1_desc=No seu repositório, crie um novo ramo e teste as modificações. pulls.merge_instruction_step1_desc=No seu repositório, crie um novo ramo e teste as modificações.
pulls.merge_instruction_step2_desc=Integre as modificações e envie para o Gitea. pulls.merge_instruction_step2_desc=Integre as modificações e envie para o Gitea.
pulls.clear_merge_message=Apagar mensagem de integração
pulls.clear_merge_message_hint=Apagar a mensagem de integração apenas remove o conteúdo da mensagem de cometimento e mantém os rodapés do git, tais como "Co-Autorado-Por …".
pulls.auto_merge_button_when_succeed=(quando as verificações forem bem-sucedidas) pulls.auto_merge_button_when_succeed=(quando as verificações forem bem-sucedidas)
pulls.auto_merge_when_succeed=Integrar automaticamente quando todas as verificações forem bem-sucedidas pulls.auto_merge_when_succeed=Integrar automaticamente quando todas as verificações forem bem-sucedidas
@ -1810,6 +1847,7 @@ settings.mirror_sync_in_progress=A sincronização da réplica está em andament
settings.site=Sítio web settings.site=Sítio web
settings.update_settings=Modificar configurações settings.update_settings=Modificar configurações
settings.branches.update_default_branch=Definir o ramo principal settings.branches.update_default_branch=Definir o ramo principal
settings.branches.add_new_rule=Adicionar nova regra
settings.advanced_settings=Configurações avançadas settings.advanced_settings=Configurações avançadas
settings.wiki_desc=Habilitar wiki do repositório settings.wiki_desc=Habilitar wiki do repositório
settings.use_internal_wiki=Usar o wiki nativo settings.use_internal_wiki=Usar o wiki nativo
@ -1839,8 +1877,11 @@ settings.pulls.ignore_whitespace=Ignorar espaços em branco nos conflitos
settings.pulls.enable_autodetect_manual_merge=Habilitar a identificação automática de integrações manuais (obs.: nalguns casos especiais a avaliação pode ser errada) settings.pulls.enable_autodetect_manual_merge=Habilitar a identificação automática de integrações manuais (obs.: nalguns casos especiais a avaliação pode ser errada)
settings.pulls.allow_rebase_update=Habilitar a modificação do ramo do pedido de integração através da mudança de base settings.pulls.allow_rebase_update=Habilitar a modificação do ramo do pedido de integração através da mudança de base
settings.pulls.default_delete_branch_after_merge=Eliminar o ramo do pedido de integração depois de finalizada a integração, como predefinição settings.pulls.default_delete_branch_after_merge=Eliminar o ramo do pedido de integração depois de finalizada a integração, como predefinição
settings.pulls.default_allow_edits_from_maintainers=Permitir, por padrão, que os responsáveis editem
settings.releases_desc=Habilitar lançamentos no repositório
settings.packages_desc=Habilitar o registo de pacotes do repositório settings.packages_desc=Habilitar o registo de pacotes do repositório
settings.projects_desc=Habilitar planeamentos no repositório settings.projects_desc=Habilitar planeamentos no repositório
settings.actions_desc=Habilitar operações no repositório
settings.admin_settings=Configurações do administrador settings.admin_settings=Configurações do administrador
settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório
settings.admin_code_indexer=Indexador de código settings.admin_code_indexer=Indexador de código
@ -2970,6 +3011,7 @@ monitor.queue.pool.cancel_desc=Deixar uma fila sem quaisquer grupos de trabalhad
notices.system_notice_list=Notificações do sistema notices.system_notice_list=Notificações do sistema
notices.view_detail_header=Ver os detalhes da notificação notices.view_detail_header=Ver os detalhes da notificação
notices.operations=Operações
notices.select_all=Marcar todas notices.select_all=Marcar todas
notices.deselect_all=Desmarcar todas notices.deselect_all=Desmarcar todas
notices.inverse_selection=Inverter as marcações notices.inverse_selection=Inverter as marcações
@ -3170,6 +3212,15 @@ settings.delete.notice=Está prestes a eliminar %s (%s). Esta operação é irre
settings.delete.success=O pacote foi eliminado. settings.delete.success=O pacote foi eliminado.
settings.delete.error=Falhou a eliminação do pacote. settings.delete.error=Falhou a eliminação do pacote.
owner.settings.cleanuprules.enabled=Habilitado owner.settings.cleanuprules.enabled=Habilitado
owner.settings.cleanuprules.keep.count=Manter a mais recente
owner.settings.cleanuprules.keep.count.1=1 versão por pacote
owner.settings.cleanuprules.keep.count.n=%d versões por pacote
owner.settings.cleanuprules.keep.pattern=Manter as versões correspondentes
owner.settings.cleanuprules.keep.pattern.container=A <code>última</code> versão será sempre mantida para pacotes de contentor.
owner.settings.cleanuprules.remove.title=Versões que correspondam a estas regras serão removidos, a não ser que a regra acima diga para os manter.
owner.settings.cleanuprules.remove.days=Remover versões mais antigas do que
owner.settings.cleanuprules.remove.pattern=Remover as versões correspondentes
owner.settings.cleanuprules.success.update=A regra de limpeza foi modificada.
[secrets] [secrets]
value=Valor value=Valor
@ -3187,8 +3238,16 @@ runners.labels=Rótulos
runners.task_list.run=Executar runners.task_list.run=Executar
runners.task_list.repository=Repositório runners.task_list.repository=Repositório
runners.task_list.commit=Cometimento runners.task_list.commit=Cometimento
runners.delete_runner=Eliminar o executor
runners.status.idle=Parada
runners.status.active=Em funcionamento runners.status.active=Em funcionamento
runners.status.offline=Desconectada
runs.all_workflows=Todos os fluxos de trabalho
runs.open_tab=%d abertas
runs.closed_tab=%d fechadas
runs.commit=Cometimento runs.commit=Cometimento
runs.pushed_by=Enviada por
need_approval_desc=É necessária aprovação para executar fluxos de trabalho para a derivação do pedido de integração.

View File

@ -12,6 +12,7 @@ import (
"code.gitea.io/gitea/modules/actions" "code.gitea.io/gitea/modules/actions"
"code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
actions_service "code.gitea.io/gitea/services/actions" actions_service "code.gitea.io/gitea/services/actions"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1" runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
@ -55,9 +56,10 @@ func (s *Service) Register(
} }
// create new runner // create new runner
name, _ := util.SplitStringAtByteN(req.Msg.Name, 255)
runner := &actions_model.ActionRunner{ runner := &actions_model.ActionRunner{
UUID: gouuid.New().String(), UUID: gouuid.New().String(),
Name: req.Msg.Name, Name: name,
OwnerID: runnerToken.OwnerID, OwnerID: runnerToken.OwnerID,
RepoID: runnerToken.RepoID, RepoID: runnerToken.RepoID,
AgentLabels: req.Msg.AgentLabels, AgentLabels: req.Msg.AgentLabels,

View File

@ -45,7 +45,7 @@ func ListUnadoptedRepositories(ctx *context.APIContext) {
if listOptions.Page == 0 { if listOptions.Page == 0 {
listOptions.Page = 1 listOptions.Page = 1
} }
repoNames, count, err := repo_service.ListUnadoptedRepositories(ctx.FormString("query"), &listOptions) repoNames, count, err := repo_service.ListUnadoptedRepositories(ctx, ctx.FormString("query"), &listOptions)
if err != nil { if err != nil {
ctx.InternalServerError(err) ctx.InternalServerError(err)
return return
@ -109,7 +109,7 @@ func AdoptRepository(ctx *context.APIContext) {
ctx.NotFound() ctx.NotFound()
return return
} }
if _, err := repo_service.AdoptRepository(ctx.Doer, ctxUser, repo_module.CreateRepoOptions{ if _, err := repo_service.AdoptRepository(ctx, ctx.Doer, ctxUser, repo_module.CreateRepoOptions{
Name: repoName, Name: repoName,
IsPrivate: true, IsPrivate: true,
}); err != nil { }); err != nil {
@ -172,7 +172,7 @@ func DeleteUnadoptedRepository(ctx *context.APIContext) {
return return
} }
if err := repo_service.DeleteUnadoptedRepository(ctx.Doer, ctxUser, repoName); err != nil { if err := repo_service.DeleteUnadoptedRepository(ctx, ctx.Doer, ctxUser, repoName); err != nil {
ctx.InternalServerError(err) ctx.InternalServerError(err)
return return
} }

View File

@ -118,7 +118,7 @@ func DeleteBranch(ctx *context.APIContext) {
branchName := ctx.Params("*") branchName := ctx.Params("*")
if err := repo_service.DeleteBranch(ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil { if err := repo_service.DeleteBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
switch { switch {
case git.IsErrBranchNotExist(err): case git.IsErrBranchNotExist(err):
ctx.NotFound(err) ctx.NotFound(err)

View File

@ -904,7 +904,7 @@ func MergePullRequest(ctx *context.APIContext) {
} }
defer headRepo.Close() defer headRepo.Close()
} }
if err := repo_service.DeleteBranch(ctx.Doer, pr.HeadRepo, headRepo, pr.HeadBranch); err != nil { if err := repo_service.DeleteBranch(ctx, ctx.Doer, pr.HeadRepo, headRepo, pr.HeadBranch); err != nil {
switch { switch {
case git.IsErrBranchNotExist(err): case git.IsErrBranchNotExist(err):
ctx.NotFound(err) ctx.NotFound(err)

View File

@ -230,7 +230,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
if opt.AutoInit && opt.Readme == "" { if opt.AutoInit && opt.Readme == "" {
opt.Readme = "Default" opt.Readme = "Default"
} }
repo, err := repo_service.CreateRepository(ctx.Doer, owner, repo_module.CreateRepoOptions{ repo, err := repo_service.CreateRepository(ctx, ctx.Doer, owner, repo_module.CreateRepoOptions{
Name: opt.Name, Name: opt.Name,
Description: opt.Description, Description: opt.Description,
IssueLabels: opt.IssueLabels, IssueLabels: opt.IssueLabels,
@ -393,7 +393,7 @@ func Generate(ctx *context.APIContext) {
} }
} }
repo, err := repo_service.GenerateRepository(ctx.Doer, ctxUser, ctx.Repo.Repository, opts) repo, err := repo_service.GenerateRepository(ctx, ctx.Doer, ctxUser, ctx.Repo.Repository, opts)
if err != nil { if err != nil {
if repo_model.IsErrRepoAlreadyExist(err) { if repo_model.IsErrRepoAlreadyExist(err) {
ctx.Error(http.StatusConflict, "", "The repository with the same name already exists.") ctx.Error(http.StatusConflict, "", "The repository with the same name already exists.")
@ -637,7 +637,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
} }
// Check if repository name has been changed and not just a case change // Check if repository name has been changed and not just a case change
if repo.LowerName != strings.ToLower(newRepoName) { if repo.LowerName != strings.ToLower(newRepoName) {
if err := repo_service.ChangeRepositoryName(ctx.Doer, repo, newRepoName); err != nil { if err := repo_service.ChangeRepositoryName(ctx, ctx.Doer, repo, newRepoName); err != nil {
switch { switch {
case repo_model.IsErrRepoAlreadyExist(err): case repo_model.IsErrRepoAlreadyExist(err):
ctx.Error(http.StatusUnprocessableEntity, fmt.Sprintf("repo name is already taken [name: %s]", newRepoName), err) ctx.Error(http.StatusUnprocessableEntity, fmt.Sprintf("repo name is already taken [name: %s]", newRepoName), err)
@ -714,7 +714,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
repo.DefaultBranch = *opts.DefaultBranch repo.DefaultBranch = *opts.DefaultBranch
} }
if err := repo_service.UpdateRepository(repo, visibilityChanged); err != nil { if err := repo_service.UpdateRepository(ctx, repo, visibilityChanged); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateRepository", err) ctx.Error(http.StatusInternalServerError, "UpdateRepository", err)
return err return err
} }

View File

@ -368,7 +368,7 @@ func ServCommand(ctx *context.PrivateContext) {
return return
} }
repo, err = repo_service.PushCreateRepo(user, owner, results.RepoName) repo, err = repo_service.PushCreateRepo(ctx, user, owner, results.RepoName)
if err != nil { if err != nil {
log.Error("pushCreateRepo: %v", err) log.Error("pushCreateRepo: %v", err)
ctx.JSON(http.StatusNotFound, private.ErrServCommand{ ctx.JSON(http.StatusNotFound, private.ErrServCommand{

View File

@ -96,7 +96,7 @@ func UnadoptedRepos(ctx *context.Context) {
} }
ctx.Data["Keyword"] = q ctx.Data["Keyword"] = q
repoNames, count, err := repo_service.ListUnadoptedRepositories(q, &opts) repoNames, count, err := repo_service.ListUnadoptedRepositories(ctx, q, &opts)
if err != nil { if err != nil {
ctx.ServerError("ListUnadoptedRepositories", err) ctx.ServerError("ListUnadoptedRepositories", err)
} }
@ -148,7 +148,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
if has || !isDir { if has || !isDir {
// Fallthrough to failure mode // Fallthrough to failure mode
} else if action == "adopt" { } else if action == "adopt" {
if _, err := repo_service.AdoptRepository(ctx.Doer, ctxUser, repo_module.CreateRepoOptions{ if _, err := repo_service.AdoptRepository(ctx, ctx.Doer, ctxUser, repo_module.CreateRepoOptions{
Name: dirSplit[1], Name: dirSplit[1],
IsPrivate: true, IsPrivate: true,
}); err != nil { }); err != nil {
@ -157,7 +157,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
} }
ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir)) ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir))
} else if action == "delete" { } else if action == "delete" {
if err := repo_service.DeleteUnadoptedRepository(ctx.Doer, ctxUser, dirSplit[1]); err != nil { if err := repo_service.DeleteUnadoptedRepository(ctx, ctx.Doer, ctxUser, dirSplit[1]); err != nil {
ctx.ServerError("repository.AdoptRepository", err) ctx.ServerError("repository.AdoptRepository", err)
return return
} }

View File

@ -137,7 +137,7 @@ func SettingsPost(ctx *context.Context) {
} }
for _, repo := range repos { for _, repo := range repos {
repo.OwnerName = org.Name repo.OwnerName = org.Name
if err := repo_service.UpdateRepository(repo, true); err != nil { if err := repo_service.UpdateRepository(ctx, repo, true); err != nil {
ctx.ServerError("UpdateRepository", err) ctx.ServerError("UpdateRepository", err)
return return
} }

View File

@ -91,7 +91,7 @@ func DeleteBranchPost(ctx *context.Context) {
defer redirect(ctx) defer redirect(ctx)
branchName := ctx.FormString("name") branchName := ctx.FormString("name")
if err := repo_service.DeleteBranch(ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil { if err := repo_service.DeleteBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
switch { switch {
case git.IsErrBranchNotExist(err): case git.IsErrBranchNotExist(err):
log.Debug("DeleteBranch: Can't delete non existing branch '%s'", branchName) log.Debug("DeleteBranch: Can't delete non existing branch '%s'", branchName)

View File

@ -276,7 +276,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
return return
} }
repo, err = repo_service.PushCreateRepo(ctx.Doer, owner, reponame) repo, err = repo_service.PushCreateRepo(ctx, ctx.Doer, owner, reponame)
if err != nil { if err != nil {
log.Error("pushCreateRepo: %v", err) log.Error("pushCreateRepo: %v", err)
ctx.Status(http.StatusNotFound) ctx.Status(http.StatusNotFound)

View File

@ -589,7 +589,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
return return
} }
teamReviewers, err = repo_service.GetReviewerTeams(repo) teamReviewers, err = repo_service.GetReviewerTeams(ctx, repo)
if err != nil { if err != nil {
ctx.ServerError("GetReviewerTeams", err) ctx.ServerError("GetReviewerTeams", err)
return return

View File

@ -1399,7 +1399,7 @@ func CleanUpPullRequest(ctx *context.Context) {
func deleteBranch(ctx *context.Context, pr *issues_model.PullRequest, gitRepo *git.Repository) { func deleteBranch(ctx *context.Context, pr *issues_model.PullRequest, gitRepo *git.Repository) {
fullBranchName := pr.HeadRepo.FullName() + ":" + pr.HeadBranch fullBranchName := pr.HeadRepo.FullName() + ":" + pr.HeadBranch
if err := repo_service.DeleteBranch(ctx.Doer, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil { if err := repo_service.DeleteBranch(ctx, ctx.Doer, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil {
switch { switch {
case git.IsErrBranchNotExist(err): case git.IsErrBranchNotExist(err):
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName)) ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))

View File

@ -248,14 +248,14 @@ func CreatePost(ctx *context.Context) {
return return
} }
repo, err = repo_service.GenerateRepository(ctx.Doer, ctxUser, templateRepo, opts) repo, err = repo_service.GenerateRepository(ctx, ctx.Doer, ctxUser, templateRepo, opts)
if err == nil { if err == nil {
log.Trace("Repository generated [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name) log.Trace("Repository generated [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
ctx.Redirect(repo.Link()) ctx.Redirect(repo.Link())
return return
} }
} else { } else {
repo, err = repo_service.CreateRepository(ctx.Doer, ctxUser, repo_module.CreateRepoOptions{ repo, err = repo_service.CreateRepository(ctx, ctx.Doer, ctxUser, repo_module.CreateRepoOptions{
Name: form.RepoName, Name: form.RepoName,
Description: form.Description, Description: form.Description,
Gitignores: form.Gitignores, Gitignores: form.Gitignores,
@ -302,7 +302,7 @@ func Action(ctx *context.Context) {
ctx.Repo.Repository.Description = ctx.FormString("desc") ctx.Repo.Repository.Description = ctx.FormString("desc")
ctx.Repo.Repository.Website = ctx.FormString("site") ctx.Repo.Repository.Website = ctx.FormString("site")
err = repo_service.UpdateRepository(ctx.Repo.Repository, false) err = repo_service.UpdateRepository(ctx, ctx.Repo.Repository, false)
} }
if err != nil { if err != nil {

View File

@ -134,7 +134,7 @@ func SettingsPost(ctx *context.Context) {
ctx.Repo.GitRepo.Close() ctx.Repo.GitRepo.Close()
ctx.Repo.GitRepo = nil ctx.Repo.GitRepo = nil
} }
if err := repo_service.ChangeRepositoryName(ctx.Doer, repo, newRepoName); err != nil { if err := repo_service.ChangeRepositoryName(ctx, ctx.Doer, repo, newRepoName); err != nil {
ctx.Data["Err_RepoName"] = true ctx.Data["Err_RepoName"] = true
switch { switch {
case repo_model.IsErrRepoAlreadyExist(err): case repo_model.IsErrRepoAlreadyExist(err):
@ -183,7 +183,7 @@ func SettingsPost(ctx *context.Context) {
} }
repo.IsPrivate = form.Private repo.IsPrivate = form.Private
if err := repo_service.UpdateRepository(repo, visibilityChanged); err != nil { if err := repo_service.UpdateRepository(ctx, repo, visibilityChanged); err != nil {
ctx.ServerError("UpdateRepository", err) ctx.ServerError("UpdateRepository", err)
return return
} }
@ -541,7 +541,7 @@ func SettingsPost(ctx *context.Context) {
return return
} }
if repoChanged { if repoChanged {
if err := repo_service.UpdateRepository(repo, false); err != nil { if err := repo_service.UpdateRepository(ctx, repo, false); err != nil {
ctx.ServerError("UpdateRepository", err) ctx.ServerError("UpdateRepository", err)
return return
} }
@ -560,7 +560,7 @@ func SettingsPost(ctx *context.Context) {
} }
if changed { if changed {
if err := repo_service.UpdateRepository(repo, false); err != nil { if err := repo_service.UpdateRepository(ctx, repo, false); err != nil {
ctx.ServerError("UpdateRepository", err) ctx.ServerError("UpdateRepository", err)
return return
} }
@ -580,7 +580,7 @@ func SettingsPost(ctx *context.Context) {
repo.IsFsckEnabled = form.EnableHealthCheck repo.IsFsckEnabled = form.EnableHealthCheck
} }
if err := repo_service.UpdateRepository(repo, false); err != nil { if err := repo_service.UpdateRepository(ctx, repo, false); err != nil {
ctx.ServerError("UpdateRepository", err) ctx.ServerError("UpdateRepository", err)
return return
} }
@ -672,7 +672,7 @@ func SettingsPost(ctx *context.Context) {
return return
} }
if err := repo_service.ConvertForkToNormalRepository(repo); err != nil { if err := repo_service.ConvertForkToNormalRepository(ctx, repo); err != nil {
log.Error("Unable to convert repository %-v from fork. Error: %v", repo, err) log.Error("Unable to convert repository %-v from fork. Error: %v", repo, err)
ctx.ServerError("Convert Fork", err) ctx.ServerError("Convert Fork", err)
return return
@ -1244,7 +1244,7 @@ func UpdateAvatarSetting(ctx *context.Context, form forms.AvatarForm) error {
if !(st.IsImage() && !st.IsSvgImage()) { if !(st.IsImage() && !st.IsSvgImage()) {
return errors.New(ctx.Tr("settings.uploaded_avatar_not_a_image")) return errors.New(ctx.Tr("settings.uploaded_avatar_not_a_image"))
} }
if err = repo_service.UploadAvatar(ctxRepo, data); err != nil { if err = repo_service.UploadAvatar(ctx, ctxRepo, data); err != nil {
return fmt.Errorf("UploadAvatar: %w", err) return fmt.Errorf("UploadAvatar: %w", err)
} }
return nil return nil
@ -1264,7 +1264,7 @@ func SettingsAvatar(ctx *context.Context) {
// SettingsDeleteAvatar delete repository avatar // SettingsDeleteAvatar delete repository avatar
func SettingsDeleteAvatar(ctx *context.Context) { func SettingsDeleteAvatar(ctx *context.Context) {
if err := repo_service.DeleteAvatar(ctx.Repo.Repository); err != nil { if err := repo_service.DeleteAvatar(ctx, ctx.Repo.Repository); err != nil {
ctx.Flash.Error(fmt.Sprintf("DeleteAvatar: %v", err)) ctx.Flash.Error(fmt.Sprintf("DeleteAvatar: %v", err))
} }
ctx.Redirect(ctx.Repo.RepoLink + "/settings") ctx.Redirect(ctx.Repo.RepoLink + "/settings")

View File

@ -356,7 +356,7 @@ func RenameBranchPost(ctx *context.Context) {
return return
} }
msg, err := repository.RenameBranch(ctx.Repo.Repository, ctx.Doer, ctx.Repo.GitRepo, form.From, form.To) msg, err := repository.RenameBranch(ctx, ctx.Repo.Repository, ctx.Doer, ctx.Repo.GitRepo, form.From, form.To)
if err != nil { if err != nil {
ctx.ServerError("RenameBranch", err) ctx.ServerError("RenameBranch", err)
return return

View File

@ -45,7 +45,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
if has || !isDir { if has || !isDir {
// Fallthrough to failure mode // Fallthrough to failure mode
} else if action == "adopt" && allowAdopt { } else if action == "adopt" && allowAdopt {
if _, err := repo_service.AdoptRepository(ctxUser, ctxUser, repo_module.CreateRepoOptions{ if _, err := repo_service.AdoptRepository(ctx, ctxUser, ctxUser, repo_module.CreateRepoOptions{
Name: dir, Name: dir,
IsPrivate: true, IsPrivate: true,
}); err != nil { }); err != nil {
@ -54,7 +54,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
} }
ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir)) ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir))
} else if action == "delete" && allowDelete { } else if action == "delete" && allowDelete {
if err := repo_service.DeleteUnadoptedRepository(ctxUser, ctxUser, dir); err != nil { if err := repo_service.DeleteUnadoptedRepository(ctx, ctxUser, ctxUser, dir); err != nil {
ctx.ServerError("repository.AdoptRepository", err) ctx.ServerError("repository.AdoptRepository", err)
return return
} }

View File

@ -26,7 +26,7 @@ import (
) )
// AdoptRepository adopts pre-existing repository files for the user/organization. // AdoptRepository adopts pre-existing repository files for the user/organization.
func AdoptRepository(doer, u *user_model.User, opts repo_module.CreateRepoOptions) (*repo_model.Repository, error) { func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts repo_module.CreateRepoOptions) (*repo_model.Repository, error) {
if !doer.IsAdmin && !u.CanCreateRepo() { if !doer.IsAdmin && !u.CanCreateRepo() {
return nil, repo_model.ErrReachLimitOfRepo{ return nil, repo_model.ErrReachLimitOfRepo{
Limit: u.MaxRepoCreation, Limit: u.MaxRepoCreation,
@ -53,7 +53,7 @@ func AdoptRepository(doer, u *user_model.User, opts repo_module.CreateRepoOption
IsEmpty: !opts.AutoInit, IsEmpty: !opts.AutoInit,
} }
if err := db.WithTx(db.DefaultContext, func(ctx context.Context) error { if err := db.WithTx(ctx, func(ctx context.Context) error {
repoPath := repo_model.RepoPath(u.Name, repo.Name) repoPath := repo_model.RepoPath(u.Name, repo.Name)
isExist, err := util.IsExist(repoPath) isExist, err := util.IsExist(repoPath)
if err != nil { if err != nil {
@ -95,7 +95,7 @@ func AdoptRepository(doer, u *user_model.User, opts repo_module.CreateRepoOption
return nil, err return nil, err
} }
notification.NotifyCreateRepository(db.DefaultContext, doer, u, repo) notification.NotifyCreateRepository(ctx, doer, u, repo)
return repo, nil return repo, nil
} }
@ -188,7 +188,7 @@ func adoptRepository(ctx context.Context, repoPath string, u *user_model.User, r
} }
// DeleteUnadoptedRepository deletes unadopted repository files from the filesystem // DeleteUnadoptedRepository deletes unadopted repository files from the filesystem
func DeleteUnadoptedRepository(doer, u *user_model.User, repoName string) error { func DeleteUnadoptedRepository(ctx context.Context, doer, u *user_model.User, repoName string) error {
if err := repo_model.IsUsableRepoName(repoName); err != nil { if err := repo_model.IsUsableRepoName(repoName); err != nil {
return err return err
} }
@ -206,7 +206,7 @@ func DeleteUnadoptedRepository(doer, u *user_model.User, repoName string) error
} }
} }
if exist, err := repo_model.IsRepositoryExist(db.DefaultContext, u, repoName); err != nil { if exist, err := repo_model.IsRepositoryExist(ctx, u, repoName); err != nil {
return err return err
} else if exist { } else if exist {
return repo_model.ErrRepoAlreadyExist{ return repo_model.ErrRepoAlreadyExist{
@ -232,11 +232,11 @@ func (unadopted *unadoptedRepositories) add(repository string) {
unadopted.index++ unadopted.index++
} }
func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unadopted *unadoptedRepositories) error { func checkUnadoptedRepositories(ctx context.Context, userName string, repoNamesToCheck []string, unadopted *unadoptedRepositories) error {
if len(repoNamesToCheck) == 0 { if len(repoNamesToCheck) == 0 {
return nil return nil
} }
ctxUser, err := user_model.GetUserByName(db.DefaultContext, userName) ctxUser, err := user_model.GetUserByName(ctx, userName)
if err != nil { if err != nil {
if user_model.IsErrUserNotExist(err) { if user_model.IsErrUserNotExist(err) {
log.Debug("Missing user: %s", userName) log.Debug("Missing user: %s", userName)
@ -271,7 +271,7 @@ func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unad
} }
// ListUnadoptedRepositories lists all the unadopted repositories that match the provided query // ListUnadoptedRepositories lists all the unadopted repositories that match the provided query
func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, int, error) { func ListUnadoptedRepositories(ctx context.Context, query string, opts *db.ListOptions) ([]string, int, error) {
globUser, _ := glob.Compile("*") globUser, _ := glob.Compile("*")
globRepo, _ := glob.Compile("*") globRepo, _ := glob.Compile("*")
@ -315,7 +315,7 @@ func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, in
if !strings.ContainsRune(path[len(root)+1:], filepath.Separator) { if !strings.ContainsRune(path[len(root)+1:], filepath.Separator) {
// Got a new user // Got a new user
if err = checkUnadoptedRepositories(userName, repoNamesToCheck, unadopted); err != nil { if err = checkUnadoptedRepositories(ctx, userName, repoNamesToCheck, unadopted); err != nil {
return err return err
} }
repoNamesToCheck = repoNamesToCheck[:0] repoNamesToCheck = repoNamesToCheck[:0]
@ -338,7 +338,7 @@ func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, in
repoNamesToCheck = append(repoNamesToCheck, name) repoNamesToCheck = append(repoNamesToCheck, name)
if len(repoNamesToCheck) >= setting.Database.IterateBufferSize { if len(repoNamesToCheck) >= setting.Database.IterateBufferSize {
if err = checkUnadoptedRepositories(userName, repoNamesToCheck, unadopted); err != nil { if err = checkUnadoptedRepositories(ctx, userName, repoNamesToCheck, unadopted); err != nil {
return err return err
} }
repoNamesToCheck = repoNamesToCheck[:0] repoNamesToCheck = repoNamesToCheck[:0]
@ -349,7 +349,7 @@ func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, in
return nil, 0, err return nil, 0, err
} }
if err := checkUnadoptedRepositories(userName, repoNamesToCheck, unadopted); err != nil { if err := checkUnadoptedRepositories(ctx, userName, repoNamesToCheck, unadopted); err != nil {
return nil, 0, err return nil, 0, err
} }

View File

@ -39,7 +39,7 @@ func TestCheckUnadoptedRepositories(t *testing.T) {
// Non existent user // Non existent user
// //
unadopted := &unadoptedRepositories{start: 0, end: 100} unadopted := &unadoptedRepositories{start: 0, end: 100}
err := checkUnadoptedRepositories("notauser", []string{"repo"}, unadopted) err := checkUnadoptedRepositories(db.DefaultContext, "notauser", []string{"repo"}, unadopted)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, 0, len(unadopted.repositories)) assert.Equal(t, 0, len(unadopted.repositories))
// //
@ -50,14 +50,14 @@ func TestCheckUnadoptedRepositories(t *testing.T) {
repoName := "repo2" repoName := "repo2"
unadoptedRepoName := "unadopted" unadoptedRepoName := "unadopted"
unadopted = &unadoptedRepositories{start: 0, end: 100} unadopted = &unadoptedRepositories{start: 0, end: 100}
err = checkUnadoptedRepositories(userName, []string{repoName, unadoptedRepoName}, unadopted) err = checkUnadoptedRepositories(db.DefaultContext, userName, []string{repoName, unadoptedRepoName}, unadopted)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, []string{path.Join(userName, unadoptedRepoName)}, unadopted.repositories) assert.Equal(t, []string{path.Join(userName, unadoptedRepoName)}, unadopted.repositories)
// //
// Existing (adopted) repository is not returned // Existing (adopted) repository is not returned
// //
unadopted = &unadoptedRepositories{start: 0, end: 100} unadopted = &unadoptedRepositories{start: 0, end: 100}
err = checkUnadoptedRepositories(userName, []string{repoName}, unadopted) err = checkUnadoptedRepositories(db.DefaultContext, userName, []string{repoName}, unadopted)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, 0, len(unadopted.repositories)) assert.Equal(t, 0, len(unadopted.repositories))
assert.Equal(t, 0, unadopted.index) assert.Equal(t, 0, unadopted.index)
@ -72,13 +72,13 @@ func TestListUnadoptedRepositories_ListOptions(t *testing.T) {
} }
opts := db.ListOptions{Page: 1, PageSize: 1} opts := db.ListOptions{Page: 1, PageSize: 1}
repoNames, count, err := ListUnadoptedRepositories("", &opts) repoNames, count, err := ListUnadoptedRepositories(db.DefaultContext, "", &opts)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, 2, count) assert.Equal(t, 2, count)
assert.Equal(t, unadoptedList[0], repoNames[0]) assert.Equal(t, unadoptedList[0], repoNames[0])
opts = db.ListOptions{Page: 2, PageSize: 1} opts = db.ListOptions{Page: 2, PageSize: 1}
repoNames, count, err = ListUnadoptedRepositories("", &opts) repoNames, count, err = ListUnadoptedRepositories(db.DefaultContext, "", &opts)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, 2, count) assert.Equal(t, 2, count)
assert.Equal(t, unadoptedList[1], repoNames[0]) assert.Equal(t, unadoptedList[1], repoNames[0])

View File

@ -20,7 +20,7 @@ import (
// UploadAvatar saves custom avatar for repository. // UploadAvatar saves custom avatar for repository.
// FIXME: split uploads to different subdirs in case we have massive number of repos. // FIXME: split uploads to different subdirs in case we have massive number of repos.
func UploadAvatar(repo *repo_model.Repository, data []byte) error { func UploadAvatar(ctx context.Context, repo *repo_model.Repository, data []byte) error {
m, err := avatar.Prepare(data) m, err := avatar.Prepare(data)
if err != nil { if err != nil {
return err return err
@ -31,7 +31,7 @@ func UploadAvatar(repo *repo_model.Repository, data []byte) error {
return nil return nil
} }
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -65,7 +65,7 @@ func UploadAvatar(repo *repo_model.Repository, data []byte) error {
} }
// DeleteAvatar deletes the repos's custom avatar. // DeleteAvatar deletes the repos's custom avatar.
func DeleteAvatar(repo *repo_model.Repository) error { func DeleteAvatar(ctx context.Context, repo *repo_model.Repository) error {
// Avatar not exists // Avatar not exists
if len(repo.Avatar) == 0 { if len(repo.Avatar) == 0 {
return nil return nil
@ -74,7 +74,7 @@ func DeleteAvatar(repo *repo_model.Repository) error {
avatarPath := repo.CustomAvatarRelativePath() avatarPath := repo.CustomAvatarRelativePath()
log.Trace("DeleteAvatar[%d]: %s", repo.ID, avatarPath) log.Trace("DeleteAvatar[%d]: %s", repo.ID, avatarPath)
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -102,7 +102,7 @@ func RemoveRandomAvatars(ctx context.Context) error {
} }
stringifiedID := strconv.FormatInt(repository.ID, 10) stringifiedID := strconv.FormatInt(repository.ID, 10)
if repository.Avatar == stringifiedID { if repository.Avatar == stringifiedID {
return DeleteAvatar(repository) return DeleteAvatar(ctx, repository)
} }
return nil return nil
}) })

View File

@ -9,6 +9,7 @@ import (
"image/png" "image/png"
"testing" "testing"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/avatar" "code.gitea.io/gitea/modules/avatar"
@ -25,7 +26,7 @@ func TestUploadAvatar(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
err := UploadAvatar(repo, buff.Bytes()) err := UploadAvatar(db.DefaultContext, repo, buff.Bytes())
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, avatar.HashAvatar(10, buff.Bytes()), repo.Avatar) assert.Equal(t, avatar.HashAvatar(10, buff.Bytes()), repo.Avatar)
} }
@ -39,7 +40,7 @@ func TestUploadBigAvatar(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
err := UploadAvatar(repo, buff.Bytes()) err := UploadAvatar(db.DefaultContext, repo, buff.Bytes())
assert.Error(t, err) assert.Error(t, err)
} }
@ -52,10 +53,10 @@ func TestDeleteAvatar(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
err := UploadAvatar(repo, buff.Bytes()) err := UploadAvatar(db.DefaultContext, repo, buff.Bytes())
assert.NoError(t, err) assert.NoError(t, err)
err = DeleteAvatar(repo) err = DeleteAvatar(db.DefaultContext, repo)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "", repo.Avatar) assert.Equal(t, "", repo.Avatar)

View File

@ -10,7 +10,6 @@ import (
"strings" "strings"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
@ -106,7 +105,7 @@ func CreateNewBranchFromCommit(ctx context.Context, doer *user_model.User, repo
} }
// RenameBranch rename a branch // RenameBranch rename a branch
func RenameBranch(repo *repo_model.Repository, doer *user_model.User, gitRepo *git.Repository, from, to string) (string, error) { func RenameBranch(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, gitRepo *git.Repository, from, to string) (string, error) {
if from == to { if from == to {
return "target_exist", nil return "target_exist", nil
} }
@ -119,7 +118,7 @@ func RenameBranch(repo *repo_model.Repository, doer *user_model.User, gitRepo *g
return "from_not_exist", nil return "from_not_exist", nil
} }
if err := git_model.RenameBranch(db.DefaultContext, repo, from, to, func(isDefault bool) error { if err := git_model.RenameBranch(ctx, repo, from, to, func(isDefault bool) error {
err2 := gitRepo.RenameBranch(from, to) err2 := gitRepo.RenameBranch(from, to)
if err2 != nil { if err2 != nil {
return err2 return err2
@ -141,8 +140,8 @@ func RenameBranch(repo *repo_model.Repository, doer *user_model.User, gitRepo *g
return "", err return "", err
} }
notification.NotifyDeleteRef(db.DefaultContext, doer, repo, "branch", git.BranchPrefix+from) notification.NotifyDeleteRef(ctx, doer, repo, "branch", git.BranchPrefix+from)
notification.NotifyCreateRef(db.DefaultContext, doer, repo, "branch", git.BranchPrefix+to, refID) notification.NotifyCreateRef(ctx, doer, repo, "branch", git.BranchPrefix+to, refID)
return "", nil return "", nil
} }
@ -153,12 +152,12 @@ var (
) )
// DeleteBranch delete branch // DeleteBranch delete branch
func DeleteBranch(doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, branchName string) error { func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, branchName string) error {
if branchName == repo.DefaultBranch { if branchName == repo.DefaultBranch {
return ErrBranchIsDefault return ErrBranchIsDefault
} }
isProtected, err := git_model.IsBranchProtected(db.DefaultContext, repo.ID, branchName) isProtected, err := git_model.IsBranchProtected(ctx, repo.ID, branchName)
if err != nil { if err != nil {
return err return err
} }
@ -195,7 +194,7 @@ func DeleteBranch(doer *user_model.User, repo *repo_model.Repository, gitRepo *g
log.Error("Update: %v", err) log.Error("Update: %v", err)
} }
if err := git_model.AddDeletedBranch(db.DefaultContext, repo.ID, branchName, commit.ID.String(), doer.ID); err != nil { if err := git_model.AddDeletedBranch(ctx, repo.ID, branchName, commit.ID.String(), doer.ID); err != nil {
log.Warn("AddDeletedBranch: %v", err) log.Warn("AddDeletedBranch: %v", err)
} }

View File

@ -189,8 +189,8 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
} }
// ConvertForkToNormalRepository convert the provided repo from a forked repo to normal repo // ConvertForkToNormalRepository convert the provided repo from a forked repo to normal repo
func ConvertForkToNormalRepository(repo *repo_model.Repository) error { func ConvertForkToNormalRepository(ctx context.Context, repo *repo_model.Repository) error {
err := db.WithTx(db.DefaultContext, func(ctx context.Context) error { err := db.WithTx(ctx, func(ctx context.Context) error {
repo, err := repo_model.GetRepositoryByID(ctx, repo.ID) repo, err := repo_model.GetRepositoryByID(ctx, repo.ID)
if err != nil { if err != nil {
return err return err

View File

@ -80,6 +80,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("PushUpdates: %s/%s", optsList[0].RepoUserName, optsList[0].RepoName)) ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("PushUpdates: %s/%s", optsList[0].RepoUserName, optsList[0].RepoName))
defer finished() defer finished()
ctx = cache.WithCacheContext(ctx)
repo, err := repo_model.GetRepositoryByOwnerAndName(ctx, optsList[0].RepoUserName, optsList[0].RepoName) repo, err := repo_model.GetRepositoryByOwnerAndName(ctx, optsList[0].RepoUserName, optsList[0].RepoName)
if err != nil { if err != nil {
@ -122,7 +123,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
tagName := opts.TagName() tagName := opts.TagName()
if opts.IsDelRef() { if opts.IsDelRef() {
notification.NotifyPushCommits( notification.NotifyPushCommits(
db.DefaultContext, pusher, repo, ctx, pusher, repo,
&repo_module.PushUpdateOptions{ &repo_module.PushUpdateOptions{
RefFullName: git.TagPrefix + tagName, RefFullName: git.TagPrefix + tagName,
OldCommitID: opts.OldCommitID, OldCommitID: opts.OldCommitID,
@ -130,7 +131,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
}, repo_module.NewPushCommits()) }, repo_module.NewPushCommits())
delTags = append(delTags, tagName) delTags = append(delTags, tagName)
notification.NotifyDeleteRef(db.DefaultContext, pusher, repo, "tag", opts.RefFullName) notification.NotifyDeleteRef(ctx, pusher, repo, "tag", opts.RefFullName)
} else { // is new tag } else { // is new tag
newCommit, err := gitRepo.GetCommit(opts.NewCommitID) newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
if err != nil { if err != nil {
@ -142,7 +143,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
commits.CompareURL = repo.ComposeCompareURL(git.EmptySHA, opts.NewCommitID) commits.CompareURL = repo.ComposeCompareURL(git.EmptySHA, opts.NewCommitID)
notification.NotifyPushCommits( notification.NotifyPushCommits(
db.DefaultContext, pusher, repo, ctx, pusher, repo,
&repo_module.PushUpdateOptions{ &repo_module.PushUpdateOptions{
RefFullName: git.TagPrefix + tagName, RefFullName: git.TagPrefix + tagName,
OldCommitID: git.EmptySHA, OldCommitID: git.EmptySHA,
@ -150,7 +151,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
}, commits) }, commits)
addTags = append(addTags, tagName) addTags = append(addTags, tagName)
notification.NotifyCreateRef(db.DefaultContext, pusher, repo, "tag", opts.RefFullName, opts.NewCommitID) notification.NotifyCreateRef(ctx, pusher, repo, "tag", opts.RefFullName, opts.NewCommitID)
} }
} else if opts.IsBranch() { // If is branch reference } else if opts.IsBranch() { // If is branch reference
if pusher == nil || pusher.ID != opts.PusherID { if pusher == nil || pusher.ID != opts.PusherID {
@ -190,7 +191,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
} }
} }
// Update the is empty and default_branch columns // Update the is empty and default_branch columns
if err := repo_model.UpdateRepositoryCols(db.DefaultContext, repo, "default_branch", "is_empty"); err != nil { if err := repo_model.UpdateRepositoryCols(ctx, repo, "default_branch", "is_empty"); err != nil {
return fmt.Errorf("UpdateRepositoryCols: %w", err) return fmt.Errorf("UpdateRepositoryCols: %w", err)
} }
} }
@ -199,7 +200,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
if err != nil { if err != nil {
return fmt.Errorf("newCommit.CommitsBeforeLimit: %w", err) return fmt.Errorf("newCommit.CommitsBeforeLimit: %w", err)
} }
notification.NotifyCreateRef(db.DefaultContext, pusher, repo, "branch", opts.RefFullName, opts.NewCommitID) notification.NotifyCreateRef(ctx, pusher, repo, "branch", opts.RefFullName, opts.NewCommitID)
} else { } else {
l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID) l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
if err != nil { if err != nil {
@ -259,7 +260,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
commits.Commits = commits.Commits[:setting.UI.FeedMaxCommitNum] commits.Commits = commits.Commits[:setting.UI.FeedMaxCommitNum]
} }
notification.NotifyPushCommits(db.DefaultContext, pusher, repo, opts, commits) notification.NotifyPushCommits(ctx, pusher, repo, opts, commits)
if err = git_model.RemoveDeletedBranchByName(ctx, repo.ID, branch); err != nil { if err = git_model.RemoveDeletedBranchByName(ctx, repo.ID, branch); err != nil {
log.Error("models.RemoveDeletedBranch %s/%s failed: %v", repo.ID, branch, err) log.Error("models.RemoveDeletedBranch %s/%s failed: %v", repo.ID, branch, err)
@ -270,7 +271,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
log.Error("repo_module.CacheRef %s/%s failed: %v", repo.ID, branch, err) log.Error("repo_module.CacheRef %s/%s failed: %v", repo.ID, branch, err)
} }
} else { } else {
notification.NotifyDeleteRef(db.DefaultContext, pusher, repo, "branch", opts.RefFullName) notification.NotifyDeleteRef(ctx, pusher, repo, "branch", opts.RefFullName)
if err = pull_service.CloseBranchPulls(pusher, repo.ID, branch); err != nil { if err = pull_service.CloseBranchPulls(pusher, repo.ID, branch); err != nil {
// close all related pulls // close all related pulls
log.Error("close related pull request failed: %v", err) log.Error("close related pull request failed: %v", err)
@ -278,14 +279,14 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
} }
// Even if user delete a branch on a repository which he didn't watch, he will be watch that. // Even if user delete a branch on a repository which he didn't watch, he will be watch that.
if err = repo_model.WatchIfAuto(db.DefaultContext, opts.PusherID, repo.ID, true); err != nil { if err = repo_model.WatchIfAuto(ctx, opts.PusherID, repo.ID, true); err != nil {
log.Warn("Fail to perform auto watch on user %v for repo %v: %v", opts.PusherID, repo.ID, err) log.Warn("Fail to perform auto watch on user %v for repo %v: %v", opts.PusherID, repo.ID, err)
} }
} else { } else {
log.Trace("Non-tag and non-branch commits pushed.") log.Trace("Non-tag and non-branch commits pushed.")
} }
} }
if err := PushUpdateAddDeleteTags(repo, gitRepo, addTags, delTags); err != nil { if err := PushUpdateAddDeleteTags(ctx, repo, gitRepo, addTags, delTags); err != nil {
return fmt.Errorf("PushUpdateAddDeleteTags: %w", err) return fmt.Errorf("PushUpdateAddDeleteTags: %w", err)
} }
@ -298,8 +299,8 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
} }
// PushUpdateAddDeleteTags updates a number of added and delete tags // PushUpdateAddDeleteTags updates a number of added and delete tags
func PushUpdateAddDeleteTags(repo *repo_model.Repository, gitRepo *git.Repository, addTags, delTags []string) error { func PushUpdateAddDeleteTags(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, addTags, delTags []string) error {
return db.WithTx(db.DefaultContext, func(ctx context.Context) error { return db.WithTx(ctx, func(ctx context.Context) error {
if err := repo_model.PushUpdateDeleteTagsContext(ctx, repo, delTags); err != nil { if err := repo_model.PushUpdateDeleteTagsContext(ctx, repo, delTags); err != nil {
return err return err
} }

View File

@ -24,14 +24,14 @@ import (
) )
// CreateRepository creates a repository for the user/organization. // CreateRepository creates a repository for the user/organization.
func CreateRepository(doer, owner *user_model.User, opts repo_module.CreateRepoOptions) (*repo_model.Repository, error) { func CreateRepository(ctx context.Context, doer, owner *user_model.User, opts repo_module.CreateRepoOptions) (*repo_model.Repository, error) {
repo, err := repo_module.CreateRepository(doer, owner, opts) repo, err := repo_module.CreateRepository(doer, owner, opts)
if err != nil { if err != nil {
// No need to rollback here we should do this in CreateRepository... // No need to rollback here we should do this in CreateRepository...
return nil, err return nil, err
} }
notification.NotifyCreateRepository(db.DefaultContext, doer, owner, repo) notification.NotifyCreateRepository(ctx, doer, owner, repo)
return repo, nil return repo, nil
} }
@ -55,10 +55,10 @@ func DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_mod
} }
// PushCreateRepo creates a repository when a new repository is pushed to an appropriate namespace // PushCreateRepo creates a repository when a new repository is pushed to an appropriate namespace
func PushCreateRepo(authUser, owner *user_model.User, repoName string) (*repo_model.Repository, error) { func PushCreateRepo(ctx context.Context, authUser, owner *user_model.User, repoName string) (*repo_model.Repository, error) {
if !authUser.IsAdmin { if !authUser.IsAdmin {
if owner.IsOrganization() { if owner.IsOrganization() {
if ok, err := organization.CanCreateOrgRepo(db.DefaultContext, owner.ID, authUser.ID); err != nil { if ok, err := organization.CanCreateOrgRepo(ctx, owner.ID, authUser.ID); err != nil {
return nil, err return nil, err
} else if !ok { } else if !ok {
return nil, fmt.Errorf("cannot push-create repository for org") return nil, fmt.Errorf("cannot push-create repository for org")
@ -68,7 +68,7 @@ func PushCreateRepo(authUser, owner *user_model.User, repoName string) (*repo_mo
} }
} }
repo, err := CreateRepository(authUser, owner, repo_module.CreateRepoOptions{ repo, err := CreateRepository(ctx, authUser, owner, repo_module.CreateRepoOptions{
Name: repoName, Name: repoName,
IsPrivate: setting.Repository.DefaultPushCreatePrivate, IsPrivate: setting.Repository.DefaultPushCreatePrivate,
}) })
@ -88,8 +88,8 @@ func Init() error {
} }
// UpdateRepository updates a repository // UpdateRepository updates a repository
func UpdateRepository(repo *repo_model.Repository, visibilityChanged bool) (err error) { func UpdateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) {
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }

View File

@ -4,20 +4,21 @@
package repository package repository
import ( import (
"code.gitea.io/gitea/models/db" "context"
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
) )
// GetReviewerTeams get all teams can be requested to review // GetReviewerTeams get all teams can be requested to review
func GetReviewerTeams(repo *repo_model.Repository) ([]*organization.Team, error) { func GetReviewerTeams(ctx context.Context, repo *repo_model.Repository) ([]*organization.Team, error) {
if err := repo.LoadOwner(db.DefaultContext); err != nil { if err := repo.LoadOwner(ctx); err != nil {
return nil, err return nil, err
} }
if !repo.Owner.IsOrganization() { if !repo.Owner.IsOrganization() {
return nil, nil return nil, nil
} }
return organization.GetTeamsWithAccessToRepo(db.DefaultContext, repo.OwnerID, repo.ID, perm.AccessModeRead) return organization.GetTeamsWithAccessToRepo(ctx, repo.OwnerID, repo.ID, perm.AccessModeRead)
} }

View File

@ -6,6 +6,7 @@ package repository
import ( import (
"testing" "testing"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
@ -16,12 +17,12 @@ func TestRepoGetReviewerTeams(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
teams, err := GetReviewerTeams(repo2) teams, err := GetReviewerTeams(db.DefaultContext, repo2)
assert.NoError(t, err) assert.NoError(t, err)
assert.Empty(t, teams) assert.Empty(t, teams)
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
teams, err = GetReviewerTeams(repo3) teams, err = GetReviewerTeams(db.DefaultContext, repo3)
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, teams, 2) assert.Len(t, teams, 2)
} }

View File

@ -40,7 +40,7 @@ func GenerateIssueLabels(ctx context.Context, templateRepo, generateRepo *repo_m
} }
// GenerateRepository generates a repository from a template // GenerateRepository generates a repository from a template
func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.Repository, opts repo_module.GenerateRepoOptions) (_ *repo_model.Repository, err error) { func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts repo_module.GenerateRepoOptions) (_ *repo_model.Repository, err error) {
if !doer.IsAdmin && !owner.CanCreateRepo() { if !doer.IsAdmin && !owner.CanCreateRepo() {
return nil, repo_model.ErrReachLimitOfRepo{ return nil, repo_model.ErrReachLimitOfRepo{
Limit: owner.MaxRepoCreation, Limit: owner.MaxRepoCreation,
@ -48,7 +48,7 @@ func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.R
} }
var generateRepo *repo_model.Repository var generateRepo *repo_model.Repository
if err = db.WithTx(db.DefaultContext, func(ctx context.Context) error { if err = db.WithTx(ctx, func(ctx context.Context) error {
generateRepo, err = repo_module.GenerateRepository(ctx, doer, owner, templateRepo, opts) generateRepo, err = repo_module.GenerateRepository(ctx, doer, owner, templateRepo, opts)
if err != nil { if err != nil {
return err return err
@ -101,7 +101,7 @@ func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.R
return nil, err return nil, err
} }
notification.NotifyCreateRepository(db.DefaultContext, doer, owner, generateRepo) notification.NotifyCreateRepository(ctx, doer, owner, generateRepo)
return generateRepo, nil return generateRepo, nil
} }

View File

@ -8,7 +8,6 @@ import (
"fmt" "fmt"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access" access_model "code.gitea.io/gitea/models/perm/access"
@ -61,7 +60,7 @@ func TransferOwnership(ctx context.Context, doer, newOwner *user_model.User, rep
} }
// ChangeRepositoryName changes all corresponding setting from old repository name to new one. // ChangeRepositoryName changes all corresponding setting from old repository name to new one.
func ChangeRepositoryName(doer *user_model.User, repo *repo_model.Repository, newRepoName string) error { func ChangeRepositoryName(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, newRepoName string) error {
log.Trace("ChangeRepositoryName: %s/%s -> %s", doer.Name, repo.Name, newRepoName) log.Trace("ChangeRepositoryName: %s/%s -> %s", doer.Name, repo.Name, newRepoName)
oldRepoName := repo.Name oldRepoName := repo.Name
@ -78,7 +77,7 @@ func ChangeRepositoryName(doer *user_model.User, repo *repo_model.Repository, ne
repoWorkingPool.CheckOut(fmt.Sprint(repo.ID)) repoWorkingPool.CheckOut(fmt.Sprint(repo.ID))
repo.Name = newRepoName repo.Name = newRepoName
notification.NotifyRenameRepository(db.DefaultContext, doer, repo, oldRepoName) notification.NotifyRenameRepository(ctx, doer, repo, oldRepoName)
return nil return nil
} }

View File

@ -46,56 +46,38 @@
<div class="ui dropdown icon button" title="{{.locale.Tr "home.filter"}}"> <div class="ui dropdown icon button" title="{{.locale.Tr "home.filter"}}">
<i class="icon gt-df gt-ac gt-jc gt-m-0">{{svg "octicon-filter" 16}}</i> <i class="icon gt-df gt-ac gt-jc gt-m-0">{{svg "octicon-filter" 16}}</i>
<div class="menu"> <div class="menu">
<div class="item"> <a class="item" @click="toggleArchivedFilter()">
<a @click="toggleArchivedFilter()"> <div class="ui checkbox"
<div class="ui checkbox" id="archivedFilterCheckbox" title="{{.locale.Tr "home.show_both_archived_unarchived"}}" v-if="archivedFilter === 'both'"> ref="checkboxArchivedFilter"
<input type="checkbox"> data-title-both="{{.locale.Tr "home.show_both_archived_unarchived"}}"
<label> data-title-unarchived="{{.locale.Tr "home.show_only_unarchived"}}"
{{svg "octicon-archive" 16 "gt-mr-2"}} data-title-archived="{{.locale.Tr "home.show_only_archived"}}"
{{.locale.Tr "home.show_archived"}} :title="checkboxArchivedFilterTitle"
</label> >
</div> <!--the "hidden" is necessary to make the checkbox work without Fomantic UI js,
<div class="ui checkbox" id="archivedFilterCheckbox" title="{{.locale.Tr "home.show_only_unarchived"}}" v-if="archivedFilter === 'unarchived'"> otherwise if the "input" handles click event for intermediate status, it breaks the internal state-->
<input type="checkbox"> <input type="checkbox" class="hidden" v-bind.prop="checkboxArchivedFilterProps">
<label> <label>
{{svg "octicon-archive" 16 "gt-mr-2"}} {{svg "octicon-archive" 16 "gt-mr-2"}}
{{.locale.Tr "home.show_archived"}} {{.locale.Tr "home.show_archived"}}
</label> </label>
</div> </div>
<div class="ui checkbox" id="archivedFilterCheckbox" title="{{.locale.Tr "home.show_only_archived"}}" v-if="archivedFilter === 'archived'"> </a>
<input type="checkbox"> <a class="item" @click="togglePrivateFilter()">
<label> <div class="ui checkbox"
{{svg "octicon-archive" 16 "gt-mr-2"}} ref="checkboxPrivateFilter"
{{.locale.Tr "home.show_archived"}} data-title-both="{{.locale.Tr "home.show_both_private_public"}}"
</label> data-title-public="{{.locale.Tr "home.show_only_public"}}"
</div> data-title-private="{{.locale.Tr "home.show_only_private"}}"
</a> :title="checkboxPrivateFilterTitle"
</div> >
<div class="item"> <input type="checkbox" class="hidden" v-bind.prop="checkboxPrivateFilterProps">
<a @click="togglePrivateFilter()"> <label>
<div class="ui checkbox" id="privateFilterCheckbox" title="{{.locale.Tr "home.show_both_private_public"}}" v-if="privateFilter === 'both'"> {{svg "octicon-lock" 16 "gt-mr-2"}}
<input type="checkbox"> {{.locale.Tr "home.show_private"}}
<label> </label>
{{svg "octicon-lock" 16 "gt-mr-2"}} </div>
{{.locale.Tr "home.show_private"}} </a>
</label>
</div>
<div class="ui checkbox" id="privateFilterCheckbox" title="{{.locale.Tr "home.show_only_public"}}" v-if="privateFilter === 'public'">
<input type="checkbox">
<label>
{{svg "octicon-lock" 16 "gt-mr-2"}}
{{.locale.Tr "home.show_private"}}
</label>
</div>
<div class="ui checkbox" id="privateFilterCheckbox" title="{{.locale.Tr "home.show_only_private"}}" v-if="privateFilter === 'private'">
<input type="checkbox">
<label>
{{svg "octicon-lock" 16 "gt-mr-2"}}
{{.locale.Tr "home.show_private"}}
</label>
</div>
</a>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -356,7 +356,7 @@ func TestConflictChecking(t *testing.T) {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
// Create new clean repo to test conflict checking. // Create new clean repo to test conflict checking.
baseRepo, err := repo_service.CreateRepository(user, user, repo_module.CreateRepoOptions{ baseRepo, err := repo_service.CreateRepository(db.DefaultContext, user, user, repo_module.CreateRepoOptions{
Name: "conflict-checking", Name: "conflict-checking",
Description: "Tempo repo", Description: "Tempo repo",
AutoInit: true, AutoInit: true,

View File

@ -80,7 +80,7 @@ func TestAPIPullUpdateByRebase(t *testing.T) {
} }
func createOutdatedPR(t *testing.T, actor, forkOrg *user_model.User) *issues_model.PullRequest { func createOutdatedPR(t *testing.T, actor, forkOrg *user_model.User) *issues_model.PullRequest {
baseRepo, err := repo_service.CreateRepository(actor, actor, repo_module.CreateRepoOptions{ baseRepo, err := repo_service.CreateRepository(db.DefaultContext, actor, actor, repo_module.CreateRepoOptions{
Name: "repo-pr-update", Name: "repo-pr-update",
Description: "repo-tmp-pr-update description", Description: "repo-tmp-pr-update description",
AutoInit: true, AutoInit: true,

View File

@ -87,6 +87,7 @@ function initVueComponents(app) {
} }
return { return {
hasMounted: false, // accessing $refs in computed() need to wait for mounted
tab, tab,
repos: [], repos: [],
reposTotalCount: 0, reposTotalCount: 0,
@ -134,7 +135,19 @@ function initVueComponents(app) {
}, },
repoTypeCount() { repoTypeCount() {
return this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`]; return this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`];
} },
checkboxArchivedFilterTitle() {
return this.hasMounted && this.$refs.checkboxArchivedFilter?.getAttribute(`data-title-${this.archivedFilter}`);
},
checkboxArchivedFilterProps() {
return {checked: this.archivedFilter === 'archived', indeterminate: this.archivedFilter === 'both'};
},
checkboxPrivateFilterTitle() {
return this.hasMounted && this.$refs.checkboxPrivateFilter?.getAttribute(`data-title-${this.privateFilter}`);
},
checkboxPrivateFilterProps() {
return {checked: this.privateFilter === 'private', indeterminate: this.privateFilter === 'both'};
},
}, },
mounted() { mounted() {
@ -144,10 +157,11 @@ function initVueComponents(app) {
initTooltip(elTooltip); initTooltip(elTooltip);
} }
$(el).find('.dropdown').dropdown(); $(el).find('.dropdown').dropdown();
this.setCheckboxes();
nextTick(() => { nextTick(() => {
this.$refs.search.focus(); this.$refs.search.focus();
}); });
this.hasMounted = true;
}, },
methods: { methods: {
@ -156,39 +170,6 @@ function initVueComponents(app) {
this.updateHistory(); this.updateHistory();
}, },
setCheckboxes() {
switch (this.archivedFilter) {
case 'unarchived':
$('#archivedFilterCheckbox').checkbox('set unchecked');
break;
case 'archived':
$('#archivedFilterCheckbox').checkbox('set checked');
break;
case 'both':
$('#archivedFilterCheckbox').checkbox('set indeterminate');
break;
default:
this.archivedFilter = 'unarchived';
$('#archivedFilterCheckbox').checkbox('set unchecked');
break;
}
switch (this.privateFilter) {
case 'public':
$('#privateFilterCheckbox').checkbox('set unchecked');
break;
case 'private':
$('#privateFilterCheckbox').checkbox('set checked');
break;
case 'both':
$('#privateFilterCheckbox').checkbox('set indeterminate');
break;
default:
this.privateFilter = 'both';
$('#privateFilterCheckbox').checkbox('set indeterminate');
break;
}
},
changeReposFilter(filter) { changeReposFilter(filter) {
this.reposFilter = filter; this.reposFilter = filter;
this.repos = []; this.repos = [];
@ -245,45 +226,29 @@ function initVueComponents(app) {
}, },
toggleArchivedFilter() { toggleArchivedFilter() {
switch (this.archivedFilter) { if (this.archivedFilter === 'unarchived') {
case 'both': this.archivedFilter = 'archived';
this.archivedFilter = 'unarchived'; } else if (this.archivedFilter === 'archived') {
break; this.archivedFilter = 'both';
case 'unarchived': } else { // including both
this.archivedFilter = 'archived'; this.archivedFilter = 'unarchived';
break;
case 'archived':
this.archivedFilter = 'both';
break;
default:
this.archivedFilter = 'unarchived';
break;
} }
this.page = 1; this.page = 1;
this.repos = []; this.repos = [];
this.setCheckboxes();
this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0; this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0;
this.searchRepos(); this.searchRepos();
}, },
togglePrivateFilter() { togglePrivateFilter() {
switch (this.privateFilter) { if (this.privateFilter === 'both') {
case 'both': this.privateFilter = 'public';
this.privateFilter = 'public'; } else if (this.privateFilter === 'public') {
break; this.privateFilter = 'private';
case 'public': } else { // including private
this.privateFilter = 'private'; this.privateFilter = 'both';
break;
case 'private':
this.privateFilter = 'both';
break;
default:
this.privateFilter = 'both';
break;
} }
this.page = 1; this.page = 1;
this.repos = []; this.repos = [];
this.setCheckboxes();
this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0; this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0;
this.searchRepos(); this.searchRepos();
}, },