mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-09 00:01:10 -04:00
Compare commits
7 Commits
426c0ad14c
...
93e907de41
Author | SHA1 | Date | |
---|---|---|---|
|
93e907de41 | ||
|
f3034b1fd9 | ||
|
d0c74dd2d2 | ||
|
2f91a12143 | ||
|
3ad62127df | ||
|
37e23c982f | ||
|
421d87933b |
@ -1087,6 +1087,9 @@ func (ctx *Context) IssueTemplatesErrorsFromDefaultBranch() ([]*api.IssueTemplat
|
|||||||
if it, err := template.UnmarshalFromEntry(entry, dirName); err != nil {
|
if it, err := template.UnmarshalFromEntry(entry, dirName); err != nil {
|
||||||
invalidFiles[fullName] = err
|
invalidFiles[fullName] = err
|
||||||
} else {
|
} else {
|
||||||
|
if !strings.HasPrefix(it.Ref, "refs/") { // Assume that the ref intended is always a branch - for tags users should use refs/tags/<ref>
|
||||||
|
it.Ref = git.BranchPrefix + it.Ref
|
||||||
|
}
|
||||||
issueTemplates = append(issueTemplates, it)
|
issueTemplates = append(issueTemplates, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,9 @@ func RefURL(repoURL, ref string) string {
|
|||||||
return repoURL + "/src/branch/" + refName
|
return repoURL + "/src/branch/" + refName
|
||||||
case strings.HasPrefix(ref, TagPrefix):
|
case strings.HasPrefix(ref, TagPrefix):
|
||||||
return repoURL + "/src/tag/" + refName
|
return repoURL + "/src/tag/" + refName
|
||||||
|
case !IsValidSHAPattern(ref):
|
||||||
|
// assume they mean a branch
|
||||||
|
return repoURL + "/src/branch/" + refName
|
||||||
default:
|
default:
|
||||||
return repoURL + "/src/commit/" + refName
|
return repoURL + "/src/commit/" + refName
|
||||||
}
|
}
|
||||||
|
@ -110,32 +110,6 @@ func (q *ChannelQueue) Flush(timeout time.Duration) error {
|
|||||||
return q.FlushWithContext(ctx)
|
return q.FlushWithContext(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlushWithContext is very similar to CleanUp but it will return as soon as the dataChan is empty
|
|
||||||
func (q *ChannelQueue) FlushWithContext(ctx context.Context) error {
|
|
||||||
log.Trace("ChannelQueue: %d Flush", q.qid)
|
|
||||||
paused, _ := q.IsPausedIsResumed()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-paused:
|
|
||||||
return nil
|
|
||||||
case data, ok := <-q.dataChan:
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if unhandled := q.handle(data); unhandled != nil {
|
|
||||||
log.Error("Unhandled Data whilst flushing queue %d", q.qid)
|
|
||||||
}
|
|
||||||
atomic.AddInt64(&q.numInQueue, -1)
|
|
||||||
case <-q.baseCtx.Done():
|
|
||||||
return q.baseCtx.Err()
|
|
||||||
case <-ctx.Done():
|
|
||||||
return ctx.Err()
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shutdown processing from this queue
|
// Shutdown processing from this queue
|
||||||
func (q *ChannelQueue) Shutdown() {
|
func (q *ChannelQueue) Shutdown() {
|
||||||
q.lock.Lock()
|
q.lock.Lock()
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/container"
|
"code.gitea.io/gitea/modules/container"
|
||||||
@ -168,35 +167,6 @@ func (q *ChannelUniqueQueue) Flush(timeout time.Duration) error {
|
|||||||
return q.FlushWithContext(ctx)
|
return q.FlushWithContext(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlushWithContext is very similar to CleanUp but it will return as soon as the dataChan is empty
|
|
||||||
func (q *ChannelUniqueQueue) FlushWithContext(ctx context.Context) error {
|
|
||||||
log.Trace("ChannelUniqueQueue: %d Flush", q.qid)
|
|
||||||
paused, _ := q.IsPausedIsResumed()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-paused:
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case data, ok := <-q.dataChan:
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if unhandled := q.handle(data); unhandled != nil {
|
|
||||||
log.Error("Unhandled Data whilst flushing queue %d", q.qid)
|
|
||||||
}
|
|
||||||
atomic.AddInt64(&q.numInQueue, -1)
|
|
||||||
case <-q.baseCtx.Done():
|
|
||||||
return q.baseCtx.Err()
|
|
||||||
case <-ctx.Done():
|
|
||||||
return ctx.Err()
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shutdown processing from this queue
|
// Shutdown processing from this queue
|
||||||
func (q *ChannelUniqueQueue) Shutdown() {
|
func (q *ChannelUniqueQueue) Shutdown() {
|
||||||
log.Trace("ChannelUniqueQueue: %s Shutting down", q.name)
|
log.Trace("ChannelUniqueQueue: %s Shutting down", q.name)
|
||||||
|
@ -464,13 +464,43 @@ func (p *WorkerPool) IsEmpty() bool {
|
|||||||
return atomic.LoadInt64(&p.numInQueue) == 0
|
return atomic.LoadInt64(&p.numInQueue) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// contextError returns either ctx.Done(), the base context's error or nil
|
||||||
|
func (p *WorkerPool) contextError(ctx context.Context) error {
|
||||||
|
select {
|
||||||
|
case <-p.baseCtx.Done():
|
||||||
|
return p.baseCtx.Err()
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FlushWithContext is very similar to CleanUp but it will return as soon as the dataChan is empty
|
// FlushWithContext is very similar to CleanUp but it will return as soon as the dataChan is empty
|
||||||
// NB: The worker will not be registered with the manager.
|
// NB: The worker will not be registered with the manager.
|
||||||
func (p *WorkerPool) FlushWithContext(ctx context.Context) error {
|
func (p *WorkerPool) FlushWithContext(ctx context.Context) error {
|
||||||
log.Trace("WorkerPool: %d Flush", p.qid)
|
log.Trace("WorkerPool: %d Flush", p.qid)
|
||||||
|
paused, _ := p.IsPausedIsResumed()
|
||||||
for {
|
for {
|
||||||
|
// Because select will return any case that is satisified at random we precheck here before looking at dataChan.
|
||||||
select {
|
select {
|
||||||
case data := <-p.dataChan:
|
case <-paused:
|
||||||
|
// Ensure that even if paused that the cancelled error is still sent
|
||||||
|
return p.contextError(ctx)
|
||||||
|
case <-p.baseCtx.Done():
|
||||||
|
return p.baseCtx.Err()
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-paused:
|
||||||
|
return p.contextError(ctx)
|
||||||
|
case data, ok := <-p.dataChan:
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if unhandled := p.handle(data); unhandled != nil {
|
if unhandled := p.handle(data); unhandled != nil {
|
||||||
log.Error("Unhandled Data whilst flushing queue %d", p.qid)
|
log.Error("Unhandled Data whilst flushing queue %d", p.qid)
|
||||||
}
|
}
|
||||||
@ -496,6 +526,7 @@ func (p *WorkerPool) doWork(ctx context.Context) {
|
|||||||
paused, _ := p.IsPausedIsResumed()
|
paused, _ := p.IsPausedIsResumed()
|
||||||
data := make([]Data, 0, p.batchLength)
|
data := make([]Data, 0, p.batchLength)
|
||||||
for {
|
for {
|
||||||
|
// Because select will return any case that is satisified at random we precheck here before looking at dataChan.
|
||||||
select {
|
select {
|
||||||
case <-paused:
|
case <-paused:
|
||||||
log.Trace("Worker for Queue %d Pausing", p.qid)
|
log.Trace("Worker for Queue %d Pausing", p.qid)
|
||||||
@ -516,8 +547,19 @@ func (p *WorkerPool) doWork(ctx context.Context) {
|
|||||||
log.Trace("Worker shutting down")
|
log.Trace("Worker shutting down")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
case <-ctx.Done():
|
||||||
|
if len(data) > 0 {
|
||||||
|
log.Trace("Handling: %d data, %v", len(data), data)
|
||||||
|
if unhandled := p.handle(data...); unhandled != nil {
|
||||||
|
log.Error("Unhandled Data in queue %d", p.qid)
|
||||||
|
}
|
||||||
|
atomic.AddInt64(&p.numInQueue, -1*int64(len(data)))
|
||||||
|
}
|
||||||
|
log.Trace("Worker shutting down")
|
||||||
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-paused:
|
case <-paused:
|
||||||
// go back around
|
// go back around
|
||||||
|
@ -784,6 +784,10 @@ func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(template.Ref, "refs/") { // Assume that the ref intended is always a branch - for tags users should use refs/tags/<ref>
|
||||||
|
template.Ref = git.BranchPrefix + template.Ref
|
||||||
}
|
}
|
||||||
ctx.Data["HasSelectedLabel"] = len(labelIDs) > 0
|
ctx.Data["HasSelectedLabel"] = len(labelIDs) > 0
|
||||||
ctx.Data["label_ids"] = strings.Join(labelIDs, ",")
|
ctx.Data["label_ids"] = strings.Join(labelIDs, ",")
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/notification"
|
"code.gitea.io/gitea/modules/notification"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/util"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewIssue creates new issue with labels for repository.
|
// NewIssue creates new issue with labels for repository.
|
||||||
@ -201,7 +200,7 @@ func GetRefEndNamesAndURLs(issues []*issues_model.Issue, repoLink string) (map[i
|
|||||||
for _, issue := range issues {
|
for _, issue := range issues {
|
||||||
if issue.Ref != "" {
|
if issue.Ref != "" {
|
||||||
issueRefEndNames[issue.ID] = git.RefEndName(issue.Ref)
|
issueRefEndNames[issue.ID] = git.RefEndName(issue.Ref)
|
||||||
issueRefURLs[issue.ID] = git.RefURL(repoLink, util.PathEscapeSegments(issue.Ref))
|
issueRefURLs[issue.ID] = git.RefURL(repoLink, issue.Ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return issueRefEndNames, issueRefURLs
|
return issueRefEndNames, issueRefURLs
|
||||||
|
@ -73,32 +73,8 @@ func GitGcRepos(ctx context.Context, timeout time.Duration, args ...git.CmdArg)
|
|||||||
return db.ErrCancelledf("before GC of %s", repo.FullName())
|
return db.ErrCancelledf("before GC of %s", repo.FullName())
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
log.Trace("Running git gc on %v", repo)
|
// we can ignore the error here because it will be logged in GitGCRepo
|
||||||
command := git.NewCommand(ctx, args...).
|
_ = GitGcRepo(ctx, repo, timeout, args)
|
||||||
SetDescription(fmt.Sprintf("Repository Garbage Collection: %s", repo.FullName()))
|
|
||||||
var stdout string
|
|
||||||
var err error
|
|
||||||
stdout, _, err = command.RunStdString(&git.RunOpts{Timeout: timeout, Dir: repo.RepoPath()})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Repository garbage collection failed for %v. Stdout: %s\nError: %v", repo, stdout, err)
|
|
||||||
desc := fmt.Sprintf("Repository garbage collection failed for %s. Stdout: %s\nError: %v", repo.RepoPath(), stdout, err)
|
|
||||||
if err = system_model.CreateRepositoryNotice(desc); err != nil {
|
|
||||||
log.Error("CreateRepositoryNotice: %v", err)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("Repository garbage collection failed in repo: %s: Error: %w", repo.FullName(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now update the size of the repository
|
|
||||||
if err := repo_module.UpdateRepoSize(ctx, repo); err != nil {
|
|
||||||
log.Error("Updating size as part of garbage collection failed for %v. Stdout: %s\nError: %v", repo, stdout, err)
|
|
||||||
desc := fmt.Sprintf("Updating size as part of garbage collection failed for %s. Stdout: %s\nError: %v", repo.RepoPath(), stdout, err)
|
|
||||||
if err = system_model.CreateRepositoryNotice(desc); err != nil {
|
|
||||||
log.Error("CreateRepositoryNotice: %v", err)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("Updating size as part of garbage collection failed in repo: %s: Error: %w", repo.FullName(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
@ -109,6 +85,37 @@ func GitGcRepos(ctx context.Context, timeout time.Duration, args ...git.CmdArg)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GitGcRepo calls 'git gc' to remove unnecessary files and optimize the local repository
|
||||||
|
func GitGcRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Duration, args []git.CmdArg) error {
|
||||||
|
log.Trace("Running git gc on %-v", repo)
|
||||||
|
command := git.NewCommand(ctx, args...).
|
||||||
|
SetDescription(fmt.Sprintf("Repository Garbage Collection: %s", repo.FullName()))
|
||||||
|
var stdout string
|
||||||
|
var err error
|
||||||
|
stdout, _, err = command.RunStdString(&git.RunOpts{Timeout: timeout, Dir: repo.RepoPath()})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Repository garbage collection failed for %-v. Stdout: %s\nError: %v", repo, stdout, err)
|
||||||
|
desc := fmt.Sprintf("Repository garbage collection failed for %s. Stdout: %s\nError: %v", repo.RepoPath(), stdout, err)
|
||||||
|
if err := system_model.CreateRepositoryNotice(desc); err != nil {
|
||||||
|
log.Error("CreateRepositoryNotice: %v", err)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Repository garbage collection failed in repo: %s: Error: %w", repo.FullName(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now update the size of the repository
|
||||||
|
if err := repo_module.UpdateRepoSize(ctx, repo); err != nil {
|
||||||
|
log.Error("Updating size as part of garbage collection failed for %-v. Stdout: %s\nError: %v", repo, stdout, err)
|
||||||
|
desc := fmt.Sprintf("Updating size as part of garbage collection failed for %s. Stdout: %s\nError: %v", repo.RepoPath(), stdout, err)
|
||||||
|
if err := system_model.CreateRepositoryNotice(desc); err != nil {
|
||||||
|
log.Error("CreateRepositoryNotice: %v", err)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Updating size as part of garbage collection failed in repo: %s: Error: %w", repo.FullName(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func gatherMissingRepoRecords(ctx context.Context) ([]*repo_model.Repository, error) {
|
func gatherMissingRepoRecords(ctx context.Context) ([]*repo_model.Repository, error) {
|
||||||
repos := make([]*repo_model.Repository, 0, 10)
|
repos := make([]*repo_model.Repository, 0, 10)
|
||||||
if err := db.Iterate(
|
if err := db.Iterate(
|
||||||
@ -162,7 +169,7 @@ func DeleteMissingRepositories(ctx context.Context, doer *user_model.User) error
|
|||||||
}
|
}
|
||||||
log.Trace("Deleting %d/%d...", repo.OwnerID, repo.ID)
|
log.Trace("Deleting %d/%d...", repo.OwnerID, repo.ID)
|
||||||
if err := models.DeleteRepository(doer, repo.OwnerID, repo.ID); err != nil {
|
if err := models.DeleteRepository(doer, repo.OwnerID, repo.ID); err != nil {
|
||||||
log.Error("Failed to DeleteRepository %s [%d]: Error: %v", repo.FullName(), repo.ID, err)
|
log.Error("Failed to DeleteRepository %-v: Error: %v", repo, err)
|
||||||
if err2 := system_model.CreateRepositoryNotice("Failed to DeleteRepository %s [%d]: Error: %v", repo.FullName(), repo.ID, err); err2 != nil {
|
if err2 := system_model.CreateRepositoryNotice("Failed to DeleteRepository %s [%d]: Error: %v", repo.FullName(), repo.ID, err); err2 != nil {
|
||||||
log.Error("CreateRepositoryNotice: %v", err)
|
log.Error("CreateRepositoryNotice: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ func (f *WechatworkPayload) PullRequest(p *api.PullRequestPayload) (api.Payloade
|
|||||||
func (f *WechatworkPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) {
|
func (f *WechatworkPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) {
|
||||||
var text, title string
|
var text, title string
|
||||||
switch p.Action {
|
switch p.Action {
|
||||||
case api.HookIssueSynchronized:
|
case api.HookIssueReviewed:
|
||||||
action, err := parseHookPullRequestEventType(event)
|
action, err := parseHookPullRequestEventType(event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
</a>
|
</a>
|
||||||
{{if and ($.Permission.CanWrite $.UnitTypeCode) (not $.Repository.IsArchived) (not .IsDeleted)}}{{- /* */ -}}
|
{{if and ($.Permission.CanWrite $.UnitTypeCode) (not $.Repository.IsArchived) (not .IsDeleted)}}{{- /* */ -}}
|
||||||
<div class="ui primary tiny floating dropdown icon button">{{.locale.Tr "repo.commit.actions"}}
|
<div class="ui primary tiny floating dropdown icon button">{{.locale.Tr "repo.commit.actions"}}
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}<span class="sr-mobile-only">{{.locale.Tr "repo.commit.actions"}}</span>
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<div class="ui header">{{.locale.Tr "repo.commit.actions"}}</div>
|
<div class="ui header">{{.locale.Tr "repo.commit.actions"}}</div>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
|
@ -143,7 +143,7 @@
|
|||||||
{{$.locale.Tr "repo.diff.file_suppressed_line_too_long"}}
|
{{$.locale.Tr "repo.diff.file_suppressed_line_too_long"}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{$.locale.Tr "repo.diff.file_suppressed"}}
|
{{$.locale.Tr "repo.diff.file_suppressed"}}
|
||||||
<a class="ui basic tiny button diff-show-more-button" data-href="{{$.Link}}?file-only=true&files={{$file.Name}}&files={{$file.OldName}}">{{$.locale.Tr "repo.diff.load"}}</a>
|
<a class="ui basic tiny button diff-load-button" data-href="{{$.Link}}?file-only=true&files={{$file.Name}}&files={{$file.OldName}}">{{$.locale.Tr "repo.diff.load"}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{$.locale.Tr "repo.diff.bin_not_shown"}}
|
{{$.locale.Tr "repo.diff.bin_not_shown"}}
|
||||||
|
@ -209,8 +209,6 @@ func (s *TestSession) MakeRequestNilResponseHashSumRecorder(t testing.TB, req *h
|
|||||||
|
|
||||||
const userPassword = "password"
|
const userPassword = "password"
|
||||||
|
|
||||||
var loginSessionCache = make(map[string]*TestSession, 10)
|
|
||||||
|
|
||||||
func emptyTestSession(t testing.TB) *TestSession {
|
func emptyTestSession(t testing.TB) *TestSession {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
jar, err := cookiejar.New(nil)
|
jar, err := cookiejar.New(nil)
|
||||||
@ -225,12 +223,8 @@ func getUserToken(t testing.TB, userName string) string {
|
|||||||
|
|
||||||
func loginUser(t testing.TB, userName string) *TestSession {
|
func loginUser(t testing.TB, userName string) *TestSession {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if session, ok := loginSessionCache[userName]; ok {
|
|
||||||
return session
|
return loginUserWithPassword(t, userName, userPassword)
|
||||||
}
|
|
||||||
session := loginUserWithPassword(t, userName, userPassword)
|
|
||||||
loginSessionCache[userName] = session
|
|
||||||
return session
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loginUserWithPassword(t testing.TB, userName, password string) *TestSession {
|
func loginUserWithPassword(t testing.TB, userName, password string) *TestSession {
|
||||||
|
@ -22,7 +22,4 @@ func TestSignOut(t *testing.T) {
|
|||||||
// try to view a private repo, should fail
|
// try to view a private repo, should fail
|
||||||
req = NewRequest(t, "GET", "/user2/repo2")
|
req = NewRequest(t, "GET", "/user2/repo2")
|
||||||
session.MakeRequest(t, req, http.StatusNotFound)
|
session.MakeRequest(t, req, http.StatusNotFound)
|
||||||
|
|
||||||
// invalidate cached cookies for user2, for subsequent tests
|
|
||||||
delete(loginSessionCache, "user2")
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<DiffFileTreeItem v-for="item in fileTree" :key="item.name" :item="item" />
|
<DiffFileTreeItem v-for="item in fileTree" :key="item.name" :item="item" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isIncomplete" id="diff-too-many-files-stats" class="pt-2">
|
<div v-if="isIncomplete" id="diff-too-many-files-stats" class="pt-2">
|
||||||
<span>{{ tooManyFilesMessage }}</span><a :class="['ui', 'basic', 'tiny', 'button', isLoadingNewData === true ? 'disabled' : '']" id="diff-show-more-files-stats" @click.stop="loadMoreData">{{ showMoreMessage }}</a>
|
<span class="mr-2">{{ tooManyFilesMessage }}</span><a :class="['ui', 'basic', 'tiny', 'button', isLoadingNewData === true ? 'disabled' : '']" id="diff-show-more-files-stats" @click.stop="loadMoreData">{{ showMoreMessage }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -98,6 +98,9 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
// ensure correct buttons when we are mounted to the dom
|
// ensure correct buttons when we are mounted to the dom
|
||||||
this.adjustToggleButton(this.fileTreeIsVisible);
|
this.adjustToggleButton(this.fileTreeIsVisible);
|
||||||
|
// replace the pageData.diffFileInfo.files with our watched data so we get updates
|
||||||
|
pageData.diffFileInfo.files = this.files;
|
||||||
|
|
||||||
document.querySelector('.diff-toggle-file-tree-button').addEventListener('click', this.toggleVisibility);
|
document.querySelector('.diff-toggle-file-tree-button').addEventListener('click', this.toggleVisibility);
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
|
@ -119,26 +119,47 @@ function onShowMoreFiles() {
|
|||||||
|
|
||||||
export function doLoadMoreFiles(link, diffEnd, callback) {
|
export function doLoadMoreFiles(link, diffEnd, callback) {
|
||||||
const url = `${link}?skip-to=${diffEnd}&file-only=true`;
|
const url = `${link}?skip-to=${diffEnd}&file-only=true`;
|
||||||
|
loadMoreFiles(url, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadMoreFiles(url, callback) {
|
||||||
|
const $target = $('a#diff-show-more-files');
|
||||||
|
if ($target.hasClass('disabled')) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$target.addClass('disabled');
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url,
|
url,
|
||||||
}).done((resp) => {
|
}).done((resp) => {
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
|
$target.removeClass('disabled');
|
||||||
callback(resp);
|
callback(resp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$('#diff-incomplete').replaceWith($(resp).find('#diff-file-boxes').children());
|
||||||
// By simply rerunning the script we add the new data to our existing
|
// By simply rerunning the script we add the new data to our existing
|
||||||
// pagedata object. this triggers vue and the filetree and filelist will
|
// pagedata object. this triggers vue and the filetree and filelist will
|
||||||
// render the new elements.
|
// render the new elements.
|
||||||
$('body').append($(resp).find('script#diff-data-script'));
|
$('body').append($(resp).find('script#diff-data-script'));
|
||||||
|
onShowMoreFiles();
|
||||||
callback(resp);
|
callback(resp);
|
||||||
}).fail(() => {
|
}).fail(() => {
|
||||||
|
$target.removeClass('disabled');
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initRepoDiffShowMore() {
|
export function initRepoDiffShowMore() {
|
||||||
$(document).on('click', 'a.diff-show-more-button', (e) => {
|
$(document).on('click', 'a#diff-show-more-files', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const $target = $(e.target);
|
||||||
|
loadMoreFiles($target.data('href'), () => {});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', 'a.diff-load-button', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const $target = $(e.target);
|
const $target = $(e.target);
|
||||||
|
|
||||||
|
@ -1665,6 +1665,9 @@
|
|||||||
background-color: var(--color-teal);
|
background-color: var(--color-teal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.button {
|
||||||
|
padding: 8px 12px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.diff-box .header:not(.resolved-placeholder) {
|
.diff-box .header:not(.resolved-placeholder) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user