Compare commits

...

17 Commits

Author SHA1 Message Date
zeripath
7ce938b6c7 Changelog 1.15.3 (#17091)
## [1.15.3](https://github.com/go-gitea/gitea/releases/tag/v1.15.3) - 2021-09-19

* ENHANCEMENTS
  * Add fluid to ui container class to remove margin (#16396) (#16976)
  * Add caller to cat-file batch calls (#17082) (#17089)
* BUGFIXES
  * Render full plain readme. (#17083) (#17090)
  * Upgrade xorm to v1.2.4 (#17059)
  * Fix bug of migrate comments which only fetch one page (#17055) (#17058)
  * Do not show issue context popup on external issues (#17050) (#17054)
  * Decrement Fork Num when converting from Fork (#17035) (#17046)
  * Correctly rollback in ForkRepository (#17034) (#17045)
  * Fix missing close in WalkGitLog (#17008) (#17009)
  * Add prefix to SVG id/class attributes (#16997) (#17000)
  * Fix bug of migrated repository not index (#16991) (#16996)
  * Skip AllowedUserVisibilityModes validation on update user if it is an organisation (#16988) (#16990)
  * Fix storage Iterate bug and Add storage doctor to delete garbage attachments (#16971) (#16977)
  * Fix issue with issue default mail template (#16956) (#16975)
  * Ensure that rebase conflicts are handled in updates (#16952) (#16960)
  * Prevent panic on diff generation (#16950) (#16951)

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2021-09-20 12:02:52 +08:00
zeripath
6139834e76 Add caller to cat-file batch calls (#17082) (#17089)
Some people still appear to report unclosed cat-files. This PR simply adds the caller
to the process descriptor for the CatFileBatch and CatFileBatchCheck calls.

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: techknowlogick <techknowlogick@gitea.io>

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2021-09-20 00:07:35 +08:00
zeripath
b673a24ee6 Render full plain readme. (#17083) (#17090)
Backport #17083

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
2021-09-19 22:01:19 +08:00
Lunny Xiao
fd35f56e87 Fix bug of migrate comments which only fetch one page (#17055) (#17058)
* Fix bug of migrate comments which only fetch one page

* add next page to trace

Co-authored-by: zeripath <art27@cantab.net>

Co-authored-by: zeripath <art27@cantab.net>
2021-09-15 14:01:54 -04:00
Lunny Xiao
1f8df5dd89 Upgrade xorm to v1.2.4 (#17059) 2021-09-15 23:27:46 +08:00
zeripath
6a025d8b4a Do not show issue context popup on external issues (#17050) (#17054)
Backport #17050

The issues pop-up context cannot work for external issues - therefore do not show
these.

Fix #17047

Signed-off-by: Andrew Thornton <art27@cantab.net>
2021-09-15 17:38:20 +08:00
zeripath
270c7f36db Correctly rollback in ForkRepository (#17034) (#17045)
Backport #17034

The rollback functionality in
services/repository/repository.go:ForkRepository is incorrect and could
lead to a deadlock as it uses DeleteRepository to delete the rolled-back
repository - a function which creates its own transaction.

This PR adjusts the rollback function to only use RemoveAll as any
database changes will be automatically rolled-back. It also handles
panics and adjusts the Close within WithTx to ensure that if there is a
panic the session will always be closed.

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2021-09-15 08:42:09 +03:00
zeripath
0e448fb96d Decrement Fork Num when converting from Fork (#17035) (#17046)
Backport #17035

When converting repositories from forks to normal the root NumFork needs to be
decremented too.

Fix #17026

Signed-off-by: Andrew Thornton <art27@cantab.net>
2021-09-15 10:05:47 +08:00
zeripath
659b946eda Fix missing close in WalkGitLog (#17008) (#17009)
Backport #17008

When the external context is cancelled it is possible for the
GitLogReader to not itself be Closed.

This PR does three things:

1. Instead of adding a plain defer it wraps the `g.Close` in a func as
`g` may change.
2. It adds the missing explicit g.Close - although the defer fix makes
this unnecessary.
3. It passes down the external context as the base context for the
GitLogReader meaning that the cancellation of the external context will
pass down automatically.

Fix #17007

Signed-off-by: Andrew Thornton <art27@cantab.net>
2021-09-10 17:46:06 +08:00
KN4CK3R
56ab5ec9ea Use filename as id/class prefix. (#16997) (#17000)
Currently the svg minifier (`make svg`) rewrites all `id` and `class` attributes in svg files. Every file gets the ids `a, b, ...`. If multiple svgs with ids are used on a page these ids are conflicting and the results are broken images.

| minified ids | unique ids |
| - | - |
| ![grafik](https://user-images.githubusercontent.com/1666336/132579375-59d3996f-c4e5-43b8-8c8d-82280c90d9e3.png) | ![grafik](https://user-images.githubusercontent.com/1666336/132579413-05bf9285-4e3b-4d0d-8f95-90b212405b05.png) |

This PR adds a prefix (the filename) to every id/class.

Follow up problem: Because we embed svg images there are duplicated ids if one svg image is used multiple times on a page. As those ids refer to the same content it may be no real problem because browser handle that fine.
2021-09-09 10:47:28 +01:00
6543
3b13c5d41a Fix bug of migrated repository not index (#16991) (#16996)
Fix #16986, #16152

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2021-09-09 07:02:22 +01:00
6543
d27f061863 Skip AllowedUserVisibilityModes validation on update user if it is an organisation (#16988) (#16990)
if AllowedUserVisibilityModes allow only public & limited, and orgs can be private, a user can create a repo to that organisation whitch will result in an update of the user. On this call the user is validaten and will be rejected since private is not allowed, but its not an user its an valid org ...

Co-authored-by: Alexey 〒erentyev <axifnx@gmail.com>

Co-authored-by: Alexey 〒erentyev <axifnx@gmail.com>
2021-09-08 23:58:00 +08:00
Lunny Xiao
07489d0405 Fix storage Iterate bug and Add storage doctor to delete garbage attachments (#16971) (#16977)
* Fix storage Iterate bug and Add storage doctor to delete garbage attachments

* Close object when used
2021-09-07 19:39:05 +01:00
Prasad Katti
30708d9ffe Fix issue with issue default mail template (#16956) (#16975)
Backport #16956

The mail template rendering was failing with the error -
`...vices/mailer/mail.go:301:composeIssueCommentMessages() [E] ExecuteTemplate [issue/default/body]: template: issue/default:65:10: executing "issue/default" at <.i18n.Tr>: can't evaluate field i18n in type *models.Comment`

The issue was the template variable i18n is available in the outer scope.

Fix #16877

Co-authored-by: 6543 <6543@obermui.de>
2021-09-07 10:06:59 +08:00
silverwind
1b08dfeacf Add fluid to ui container class to remove margin (#16396) (#16976)
Co-authored-by: Stanley Hu <stanthetiger@yahoo.com>
2021-09-07 03:37:32 +02:00
zeripath
e5ded0ee19 Ensure that rebase conflicts are handled in updates (#16952) (#16960)
Backport #16952

PR #16125 did not update the error handlers to handle conflict errors relating
to rebases. This PR adds them.

Fix #16922

Signed-off-by: Andrew Thornton <art27@cantab.net>
2021-09-05 18:54:13 +02:00
zeripath
a384109244 Prevent panic on diff generation (#16950) (#16951)
Backport #16950

The lastLeftIdx should be reset at the same time as creating a new section otherwise
it is possible for a second addition to end up attempting to read a nil entry.

Fix #16943

Signed-off-by: Andrew Thornton <art27@cantab.net>
2021-09-05 12:17:42 +02:00
41 changed files with 435 additions and 220 deletions

View File

@@ -4,6 +4,27 @@ This changelog goes through all the changes that have been made in each release
without substantial changes to our git log; to see the highlights of what has
been added to each release, please refer to the [blog](https://blog.gitea.io).
## [1.15.3](https://github.com/go-gitea/gitea/releases/tag/v1.15.3) - 2021-09-19
* ENHANCEMENTS
* Add fluid to ui container class to remove margin (#16396) (#16976)
* Add caller to cat-file batch calls (#17082) (#17089)
* BUGFIXES
* Render full plain readme. (#17083) (#17090)
* Upgrade xorm to v1.2.4 (#17059)
* Fix bug of migrate comments which only fetch one page (#17055) (#17058)
* Do not show issue context popup on external issues (#17050) (#17054)
* Decrement Fork Num when converting from Fork (#17035) (#17046)
* Correctly rollback in ForkRepository (#17034) (#17045)
* Fix missing close in WalkGitLog (#17008) (#17009)
* Add prefix to SVG id/class attributes (#16997) (#17000)
* Fix bug of migrated repository not index (#16991) (#16996)
* Skip AllowedUserVisibilityModes validation on update user if it is an organisation (#16988) (#16990)
* Fix storage Iterate bug and Add storage doctor to delete garbage attachments (#16971) (#16977)
* Fix issue with issue default mail template (#16956) (#16975)
* Ensure that rebase conflicts are handled in updates (#16952) (#16960)
* Prevent panic on diff generation (#16950) (#16951)
## [1.15.2](https://github.com/go-gitea/gitea/releases/tag/v1.15.2) - 2021-09-03
* BUGFIXES

View File

@@ -29,6 +29,7 @@ async function processFile(file, {prefix, fullName} = {}) {
plugins: extendDefaultPlugins([
'removeXMLNS',
'removeDimensions',
{name: 'prefixIds', params: {prefix: () => name}},
{
name: 'addClassesToSVGElement',
params: {classNames: ['svg', name]},

View File

@@ -124,7 +124,6 @@ func runRecreateTable(ctx *cli.Context) error {
}
func runDoctor(ctx *cli.Context) error {
// Silence the default loggers
log.DelNamedLogger("console")
log.DelNamedLogger(log.DEFAULT)

2
go.mod
View File

@@ -139,7 +139,7 @@ require (
mvdan.cc/xurls/v2 v2.2.0
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
xorm.io/builder v0.3.9
xorm.io/xorm v1.2.2
xorm.io/xorm v1.2.4
)
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1

4
go.sum
View File

@@ -1765,5 +1765,5 @@ xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/builder v0.3.9 h1:Sd65/LdWyO7LR8+Cbd+e7mm3sK/7U9k0jS3999IDHMc=
xorm.io/builder v0.3.9/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/xorm v1.0.6/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
xorm.io/xorm v1.2.2 h1:FFBOEvJ++8fYBA9cywf2sxDVmFktl1SpJzTAG1ab06Y=
xorm.io/xorm v1.2.2/go.mod h1:fTG8tSjk6O1BYxwuohZUK+S1glnRycsCF05L1qQyEU0=
xorm.io/xorm v1.2.4 h1:2MQV4wJt4kY6CYJsLxjCLzBen7+aqVxqDTIwfnR59g4=
xorm.io/xorm v1.2.4/go.mod h1:fTG8tSjk6O1BYxwuohZUK+S1glnRycsCF05L1qQyEU0=

View File

@@ -144,6 +144,11 @@ func GetAttachmentByUUID(uuid string) (*Attachment, error) {
return getAttachmentByUUID(x, uuid)
}
// ExistAttachmentsByUUID returns true if attachment is exist by given UUID
func ExistAttachmentsByUUID(uuid string) (bool, error) {
return x.Where("`uuid`=?", uuid).Exist(new(Attachment))
}
// GetAttachmentByReleaseIDFileName returns attachment by given releaseId and fileName.
func GetAttachmentByReleaseIDFileName(releaseID int64, fileName string) (*Attachment, error) {
return getAttachmentByReleaseIDFileName(x, releaseID, fileName)

View File

@@ -45,19 +45,16 @@ func WithContext(f func(ctx DBContext) error) error {
// WithTx represents executing database operations on a transaction
func WithTx(f func(ctx DBContext) error) error {
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
sess.Close()
return err
}
if err := f(DBContext{sess}); err != nil {
sess.Close()
return err
}
err := sess.Commit()
sess.Close()
return err
return sess.Commit()
}
// Iterate iterates the databases and doing something

View File

@@ -1217,6 +1217,12 @@ func IncrementRepoForkNum(ctx DBContext, repoID int64) error {
return err
}
// DecrementRepoForkNum decrement repository fork number
func DecrementRepoForkNum(ctx DBContext, repoID int64) error {
_, err := ctx.e.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repoID)
return err
}
// ChangeRepositoryName changes all corresponding setting from old repository name to new one.
func ChangeRepositoryName(doer *User, repo *Repository, newRepoName string) (err error) {
oldRepoName := repo.Name

View File

@@ -1062,9 +1062,9 @@ func checkDupEmail(e Engine, u *User) error {
return nil
}
// validateUser check if user is valide to insert / update into database
// validateUser check if user is valid to insert / update into database
func validateUser(u *User) error {
if !setting.Service.AllowedUserVisibilityModesSlice.IsAllowedVisibility(u.Visibility) {
if !setting.Service.AllowedUserVisibilityModesSlice.IsAllowedVisibility(u.Visibility) && !u.IsOrganization() {
return fmt.Errorf("visibility Mode not allowed: %s", u.Visibility.String())
}

76
modules/doctor/storage.go Normal file
View File

@@ -0,0 +1,76 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package doctor
import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/storage"
)
func checkAttachmentStorageFiles(logger log.Logger, autofix bool) error {
var total, garbageNum int
var deletePaths []string
if err := storage.Attachments.IterateObjects(func(p string, obj storage.Object) error {
defer obj.Close()
total++
stat, err := obj.Stat()
if err != nil {
return err
}
exist, err := models.ExistAttachmentsByUUID(stat.Name())
if err != nil {
return err
}
if !exist {
garbageNum++
if autofix {
deletePaths = append(deletePaths, p)
}
}
return nil
}); err != nil {
logger.Error("storage.Attachments.IterateObjects failed: %v", err)
return err
}
if garbageNum > 0 {
if autofix {
var deletedNum int
for _, p := range deletePaths {
if err := storage.Attachments.Delete(p); err != nil {
log.Error("Delete attachment %s failed: %v", p, err)
} else {
deletedNum++
}
}
logger.Info("%d missed information attachment detected, %d deleted.", garbageNum, deletedNum)
} else {
logger.Warn("Checked %d attachment, %d missed information.", total, garbageNum)
}
}
return nil
}
func checkStorageFiles(logger log.Logger, autofix bool) error {
if err := storage.Init(); err != nil {
logger.Error("storage.Init failed: %v", err)
return err
}
return checkAttachmentStorageFiles(logger, autofix)
}
func init() {
Register(&Check{
Title: "Check if there is garbage storage files",
Name: "storages",
IsDefault: false,
Run: checkStorageFiles,
AbortIfFailed: false,
SkipDatabaseInitialization: false,
Priority: 1,
})
}

View File

@@ -8,8 +8,10 @@ import (
"bufio"
"bytes"
"context"
"fmt"
"io"
"math"
"runtime"
"strconv"
"strings"
@@ -40,9 +42,14 @@ func CatFileBatchCheck(repoPath string) (WriteCloserError, *bufio.Reader, func()
<-closed
}
_, filename, line, _ := runtime.Caller(2)
filename = strings.TrimPrefix(filename, callerPrefix)
go func() {
stderr := strings.Builder{}
err := NewCommandContext(ctx, "cat-file", "--batch-check").RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
err := NewCommandContext(ctx, "cat-file", "--batch-check").
SetDescription(fmt.Sprintf("%s cat-file --batch-check [repo_path: %s] (%s:%d)", GitExecutable, repoPath, filename, line)).
RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
if err != nil {
_ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
_ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
@@ -76,9 +83,14 @@ func CatFileBatch(repoPath string) (WriteCloserError, *bufio.Reader, func()) {
<-closed
}
_, filename, line, _ := runtime.Caller(2)
filename = strings.TrimPrefix(filename, callerPrefix)
go func() {
stderr := strings.Builder{}
err := NewCommandContext(ctx, "cat-file", "--batch").RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
err := NewCommandContext(ctx, "cat-file", "--batch").
SetDescription(fmt.Sprintf("%s cat-file --batch [repo_path: %s] (%s:%d)", GitExecutable, repoPath, filename, line)).
RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
if err != nil {
_ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
_ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
@@ -292,3 +304,10 @@ func ParseTreeLine(rd *bufio.Reader, modeBuf, fnameBuf, shaBuf []byte) (mode, fn
sha = shaBuf
return
}
var callerPrefix string
func init() {
_, filename, _, _ := runtime.Caller(0)
callerPrefix = strings.TrimSuffix(filename, "modules/git/batch_reader.go")
}

View File

@@ -18,11 +18,16 @@ import (
)
// LogNameStatusRepo opens git log --raw in the provided repo and returns a stdin pipe, a stdout reader and cancel function
func LogNameStatusRepo(repository, head, treepath string, paths ...string) (*bufio.Reader, func()) {
func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, paths ...string) (*bufio.Reader, func()) {
// We often want to feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
// so let's create a batch stdin and stdout
stdoutReader, stdoutWriter := nio.Pipe(buffer.New(32 * 1024))
// Lets also create a context so that we can absolutely ensure that the command should die when we're done
ctx, ctxCancel := context.WithCancel(ctx)
cancel := func() {
ctxCancel()
_ = stdoutReader.Close()
_ = stdoutWriter.Close()
}
@@ -50,7 +55,7 @@ func LogNameStatusRepo(repository, head, treepath string, paths ...string) (*buf
go func() {
stderr := strings.Builder{}
err := NewCommand(args...).RunInDirFullPipeline(repository, stdoutWriter, &stderr, nil)
err := NewCommandContext(ctx, args...).RunInDirFullPipeline(repository, stdoutWriter, &stderr, nil)
if err != nil {
_ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
} else {
@@ -75,8 +80,8 @@ type LogNameStatusRepoParser struct {
}
// NewLogNameStatusRepoParser returns a new parser for a git log raw output
func NewLogNameStatusRepoParser(repository, head, treepath string, paths ...string) *LogNameStatusRepoParser {
rd, cancel := LogNameStatusRepo(repository, head, treepath, paths...)
func NewLogNameStatusRepoParser(ctx context.Context, repository, head, treepath string, paths ...string) *LogNameStatusRepoParser {
rd, cancel := LogNameStatusRepo(ctx, repository, head, treepath, paths...)
return &LogNameStatusRepoParser{
treepath: treepath,
paths: paths,
@@ -311,8 +316,11 @@ func WalkGitLog(ctx context.Context, repo *Repository, head *Commit, treepath st
}
}
g := NewLogNameStatusRepoParser(repo.Path, head.ID.String(), treepath, paths...)
defer g.Close()
g := NewLogNameStatusRepoParser(ctx, repo.Path, head.ID.String(), treepath, paths...)
// don't use defer g.Close() here as g may change its value - instead wrap in a func
defer func() {
g.Close()
}()
results := make([]string, len(paths))
remaining := len(paths)
@@ -331,6 +339,7 @@ heaploop:
for {
select {
case <-ctx.Done():
g.Close()
return nil, ctx.Err()
default:
}
@@ -380,7 +389,7 @@ heaploop:
remainingPaths = append(remainingPaths, pth)
}
}
g = NewLogNameStatusRepoParser(repo.Path, lastEmptyParent, treepath, remainingPaths...)
g = NewLogNameStatusRepoParser(ctx, repo.Path, lastEmptyParent, treepath, remainingPaths...)
parentRemaining = map[string]bool{}
nextRestart = (remaining * 3) / 4
continue heaploop

View File

@@ -827,7 +827,7 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
reftext := node.Data[ref.RefLocation.Start:ref.RefLocation.End]
if exttrack && !ref.IsPull {
ctx.Metas["index"] = ref.Issue
link = createLink(com.Expand(ctx.Metas["format"], ctx.Metas), reftext, "ref-issue")
link = createLink(com.Expand(ctx.Metas["format"], ctx.Metas), reftext, "ref-issue ref-external-issue")
} else {
// Path determines the type of link that will be rendered. It's unknown at this point whether
// the linked item is actually a PR or an issue. Luckily it's of no real consequence because

View File

@@ -96,12 +96,14 @@ func TestRender_IssueIndexPattern2(t *testing.T) {
// numeric: render inputs with valid mentions
test := func(s, expectedFmt, marker string, indices ...int) {
var path, prefix string
isExternal := false
if marker == "!" {
path = "pulls"
prefix = "http://localhost:3000/someUser/someRepo/pulls/"
} else {
path = "issues"
prefix = "https://someurl.com/someUser/someRepo/"
isExternal = true
}
links := make([]interface{}, len(indices))
@@ -111,8 +113,13 @@ func TestRender_IssueIndexPattern2(t *testing.T) {
expectedNil := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expectedNil, &RenderContext{Metas: localMetas})
class := "ref-issue"
if isExternal {
class += " ref-external-issue"
}
for i, index := range indices {
links[i] = numericIssueLink(prefix, "ref-issue", index, marker)
links[i] = numericIssueLink(prefix, class, index, marker)
}
expectedNum := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expectedNum, &RenderContext{Metas: numericMetas})
@@ -178,7 +185,7 @@ func TestRender_IssueIndexPattern4(t *testing.T) {
test := func(s, expectedFmt string, names ...string) {
links := make([]interface{}, len(names))
for i, name := range names {
links[i] = alphanumIssueLink("https://someurl.com/someUser/someRepo/", "ref-issue", name)
links[i] = alphanumIssueLink("https://someurl.com/someUser/someRepo/", "ref-issue ref-external-issue", name)
}
expected := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expected, &RenderContext{Metas: alphanumericMetas})

View File

@@ -66,7 +66,7 @@ func createDefaultPolicy() *bluemonday.Policy {
}
// Allow classes for anchors
policy.AllowAttrs("class").Matching(regexp.MustCompile(`ref-issue`)).OnElements("a")
policy.AllowAttrs("class").Matching(regexp.MustCompile(`ref-issue( ref-external-issue)?`)).OnElements("a")
// Allow classes for task lists
policy.AllowAttrs("class").Matching(regexp.MustCompile(`task-list-item`)).OnElements("li")

View File

@@ -541,6 +541,9 @@ func (g *GithubDownloaderV3) GetAllComments(page, perPage int) ([]*base.Comment,
created = "created"
asc = "asc"
)
if perPage > g.maxPerPage {
perPage = g.maxPerPage
}
opt := &github.IssueListCommentsOptions{
Sort: &created,
Direction: &asc,
@@ -555,7 +558,9 @@ func (g *GithubDownloaderV3) GetAllComments(page, perPage int) ([]*base.Comment,
if err != nil {
return nil, false, fmt.Errorf("error while listing repos: %v", err)
}
log.Trace("Request get comments %d/%d, but in fact get %d", perPage, page, len(comments))
var isEnd = resp.NextPage == 0
log.Trace("Request get comments %d/%d, but in fact get %d, next page is %d", perPage, page, len(comments), resp.NextPage)
g.rate = &resp.Rate
for _, comment := range comments {
var email string
@@ -600,7 +605,7 @@ func (g *GithubDownloaderV3) GetAllComments(page, perPage int) ([]*base.Comment,
})
}
return allComments, len(allComments) < perPage, nil
return allComments, isEnd, nil
}
// GetPullRequests returns pull requests according page and perPage

View File

@@ -13,6 +13,7 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
)
// ForkRepository forks a repository
@@ -45,38 +46,60 @@ func ForkRepository(doer, owner *models.User, oldRepo *models.Repository, name,
oldRepoPath := oldRepo.RepoPath()
needsRollback := false
rollbackFn := func() {
if !needsRollback {
return
}
repoPath := models.RepoPath(owner.Name, repo.Name)
if exists, _ := util.IsExist(repoPath); !exists {
return
}
// As the transaction will be failed and hence database changes will be destroyed we only need
// to delete the related repository on the filesystem
if errDelete := util.RemoveAll(repoPath); errDelete != nil {
log.Error("Failed to remove fork repo")
}
}
needsRollbackInPanic := true
defer func() {
panicErr := recover()
if panicErr == nil {
return
}
if needsRollbackInPanic {
rollbackFn()
}
panic(panicErr)
}()
err = models.WithTx(func(ctx models.DBContext) error {
if err = models.CreateRepository(ctx, doer, owner, repo, false); err != nil {
return err
}
rollbackRemoveFn := func() {
if repo.ID == 0 {
return
}
if errDelete := models.DeleteRepository(doer, owner.ID, repo.ID); errDelete != nil {
log.Error("Rollback deleteRepository: %v", errDelete)
}
}
if err = models.IncrementRepoForkNum(ctx, oldRepo.ID); err != nil {
rollbackRemoveFn()
return err
}
// copy lfs files failure should not be ignored
if err := models.CopyLFS(ctx, repo, oldRepo); err != nil {
rollbackRemoveFn()
if err = models.CopyLFS(ctx, repo, oldRepo); err != nil {
return err
}
needsRollback = true
repoPath := models.RepoPath(owner.Name, repo.Name)
if stdout, err := git.NewCommand(
"clone", "--bare", oldRepoPath, repoPath).
SetDescription(fmt.Sprintf("ForkRepository(git clone): %s to %s", oldRepo.FullName(), repo.FullName())).
RunInDirTimeout(10*time.Minute, ""); err != nil {
log.Error("Fork Repository (git clone) Failed for %v (from %v):\nStdout: %s\nError: %v", repo, oldRepo, stdout, err)
rollbackRemoveFn()
return fmt.Errorf("git clone: %v", err)
}
@@ -84,23 +107,23 @@ func ForkRepository(doer, owner *models.User, oldRepo *models.Repository, name,
SetDescription(fmt.Sprintf("ForkRepository(git update-server-info): %s", repo.FullName())).
RunInDir(repoPath); err != nil {
log.Error("Fork Repository (git update-server-info) failed for %v:\nStdout: %s\nError: %v", repo, stdout, err)
rollbackRemoveFn()
return fmt.Errorf("git update-server-info: %v", err)
}
if err = createDelegateHooks(repoPath); err != nil {
rollbackRemoveFn()
return fmt.Errorf("createDelegateHooks: %v", err)
}
return nil
})
needsRollbackInPanic = false
if err != nil {
rollbackFn()
return nil, err
}
// even if below operations failed, it could be ignored. And they will be retried
ctx := models.DefaultDBContext()
if err = repo.UpdateSize(ctx); err != nil {
if err := repo.UpdateSize(ctx); err != nil {
log.Error("Failed to update size for repository: %v", err)
}
if err := models.CopyLanguageStat(oldRepo, repo); err != nil {
@@ -109,3 +132,34 @@ func ForkRepository(doer, owner *models.User, oldRepo *models.Repository, name,
return repo, nil
}
// ConvertForkToNormalRepository convert the provided repo from a forked repo to normal repo
func ConvertForkToNormalRepository(repo *models.Repository) error {
err := models.WithTx(func(ctx models.DBContext) error {
repo, err := models.GetRepositoryByIDCtx(ctx, repo.ID)
if err != nil {
return err
}
if !repo.IsFork {
return nil
}
if err := models.DecrementRepoForkNum(ctx, repo.ForkID); err != nil {
log.Error("Unable to decrement repo fork num for old root repo %d of repository %-v whilst converting from fork. Error: %v", repo.ForkID, repo, err)
return err
}
repo.IsFork = false
repo.ForkID = 0
if err := models.UpdateRepositoryCtx(ctx, repo, false); err != nil {
log.Error("Unable to update repository %-v whilst converting from fork. Error: %v", repo, err)
return err
}
return nil
})
return err
}

View File

@@ -151,7 +151,7 @@ type minioFileInfo struct {
}
func (m minioFileInfo) Name() string {
return m.ObjectInfo.Key
return path.Base(m.ObjectInfo.Key)
}
func (m minioFileInfo) Size() int64 {
@@ -219,7 +219,7 @@ func (m *MinioStorage) IterateObjects(fn func(path string, obj Object) error) er
}
if err := func(object *minio.Object, fn func(path string, obj Object) error) error {
defer object.Close()
return fn(strings.TrimPrefix(m.basePath, mObjInfo.Key), &minioObject{object})
return fn(strings.TrimPrefix(mObjInfo.Key, m.basePath), &minioObject{object})
}(object, fn); err != nil {
return convertMinioErr(err)
}

View File

@@ -93,7 +93,6 @@ func runMigrateTask(t *models.Task) (err error) {
}
opts.MigrateToRepoID = t.RepoID
var repo *models.Repository
ctx, cancel := context.WithCancel(graceful.GetManager().ShutdownContext())
defer cancel()
@@ -107,7 +106,7 @@ func runMigrateTask(t *models.Task) (err error) {
return
}
repo, err = migrations.MigrateRepository(ctx, t.Doer, t.Owner.Name, *opts, func(format string, args ...interface{}) {
t.Repo, err = migrations.MigrateRepository(ctx, t.Doer, t.Owner.Name, *opts, func(format string, args ...interface{}) {
message := models.TranslatableMessage{
Format: format,
Args: args,
@@ -118,7 +117,7 @@ func runMigrateTask(t *models.Task) (err error) {
_ = t.UpdateCols("message")
})
if err == nil {
log.Trace("Repository migrated [%d]: %s/%s", repo.ID, t.Owner.Name, repo.Name)
log.Trace("Repository migrated [%d]: %s/%s", t.Repo.ID, t.Owner.Name, t.Repo.Name)
return
}

View File

@@ -1 +1 @@
<svg viewBox="0 0 64 64" class="svg gitea-github" width="16" height="16" aria-hidden="true"><linearGradient id="a" x1="30.999" x2="30.999" y1="16" y2="55.342" gradientUnits="userSpaceOnUse" spreadMethod="reflect"><stop offset="0" stop-color="#6dc7ff"/><stop offset="1" stop-color="#e6abff"/></linearGradient><path fill="url(#a)" d="M25.008 56.007c-.003-.368-.006-1.962-.009-3.454l-.003-1.55c-6.729.915-8.358-3.78-8.376-3.83-.934-2.368-2.211-3.045-2.266-3.073l-.124-.072c-.463-.316-1.691-1.157-1.342-2.263.315-.997 1.536-1.1 2.091-1.082 3.074.215 4.63 2.978 4.694 3.095 1.569 2.689 3.964 2.411 5.509 1.844.144-.688.367-1.32.659-1.878-4.956-.879-10.571-3.515-10.571-13.104 0-2.633.82-4.96 2.441-6.929-.362-1.206-.774-3.666.446-6.765l.174-.442.452-.144c.416-.137 2.688-.624 7.359 2.433a24.959 24.959 0 0 1 6.074-.759c2.115.01 4.158.265 6.09.759 4.667-3.058 6.934-2.565 7.351-2.433l.451.145.174.44c1.225 3.098.813 5.559.451 6.766 1.618 1.963 2.438 4.291 2.438 6.929 0 9.591-5.621 12.219-10.588 13.087.563 1.065.868 2.402.868 3.878 0 1.683-.007 7.204-.015 8.402l-2-.014c.008-1.196.015-6.708.015-8.389 0-2.442-.943-3.522-1.35-3.874l-1.73-1.497 2.274-.253c5.205-.578 10.525-2.379 10.525-11.341 0-2.33-.777-4.361-2.31-6.036l-.43-.469.242-.587c.166-.401.894-2.442-.043-5.291-.758.045-2.568.402-5.584 2.447l-.384.259-.445-.123c-1.863-.518-3.938-.796-6.001-.806-2.052.01-4.124.288-5.984.806l-.445.123-.383-.259c-3.019-2.044-4.833-2.404-5.594-2.449-.935 2.851-.206 4.892-.04 5.293l.242.587-.429.469c-1.536 1.681-2.314 3.712-2.314 6.036 0 8.958 5.31 10.77 10.504 11.361l2.252.256-1.708 1.49c-.372.325-1.03 1.112-1.254 2.727l-.075.549-.506.227c-1.321.592-5.839 2.162-8.548-2.485-.015-.025-.544-.945-1.502-1.557.646.639 1.433 1.673 2.068 3.287.066.19 1.357 3.622 7.28 2.339l1.206-.262.012 3.978c.003 1.487.006 3.076.009 3.444l-1.998.014z"/><linearGradient id="b" x1="32" x2="32" y1="5" y2="59.167" gradientUnits="userSpaceOnUse" spreadMethod="reflect"><stop offset="0" stop-color="#1a6dff"/><stop offset="1" stop-color="#c822ff"/></linearGradient><path fill="url(#b)" d="M32 58C17.663 58 6 46.337 6 32S17.663 6 32 6s26 11.663 26 26-11.663 26-26 26zm0-50C18.767 8 8 18.767 8 32s10.767 24 24 24 24-10.767 24-24S45.233 8 32 8z"/></svg>
<svg viewBox="0 0 64 64" class="svg gitea-github" width="16" height="16" aria-hidden="true"><linearGradient id="gitea-github__a" x1="30.999" x2="30.999" y1="16" y2="55.342" gradientUnits="userSpaceOnUse" spreadMethod="reflect"><stop offset="0" stop-color="#6dc7ff"/><stop offset="1" stop-color="#e6abff"/></linearGradient><path fill="url(#gitea-github__a)" d="M25.008 56.007c-.003-.368-.006-1.962-.009-3.454l-.003-1.55c-6.729.915-8.358-3.78-8.376-3.83-.934-2.368-2.211-3.045-2.266-3.073l-.124-.072c-.463-.316-1.691-1.157-1.342-2.263.315-.997 1.536-1.1 2.091-1.082 3.074.215 4.63 2.978 4.694 3.095 1.569 2.689 3.964 2.411 5.509 1.844.144-.688.367-1.32.659-1.878-4.956-.879-10.571-3.515-10.571-13.104 0-2.633.82-4.96 2.441-6.929-.362-1.206-.774-3.666.446-6.765l.174-.442.452-.144c.416-.137 2.688-.624 7.359 2.433a24.959 24.959 0 0 1 6.074-.759c2.115.01 4.158.265 6.09.759 4.667-3.058 6.934-2.565 7.351-2.433l.451.145.174.44c1.225 3.098.813 5.559.451 6.766 1.618 1.963 2.438 4.291 2.438 6.929 0 9.591-5.621 12.219-10.588 13.087.563 1.065.868 2.402.868 3.878 0 1.683-.007 7.204-.015 8.402l-2-.014c.008-1.196.015-6.708.015-8.389 0-2.442-.943-3.522-1.35-3.874l-1.73-1.497 2.274-.253c5.205-.578 10.525-2.379 10.525-11.341 0-2.33-.777-4.361-2.31-6.036l-.43-.469.242-.587c.166-.401.894-2.442-.043-5.291-.758.045-2.568.402-5.584 2.447l-.384.259-.445-.123c-1.863-.518-3.938-.796-6.001-.806-2.052.01-4.124.288-5.984.806l-.445.123-.383-.259c-3.019-2.044-4.833-2.404-5.594-2.449-.935 2.851-.206 4.892-.04 5.293l.242.587-.429.469c-1.536 1.681-2.314 3.712-2.314 6.036 0 8.958 5.31 10.77 10.504 11.361l2.252.256-1.708 1.49c-.372.325-1.03 1.112-1.254 2.727l-.075.549-.506.227c-1.321.592-5.839 2.162-8.548-2.485-.015-.025-.544-.945-1.502-1.557.646.639 1.433 1.673 2.068 3.287.066.19 1.357 3.622 7.28 2.339l1.206-.262.012 3.978c.003 1.487.006 3.076.009 3.444l-1.998.014z"/><linearGradient id="gitea-github__b" x1="32" x2="32" y1="5" y2="59.167" gradientUnits="userSpaceOnUse" spreadMethod="reflect"><stop offset="0" stop-color="#1a6dff"/><stop offset="1" stop-color="#c822ff"/></linearGradient><path fill="url(#gitea-github__b)" d="M32 58C17.663 58 6 46.337 6 32S17.663 6 32 6s26 11.663 26 26-11.663 26-26 26zm0-50C18.767 8 8 18.767 8 32s10.767 24 24 24 24-10.767 24-24S45.233 8 32 8z"/></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -119,13 +119,15 @@ func GetArchive(ctx *context.APIContext) {
// "$ref": "#/responses/notFound"
repoPath := models.RepoPath(ctx.Params(":username"), ctx.Params(":reponame"))
gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
ctx.Error(http.StatusInternalServerError, "OpenRepository", err)
return
if ctx.Repo.GitRepo == nil {
gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
ctx.Error(http.StatusInternalServerError, "OpenRepository", err)
return
}
ctx.Repo.GitRepo = gitRepo
defer gitRepo.Close()
}
ctx.Repo.GitRepo = gitRepo
defer gitRepo.Close()
repo.Download(ctx.Context)
}

View File

@@ -1130,6 +1130,9 @@ func UpdatePullRequest(ctx *context.APIContext) {
if models.IsErrMergeConflicts(err) {
ctx.Error(http.StatusConflict, "Update", "merge failed because of conflict")
return
} else if models.IsErrRebaseConflicts(err) {
ctx.Error(http.StatusConflict, "Update", "rebase failed because of conflict")
return
}
ctx.Error(http.StatusInternalServerError, "pull_service.Update", err)
return

View File

@@ -752,6 +752,21 @@ func UpdatePullRequest(ctx *context.Context) {
ctx.Flash.Error(flashError)
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index))
return
} else if models.IsErrRebaseConflicts(err) {
conflictError := err.(models.ErrRebaseConflicts)
flashError, err := ctx.HTMLString(string(tplAlertDetails), map[string]interface{}{
"Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)),
"Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"),
"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
})
if err != nil {
ctx.ServerError("UpdatePullRequest.HTMLString", err)
return
}
ctx.Flash.Error(flashError)
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index))
return
}
ctx.Flash.Error(err.Error())
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index))

View File

@@ -538,10 +538,8 @@ func SettingsPost(ctx *context.Context) {
return
}
repo.IsFork = false
repo.ForkID = 0
if err := models.UpdateRepository(repo, false); err != nil {
log.Error("Unable to update repository %-v whilst converting from fork", repo)
if err := repository.ConvertForkToNormalRepository(repo); err != nil {
log.Error("Unable to convert repository %-v from fork. Error: %v", repo, err)
ctx.ServerError("Convert Fork", err)
return
}

View File

@@ -353,6 +353,10 @@ func renderDirectory(ctx *context.Context, treeLink string) {
}
} else {
ctx.Data["IsRenderedHTML"] = true
buf, err = ioutil.ReadAll(rd)
if err != nil {
log.Error("ReadAll failed: %v", err)
}
ctx.Data["FileContent"] = strings.ReplaceAll(
gotemplate.HTMLEscapeString(string(buf)), "\n", `<br>`,
)

View File

@@ -996,6 +996,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
// Create a new section to represent this hunk
curSection = &DiffSection{}
lastLeftIdx = -1
curFile.Sections = append(curFile.Sections, curSection)
lineSectionInfo := getDiffLineSectionInfo(curFile.Name, line, leftLine-1, rightLine-1)
@@ -1036,6 +1037,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
// Create a new section to represent this hunk
curSection = &DiffSection{}
curFile.Sections = append(curFile.Sections, curSection)
lastLeftIdx = -1
}
if lastLeftIdx > -1 {
diffLine.Match = lastLeftIdx
@@ -1061,6 +1063,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
// Create a new section to represent this hunk
curSection = &DiffSection{}
curFile.Sections = append(curFile.Sections, curSection)
lastLeftIdx = -1
}
if len(curSection.Lines) == 0 || curSection.Lines[len(curSection.Lines)-1].Type != DiffLineDel {
lastLeftIdx = len(curSection.Lines)
@@ -1121,6 +1124,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
curFile.IsBin = true
curFile.IsLFSFile = true
curSection.Lines = nil
lastLeftIdx = -1
}
}
}

View File

@@ -62,7 +62,7 @@
{{end -}}
{{- range .ReviewComments}}
<hr>
{{.i18n.Tr "mail.issue.in_tree_path" .TreePath}}
{{$.i18n.Tr "mail.issue.in_tree_path" .TreePath}}
<div class="review">
<pre>{{.Patch}}</pre>
<div>{{.RenderedContent | Safe}}</div>

View File

@@ -2,7 +2,7 @@
<div class="page-content user signin{{if .LinkAccountMode}} icon{{end}}">
{{template "user/auth/signin_navbar" .}}
<div class="ui middle very relaxed page grid">
<div class="ui container column">
<div class="ui container column fluid">
{{template "user/auth/signin_inner" .}}
</div>
</div>

View File

@@ -1,4 +1,4 @@
<div class="ui container column{{if .LinkAccountMode}} icon{{end}}">
<div class="ui container column fluid{{if .LinkAccountMode}} icon{{end}}">
<h4 class="ui top attached header center">
{{if .LinkAccountMode}}
{{.i18n.Tr "auth.oauth_signup_title"}}

2
vendor/modules.txt vendored
View File

@@ -1047,7 +1047,7 @@ strk.kbt.io/projects/go/libravatar
# xorm.io/builder v0.3.9
## explicit
xorm.io/builder
# xorm.io/xorm v1.2.2
# xorm.io/xorm v1.2.4
## explicit
xorm.io/xorm
xorm.io/xorm/caches

View File

@@ -325,6 +325,9 @@ func AssignValue(dv reflect.Value, src interface{}) error {
if src == nil {
return nil
}
if v, ok := src.(*interface{}); ok {
return AssignValue(dv, *v)
}
if dv.Type().Implements(scannerType) {
return dv.Interface().(sql.Scanner).Scan(src)

View File

@@ -103,6 +103,39 @@ func (db *Base) URI() *URI {
return db.uri
}
// CreateTableSQL implements Dialect
func (db *Base) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
if tableName == "" {
tableName = table.Name
}
quoter := db.dialect.Quoter()
var b strings.Builder
b.WriteString("CREATE TABLE IF NOT EXISTS ")
quoter.QuoteTo(&b, tableName)
b.WriteString(" (")
for i, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName)
s, _ := ColumnString(db.dialect, col, col.IsPrimaryKey && len(table.PrimaryKeys) == 1)
b.WriteString(s)
if i != len(table.ColumnsSeq())-1 {
b.WriteString(", ")
}
}
if len(table.PrimaryKeys) > 1 {
b.WriteString(", PRIMARY KEY (")
b.WriteString(quoter.Join(table.PrimaryKeys, ","))
b.WriteString(")")
}
b.WriteString(")")
return []string{b.String()}, false
}
// DropTableSQL returns drop table SQL
func (db *Base) DropTableSQL(tableName string) (string, bool) {
quote := db.dialect.Quoter().Quote

View File

@@ -626,34 +626,37 @@ WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
}
func (db *mssql) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
var sql string
if tableName == "" {
tableName = table.Name
}
sql = "IF NOT EXISTS (SELECT [name] FROM sys.tables WHERE [name] = '" + tableName + "' ) CREATE TABLE "
quoter := db.dialect.Quoter()
var b strings.Builder
b.WriteString("IF NOT EXISTS (SELECT [name] FROM sys.tables WHERE [name] = '")
quoter.QuoteTo(&b, tableName)
b.WriteString("' ) CREATE TABLE ")
quoter.QuoteTo(&b, tableName)
b.WriteString(" (")
sql += db.Quoter().Quote(tableName) + " ("
pkList := table.PrimaryKeys
for _, colName := range table.ColumnsSeq() {
for i, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName)
s, _ := ColumnString(db, col, col.IsPrimaryKey && len(pkList) == 1)
sql += s
sql = strings.TrimSpace(sql)
sql += ", "
s, _ := ColumnString(db.dialect, col, col.IsPrimaryKey && len(table.PrimaryKeys) == 1)
b.WriteString(s)
if i != len(table.ColumnsSeq())-1 {
b.WriteString(", ")
}
}
if len(pkList) > 1 {
sql += "PRIMARY KEY ( "
sql += strings.Join(pkList, ",")
sql += " ), "
if len(table.PrimaryKeys) > 1 {
b.WriteString(", PRIMARY KEY (")
b.WriteString(quoter.Join(table.PrimaryKeys, ","))
b.WriteString(")")
}
sql = sql[:len(sql)-2] + ")"
sql += ";"
return []string{sql}, true
b.WriteString(")")
return []string{b.String()}, true
}
func (db *mssql) ForUpdateSQL(query string) string {

View File

@@ -626,42 +626,43 @@ func (db *mysql) GetIndexes(queryer core.Queryer, ctx context.Context, tableName
}
func (db *mysql) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
var sql = "CREATE TABLE IF NOT EXISTS "
if tableName == "" {
tableName = table.Name
}
quoter := db.Quoter()
quoter := db.dialect.Quoter()
var b strings.Builder
b.WriteString("CREATE TABLE IF NOT EXISTS ")
quoter.QuoteTo(&b, tableName)
b.WriteString(" (")
sql += quoter.Quote(tableName)
sql += " ("
for i, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName)
s, _ := ColumnString(db.dialect, col, col.IsPrimaryKey && len(table.PrimaryKeys) == 1)
b.WriteString(s)
if len(table.ColumnsSeq()) > 0 {
pkList := table.PrimaryKeys
for _, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName)
s, _ := ColumnString(db, col, col.IsPrimaryKey && len(pkList) == 1)
sql += s
sql = strings.TrimSpace(sql)
if len(col.Comment) > 0 {
sql += " COMMENT '" + col.Comment + "'"
}
sql += ", "
if len(col.Comment) > 0 {
b.WriteString(" COMMENT '")
b.WriteString(col.Comment)
b.WriteString("'")
}
if len(pkList) > 1 {
sql += "PRIMARY KEY ( "
sql += quoter.Join(pkList, ",")
sql += " ), "
if i != len(table.ColumnsSeq())-1 {
b.WriteString(", ")
}
sql = sql[:len(sql)-2]
}
sql += ")"
if len(table.PrimaryKeys) > 1 {
b.WriteString(", PRIMARY KEY (")
b.WriteString(quoter.Join(table.PrimaryKeys, ","))
b.WriteString(")")
}
b.WriteString(")")
if table.StoreEngine != "" {
sql += " ENGINE=" + table.StoreEngine
b.WriteString(" ENGINE=")
b.WriteString(table.StoreEngine)
}
var charset = table.Charset
@@ -669,13 +670,15 @@ func (db *mysql) CreateTableSQL(table *schemas.Table, tableName string) ([]strin
charset = db.URI().Charset
}
if len(charset) != 0 {
sql += " DEFAULT CHARSET " + charset
b.WriteString(" DEFAULT CHARSET ")
b.WriteString(charset)
}
if db.rowFormat != "" {
sql += " ROW_FORMAT=" + db.rowFormat
b.WriteString(" ROW_FORMAT=")
b.WriteString(db.rowFormat)
}
return []string{sql}, true
return []string{b.String()}, true
}
func (db *mysql) Filters() []Filter {

View File

@@ -965,41 +965,6 @@ func (db *postgres) AutoIncrStr() string {
return ""
}
func (db *postgres) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
var sql string
sql = "CREATE TABLE IF NOT EXISTS "
if tableName == "" {
tableName = table.Name
}
quoter := db.Quoter()
sql += quoter.Quote(tableName)
sql += " ("
if len(table.ColumnsSeq()) > 0 {
pkList := table.PrimaryKeys
for _, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName)
s, _ := ColumnString(db, col, col.IsPrimaryKey && len(pkList) == 1)
sql += s
sql = strings.TrimSpace(sql)
sql += ", "
}
if len(pkList) > 1 {
sql += "PRIMARY KEY ( "
sql += quoter.Join(pkList, ",")
sql += " ), "
}
sql = sql[:len(sql)-2]
}
sql += ")"
return []string{sql}, true
}
func (db *postgres) IndexCheckSQL(tableName, idxName string) (string, []interface{}) {
if len(db.getSchema()) == 0 {
args := []interface{}{tableName, idxName}

View File

@@ -285,41 +285,6 @@ func (db *sqlite3) DropIndexSQL(tableName string, index *schemas.Index) string {
return fmt.Sprintf("DROP INDEX %v", db.Quoter().Quote(idxName))
}
func (db *sqlite3) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
var sql string
sql = "CREATE TABLE IF NOT EXISTS "
if tableName == "" {
tableName = table.Name
}
quoter := db.Quoter()
sql += quoter.Quote(tableName)
sql += " ("
if len(table.ColumnsSeq()) > 0 {
pkList := table.PrimaryKeys
for _, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName)
s, _ := ColumnString(db, col, col.IsPrimaryKey && len(pkList) == 1)
sql += s
sql = strings.TrimSpace(sql)
sql += ", "
}
if len(pkList) > 1 {
sql += "PRIMARY KEY ( "
sql += quoter.Join(pkList, ",")
sql += " ), "
}
sql = sql[:len(sql)-2]
}
sql += ")"
return []string{sql}, true
}
func (db *sqlite3) ForUpdateSQL(query string) string {
return query
}

25
vendor/xorm.io/xorm/internal/utils/new.go generated vendored Normal file
View File

@@ -0,0 +1,25 @@
// Copyright 2021 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package utils
import "reflect"
// New creates a value according type
func New(tp reflect.Type, length, cap int) reflect.Value {
switch tp.Kind() {
case reflect.Slice:
slice := reflect.MakeSlice(tp, length, cap)
x := reflect.New(slice.Type())
x.Elem().Set(slice)
return x
case reflect.Map:
mp := reflect.MakeMapWithSize(tp, cap)
x := reflect.New(mp.Type())
x.Elem().Set(mp)
return x
default:
return reflect.New(tp)
}
}

10
vendor/xorm.io/xorm/rows.go generated vendored
View File

@@ -84,12 +84,18 @@ func newRows(session *Session, bean interface{}) (*Rows, error) {
// Next move cursor to next record, return false if end has reached
func (rows *Rows) Next() bool {
return rows.rows.Next()
if rows.rows != nil {
return rows.rows.Next()
}
return false
}
// Err returns the error, if any, that was encountered during iteration. Err may be called after an explicit or implicit Close.
func (rows *Rows) Err() error {
return rows.rows.Err()
if rows.rows != nil {
return rows.rows.Err()
}
return nil
}
// Scan row record to bean properties

5
vendor/xorm.io/xorm/session.go generated vendored
View File

@@ -174,6 +174,11 @@ func (session *Session) Engine() *Engine {
return session.engine
}
// Tx returns session tx
func (session *Session) Tx() *core.Tx {
return session.tx
}
func (session *Session) getQueryer() core.Queryer {
if session.tx != nil {
return session.tx

62
vendor/xorm.io/xorm/session_find.go generated vendored
View File

@@ -161,6 +161,16 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
}
func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect.Value, sqlStr string, args ...interface{}) error {
elemType := containerValue.Type().Elem()
var isPointer bool
if elemType.Kind() == reflect.Ptr {
isPointer = true
elemType = elemType.Elem()
}
if elemType.Kind() == reflect.Ptr {
return errors.New("pointer to pointer is not supported")
}
rows, err := session.queryRows(sqlStr, args...)
if err != nil {
return err
@@ -177,31 +187,8 @@ func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect
return err
}
var newElemFunc func(fields []string) reflect.Value
elemType := containerValue.Type().Elem()
var isPointer bool
if elemType.Kind() == reflect.Ptr {
isPointer = true
elemType = elemType.Elem()
}
if elemType.Kind() == reflect.Ptr {
return errors.New("pointer to pointer is not supported")
}
newElemFunc = func(fields []string) reflect.Value {
switch elemType.Kind() {
case reflect.Slice:
slice := reflect.MakeSlice(elemType, len(fields), len(fields))
x := reflect.New(slice.Type())
x.Elem().Set(slice)
return x
case reflect.Map:
mp := reflect.MakeMap(elemType)
x := reflect.New(mp.Type())
x.Elem().Set(mp)
return x
}
return reflect.New(elemType)
var newElemFunc = func(fields []string) reflect.Value {
return utils.New(elemType, len(fields), len(fields))
}
var containerValueSetFunc func(*reflect.Value, schemas.PK) error
@@ -226,10 +213,15 @@ func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect
containerValueSetFunc = func(newValue *reflect.Value, pk schemas.PK) error {
keyValue := reflect.New(keyType)
err := convertPKToValue(table, keyValue.Interface(), pk)
if err != nil {
return err
cols := table.PKColumns()
if len(cols) == 1 {
if err := convert.AssignValue(keyValue, pk[0]); err != nil {
return err
}
} else {
keyValue.Set(reflect.ValueOf(&pk))
}
if isPointer {
containerValue.SetMapIndex(keyValue.Elem(), newValue.Elem().Addr())
} else {
@@ -241,8 +233,7 @@ func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect
if elemType.Kind() == reflect.Struct {
var newValue = newElemFunc(fields)
dataStruct := utils.ReflectValue(newValue.Interface())
tb, err := session.engine.tagParser.ParseWithCache(dataStruct)
tb, err := session.engine.tagParser.ParseWithCache(newValue)
if err != nil {
return err
}
@@ -266,7 +257,6 @@ func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect
default:
err = rows.Scan(bean)
}
if err != nil {
return err
}
@@ -278,16 +268,6 @@ func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect
return rows.Err()
}
func convertPKToValue(table *schemas.Table, dst interface{}, pk schemas.PK) error {
cols := table.PKColumns()
if len(cols) == 1 {
return convert.Assign(dst, pk[0], nil, nil)
}
dst = pk
return nil
}
func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr interface{}, args ...interface{}) (err error) {
if !session.canCache() ||
utils.IndexNoCase(sqlStr, "having") != -1 ||

View File

@@ -7,6 +7,9 @@ export default function initContextPopups() {
if (!refIssues.length) return;
refIssues.each(function () {
if ($(this).hasClass('ref-external-issue')) {
return;
}
const [index, _issues, repo, owner] = $(this).attr('href').replace(/[#?].*$/, '').split('/').reverse();
const el = document.createElement('div');