mirror of https://github.com/go-gitea/gitea.git
Compare commits
32 Commits
555fa70d9e
...
1d56fa5608
Author | SHA1 | Date |
---|---|---|
silverwind | 1d56fa5608 | |
silverwind | 6247864aaf | |
silverwind | f4a743dff0 | |
silverwind | 7c31f74849 | |
silverwind | 3de13aa93f | |
silverwind | 2bd28a7f73 | |
silverwind | f18ad0efa9 | |
wxiaoguang | 8de2992ffb | |
wxiaoguang | 6d2a307ad8 | |
silverwind | b93c87b6fe | |
Yarden Shoham | 51c28d9683 | |
wxiaoguang | d3cdef88ad | |
Kemal Zebari | dd301cae1c | |
silverwind | 238eb3ff9f | |
silverwind | b2abac5e5f | |
Chongyi Zheng | 4ae6b1a553 | |
wxiaoguang | 7a832ef248 | |
silverwind | 2cdda417ce | |
silverwind | 02be08f233 | |
silverwind | 424d976776 | |
silverwind | 33d4ed973f | |
silverwind | 73937a5204 | |
silverwind | 839700b923 | |
silverwind | 41bd63b6e8 | |
silverwind | 484691be05 | |
silverwind | 0dbb24635a | |
silverwind | 7e40149415 | |
silverwind | 110bc5d7ad | |
silverwind | 086231338d | |
silverwind | f6df3ef0ae | |
silverwind | 34c6e6f4b3 | |
silverwind | 2c9a036ad6 |
|
@ -35,7 +35,7 @@ var microcmdUserChangePassword = &cli.Command{
|
|||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "must-change-password",
|
||||
Usage: "User must change password",
|
||||
Usage: "User must change password (can be disabled by --must-change-password=false)",
|
||||
Value: true,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
@ -48,7 +49,7 @@ var microcmdUserCreate = &cli.Command{
|
|||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "must-change-password",
|
||||
Usage: "Set to false to prevent forcing the user to change their password after initial login",
|
||||
Usage: "User must change password after initial login, defaults to true for all users except the first one (can be disabled by --must-change-password=false)",
|
||||
DisableDefaultText: true,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
|
@ -91,11 +92,16 @@ func runCreateUser(c *cli.Context) error {
|
|||
_, _ = fmt.Fprintf(c.App.ErrWriter, "--name flag is deprecated. Use --username instead.\n")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
ctx := c.Context
|
||||
if !setting.IsInTesting {
|
||||
// FIXME: need to refactor the "installSignals/initDB" related code later
|
||||
// it doesn't make sense to call it in (almost) every command action function
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = installSignals()
|
||||
defer cancel()
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var password string
|
||||
|
@ -123,8 +129,8 @@ func runCreateUser(c *cli.Context) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("IsTableNotEmpty: %w", err)
|
||||
}
|
||||
if !hasUserRecord && isAdmin {
|
||||
// if this is the first admin being created, don't force to change password (keep the old behavior)
|
||||
if !hasUserRecord {
|
||||
// if this is the first one being created, don't force to change password (keep the old behavior)
|
||||
mustChangePassword = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAdminUserCreate(t *testing.T) {
|
||||
app := NewMainApp(AppVersion{})
|
||||
|
||||
reset := func() {
|
||||
assert.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{}))
|
||||
assert.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.EmailAddress{}))
|
||||
}
|
||||
|
||||
type createCheck struct{ IsAdmin, MustChangePassword bool }
|
||||
createUser := func(name, args string) createCheck {
|
||||
assert.NoError(t, app.Run(strings.Fields(fmt.Sprintf("./gitea admin user create --username %s --email %s@gitea.local %s --password foobar", name, name, args))))
|
||||
u := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: name})
|
||||
return createCheck{u.IsAdmin, u.MustChangePassword}
|
||||
}
|
||||
reset()
|
||||
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: false}, createUser("u", ""), "first non-admin user doesn't need to change password")
|
||||
|
||||
reset()
|
||||
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: false}, createUser("u", "--admin"), "first admin user doesn't need to change password")
|
||||
|
||||
reset()
|
||||
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: true}, createUser("u", "--admin --must-change-password"))
|
||||
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: true}, createUser("u2", "--admin"))
|
||||
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: false}, createUser("u3", "--admin --must-change-password=false"))
|
||||
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: true}, createUser("u4", ""))
|
||||
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: false}, createUser("u5", "--must-change-password=false"))
|
||||
}
|
|
@ -112,13 +112,18 @@ func prepareWorkPathAndCustomConf(action cli.ActionFunc) func(ctx *cli.Context)
|
|||
}
|
||||
}
|
||||
|
||||
func NewMainApp(version, versionExtra string) *cli.App {
|
||||
type AppVersion struct {
|
||||
Version string
|
||||
Extra string
|
||||
}
|
||||
|
||||
func NewMainApp(appVer AppVersion) *cli.App {
|
||||
app := cli.NewApp()
|
||||
app.Name = "Gitea"
|
||||
app.HelpName = "gitea"
|
||||
app.Usage = "A painless self-hosted Git service"
|
||||
app.Description = `Gitea program contains "web" and other subcommands. If no subcommand is given, it starts the web server by default. Use "web" subcommand for more web server arguments, use other subcommands for other purposes.`
|
||||
app.Version = version + versionExtra
|
||||
app.Version = appVer.Version + appVer.Extra
|
||||
app.EnableBashCompletion = true
|
||||
|
||||
// these sub-commands need to use config file
|
||||
|
|
|
@ -28,7 +28,7 @@ func makePathOutput(workPath, customPath, customConf string) string {
|
|||
}
|
||||
|
||||
func newTestApp(testCmdAction func(ctx *cli.Context) error) *cli.App {
|
||||
app := NewMainApp("version", "version-extra")
|
||||
app := NewMainApp(AppVersion{})
|
||||
testCmd := &cli.Command{Name: "test-cmd", Action: testCmdAction}
|
||||
prepareSubcommandWithConfig(testCmd, appGlobalFlags())
|
||||
app.Commands = append(app.Commands, testCmd)
|
||||
|
|
2
main.go
2
main.go
|
@ -42,7 +42,7 @@ func main() {
|
|||
log.GetManager().Close()
|
||||
os.Exit(code)
|
||||
}
|
||||
app := cmd.NewMainApp(Version, formatBuiltWith())
|
||||
app := cmd.NewMainApp(cmd.AppVersion{Version: Version, Extra: formatBuiltWith()})
|
||||
_ = cmd.RunMainApp(app, os.Args...) // all errors should have been handled by the RunMainApp
|
||||
log.GetManager().Close()
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
"code.gitea.io/gitea/models/migrations/v1_20"
|
||||
"code.gitea.io/gitea/models/migrations/v1_21"
|
||||
"code.gitea.io/gitea/models/migrations/v1_22"
|
||||
"code.gitea.io/gitea/models/migrations/v1_23"
|
||||
"code.gitea.io/gitea/models/migrations/v1_6"
|
||||
"code.gitea.io/gitea/models/migrations/v1_7"
|
||||
"code.gitea.io/gitea/models/migrations/v1_8"
|
||||
|
@ -574,18 +573,20 @@ var migrations = []Migration{
|
|||
// v293 -> v294
|
||||
NewMigration("Ensure every project has exactly one default column", v1_22.CheckProjectColumnsConsistency),
|
||||
|
||||
// Gitea 1.22.0 ends at 294
|
||||
// Gitea 1.22.0-rc0 ends at 294
|
||||
|
||||
// v294 -> v295
|
||||
NewMigration("Add unique index for project issue table", v1_23.AddUniqueIndexForProjectIssue),
|
||||
NewMigration("Add unique index for project issue table", v1_22.AddUniqueIndexForProjectIssue),
|
||||
// v295 -> v296
|
||||
NewMigration("Add commit status summary table", v1_23.AddCommitStatusSummary),
|
||||
NewMigration("Add commit status summary table", v1_22.AddCommitStatusSummary),
|
||||
// v296 -> v297
|
||||
NewMigration("Add missing field of commit status summary table", v1_23.AddCommitStatusSummary2),
|
||||
NewMigration("Add missing field of commit status summary table", v1_22.AddCommitStatusSummary2),
|
||||
// v297 -> v298
|
||||
NewMigration("Add everyone_access_mode for repo_unit", v1_23.AddRepoUnitEveryoneAccessMode),
|
||||
NewMigration("Add everyone_access_mode for repo_unit", v1_22.AddRepoUnitEveryoneAccessMode),
|
||||
// v298 -> v299
|
||||
NewMigration("Drop wrongly created table o_auth2_application", v1_23.DropWronglyCreatedTable),
|
||||
NewMigration("Drop wrongly created table o_auth2_application", v1_22.DropWronglyCreatedTable),
|
||||
|
||||
// Gitea 1.22.0-rc1 ends at 299
|
||||
}
|
||||
|
||||
// GetCurrentDBVersion returns the current db version
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_23 //nolint
|
||||
package v1_22 //nolint
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_23 //nolint
|
||||
package v1_22 //nolint
|
||||
|
||||
import (
|
||||
"slices"
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_23 //nolint
|
||||
package v1_22 //nolint
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_23 //nolint
|
||||
package v1_22 //nolint
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_23 //nolint
|
||||
package v1_22 //nolint
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/models/perm"
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_23 //nolint
|
||||
package v1_22 //nolint
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
|
@ -6,7 +6,6 @@ package unittest
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -18,6 +17,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/setting/config"
|
||||
"code.gitea.io/gitea/modules/storage"
|
||||
|
@ -46,6 +46,14 @@ func fatalTestError(fmtStr string, args ...any) {
|
|||
|
||||
// InitSettings initializes config provider and load common settings for tests
|
||||
func InitSettings() {
|
||||
setting.IsInTesting = true
|
||||
log.OsExiter = func(code int) {
|
||||
if code != 0 {
|
||||
// non-zero exit code (log.Fatal) shouldn't occur during testing, if it happens, show a full stacktrace for more details
|
||||
panic(fmt.Errorf("non-zero exit code during testing: %d", code))
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
if setting.CustomConf == "" {
|
||||
setting.CustomConf = filepath.Join(setting.CustomPath, "conf/app-unittest-tmp.ini")
|
||||
_ = os.Remove(setting.CustomConf)
|
||||
|
@ -54,7 +62,7 @@ func InitSettings() {
|
|||
setting.LoadCommonSettings()
|
||||
|
||||
if err := setting.PrepareAppDataPath(); err != nil {
|
||||
log.Fatalf("Can not prepare APP_DATA_PATH: %v", err)
|
||||
log.Fatal("Can not prepare APP_DATA_PATH: %v", err)
|
||||
}
|
||||
// register the dummy hash algorithm function used in the test fixtures
|
||||
_ = hash.Register("dummy", hash.NewDummyHasher)
|
||||
|
|
|
@ -57,11 +57,13 @@ func Critical(format string, v ...any) {
|
|||
Log(1, ERROR, format, v...)
|
||||
}
|
||||
|
||||
var OsExiter = os.Exit
|
||||
|
||||
// Fatal records fatal log and exit process
|
||||
func Fatal(format string, v ...any) {
|
||||
Log(1, FATAL, format, v...)
|
||||
GetManager().Close()
|
||||
os.Exit(1)
|
||||
OsExiter(1)
|
||||
}
|
||||
|
||||
func GetLogger(name string) Logger {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
|
@ -4,9 +4,9 @@
|
|||
"node": ">= 18.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@citation-js/core": "0.7.9",
|
||||
"@citation-js/plugin-bibtex": "0.7.9",
|
||||
"@citation-js/plugin-csl": "0.7.9",
|
||||
"@citation-js/core": "0.7.11",
|
||||
"@citation-js/plugin-bibtex": "0.7.11",
|
||||
"@citation-js/plugin-csl": "0.7.11",
|
||||
"@citation-js/plugin-software-formats": "0.6.1",
|
||||
"@github/markdown-toolbar-element": "2.2.3",
|
||||
"@github/relative-time-element": "4.4.0",
|
||||
|
@ -33,17 +33,17 @@
|
|||
"katex": "0.16.10",
|
||||
"license-checker-webpack-plugin": "0.2.1",
|
||||
"mermaid": "10.9.0",
|
||||
"mini-css-extract-plugin": "2.8.1",
|
||||
"mini-css-extract-plugin": "2.9.0",
|
||||
"minimatch": "9.0.4",
|
||||
"monaco-editor": "0.47.0",
|
||||
"monaco-editor": "0.48.0",
|
||||
"monaco-editor-webpack-plugin": "7.1.0",
|
||||
"pdfobject": "2.3.0",
|
||||
"postcss": "8.4.38",
|
||||
"postcss-loader": "8.1.1",
|
||||
"postcss-nesting": "12.1.1",
|
||||
"postcss-nesting": "12.1.2",
|
||||
"pretty-ms": "9.0.0",
|
||||
"sortablejs": "1.15.2",
|
||||
"swagger-ui-dist": "5.15.1",
|
||||
"swagger-ui-dist": "5.17.2",
|
||||
"tailwindcss": "3.4.3",
|
||||
"temporal-polyfill": "0.2.4",
|
||||
"throttle-debounce": "5.0.0",
|
||||
|
@ -53,7 +53,7 @@
|
|||
"tributejs": "5.1.3",
|
||||
"uint8-to-base64": "0.2.0",
|
||||
"vanilla-colorful": "0.7.2",
|
||||
"vue": "3.4.21",
|
||||
"vue": "3.4.25",
|
||||
"vue-bar-graph": "2.0.0",
|
||||
"vue-chartjs": "5.3.1",
|
||||
"vue-loader": "17.4.2",
|
||||
|
@ -66,7 +66,7 @@
|
|||
"@eslint-community/eslint-plugin-eslint-comments": "4.3.0",
|
||||
"@playwright/test": "1.43.1",
|
||||
"@stoplight/spectral-cli": "6.11.1",
|
||||
"@stylistic/eslint-plugin-js": "1.7.0",
|
||||
"@stylistic/eslint-plugin-js": "1.7.2",
|
||||
"@stylistic/stylelint-plugin": "2.1.1",
|
||||
"@vitejs/plugin-vue": "5.0.4",
|
||||
"eslint": "8.57.0",
|
||||
|
@ -81,20 +81,20 @@
|
|||
"eslint-plugin-unicorn": "52.0.0",
|
||||
"eslint-plugin-vitest": "0.4.1",
|
||||
"eslint-plugin-vitest-globals": "1.5.0",
|
||||
"eslint-plugin-vue": "9.24.1",
|
||||
"eslint-plugin-vue": "9.25.0",
|
||||
"eslint-plugin-vue-scoped-css": "2.8.0",
|
||||
"eslint-plugin-wc": "2.1.0",
|
||||
"happy-dom": "14.7.1",
|
||||
"markdownlint-cli": "0.39.0",
|
||||
"postcss-html": "1.6.0",
|
||||
"stylelint": "16.3.1",
|
||||
"stylelint": "16.4.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
||||
"stylelint-declaration-strict-value": "1.10.4",
|
||||
"stylelint-value-no-unknown-custom-properties": "6.0.1",
|
||||
"svgo": "3.2.0",
|
||||
"updates": "16.0.1",
|
||||
"vite-string-plugin": "1.1.5",
|
||||
"vitest": "1.5.0"
|
||||
"vite-string-plugin": "1.2.0",
|
||||
"vitest": "1.5.2"
|
||||
},
|
||||
"browserslist": [
|
||||
"defaults"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
package repo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
@ -372,7 +373,11 @@ func CreatePullReview(ctx *context.APIContext) {
|
|||
// create review and associate all pending review comments
|
||||
review, _, err := pull_service.SubmitReview(ctx, ctx.Doer, ctx.Repo.GitRepo, pr.Issue, reviewType, opts.Body, opts.CommitID, nil)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "SubmitReview", err)
|
||||
if errors.Is(err, pull_service.ErrSubmitReviewOnClosedPR) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "SubmitReview", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -460,7 +465,11 @@ func SubmitPullReview(ctx *context.APIContext) {
|
|||
// create review and associate all pending review comments
|
||||
review, _, err = pull_service.SubmitReview(ctx, ctx.Doer, ctx.Repo.GitRepo, pr.Issue, reviewType, opts.Body, headCommitID, nil)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "SubmitReview", err)
|
||||
if errors.Is(err, pull_service.ErrSubmitReviewOnClosedPR) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "SubmitReview", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -419,11 +419,9 @@ func DiffPreviewPost(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if diff.NumFiles == 0 {
|
||||
ctx.PlainText(http.StatusOK, ctx.Locale.TrString("repo.editor.no_changes_to_show"))
|
||||
return
|
||||
if diff.NumFiles != 0 {
|
||||
ctx.Data["File"] = diff.Files[0]
|
||||
}
|
||||
ctx.Data["File"] = diff.Files[0]
|
||||
|
||||
ctx.HTML(http.StatusOK, tplEditDiffPreview)
|
||||
}
|
||||
|
|
|
@ -264,6 +264,8 @@ func SubmitReview(ctx *context.Context) {
|
|||
if issues_model.IsContentEmptyErr(err) {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.review.content.empty"))
|
||||
ctx.JSONRedirect(fmt.Sprintf("%s/pulls/%d/files", ctx.Repo.RepoLink, issue.Index))
|
||||
} else if errors.Is(err, pull_service.ErrSubmitReviewOnClosedPR) {
|
||||
ctx.Status(http.StatusUnprocessableEntity)
|
||||
} else {
|
||||
ctx.ServerError("SubmitReview", err)
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ func Update(ctx context.Context, pullLimit, pushLimit int) error {
|
|||
}
|
||||
log.Trace("Doing: Update")
|
||||
|
||||
handler := func(idx int, bean any) error {
|
||||
handler := func(bean any) error {
|
||||
var repo *repo_model.Repository
|
||||
var mirrorType SyncType
|
||||
var referenceID int64
|
||||
|
@ -91,7 +91,7 @@ func Update(ctx context.Context, pullLimit, pushLimit int) error {
|
|||
pullMirrorsRequested := 0
|
||||
if pullLimit != 0 {
|
||||
if err := repo_model.MirrorsIterate(ctx, pullLimit, func(idx int, bean any) error {
|
||||
if err := handler(idx, bean); err != nil {
|
||||
if err := handler(bean); err != nil {
|
||||
return err
|
||||
}
|
||||
pullMirrorsRequested++
|
||||
|
@ -105,7 +105,7 @@ func Update(ctx context.Context, pullLimit, pushLimit int) error {
|
|||
pushMirrorsRequested := 0
|
||||
if pushLimit != 0 {
|
||||
if err := repo_model.PushMirrorsIterate(ctx, pushLimit, func(idx int, bean any) error {
|
||||
if err := handler(idx, bean); err != nil {
|
||||
if err := handler(bean); err != nil {
|
||||
return err
|
||||
}
|
||||
pushMirrorsRequested++
|
||||
|
|
|
@ -466,7 +466,7 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool {
|
|||
|
||||
log.Trace("SyncMirrors [repo: %-v]: %d branches updated", m.Repo, len(results))
|
||||
if len(results) > 0 {
|
||||
if ok := checkAndUpdateEmptyRepository(ctx, m, gitRepo, results); !ok {
|
||||
if ok := checkAndUpdateEmptyRepository(ctx, m, results); !ok {
|
||||
log.Error("SyncMirrors [repo: %-v]: checkAndUpdateEmptyRepository: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
|
@ -564,7 +564,7 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func checkAndUpdateEmptyRepository(ctx context.Context, m *repo_model.Mirror, gitRepo *git.Repository, results []*mirrorSyncResult) bool {
|
||||
func checkAndUpdateEmptyRepository(ctx context.Context, m *repo_model.Mirror, results []*mirrorSyncResult) bool {
|
||||
if !m.Repo.IsEmpty {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package pull
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
|
@ -43,6 +44,9 @@ func (err ErrDismissRequestOnClosedPR) Unwrap() error {
|
|||
return util.ErrPermissionDenied
|
||||
}
|
||||
|
||||
// ErrSubmitReviewOnClosedPR represents an error when an user tries to submit an approve or reject review associated to a closed or merged PR.
|
||||
var ErrSubmitReviewOnClosedPR = errors.New("can't submit review for a closed or merged PR")
|
||||
|
||||
// checkInvalidation checks if the line of code comment got changed by another commit.
|
||||
// If the line got changed the comment is going to be invalidated.
|
||||
func checkInvalidation(ctx context.Context, c *issues_model.Comment, doer *user_model.User, repo *git.Repository, branch string) error {
|
||||
|
@ -293,6 +297,10 @@ func SubmitReview(ctx context.Context, doer *user_model.User, gitRepo *git.Repos
|
|||
if reviewType != issues_model.ReviewTypeApprove && reviewType != issues_model.ReviewTypeReject {
|
||||
stale = false
|
||||
} else {
|
||||
if issue.IsClosed {
|
||||
return nil, nil, ErrSubmitReviewOnClosedPR
|
||||
}
|
||||
|
||||
headCommitID, err := gitRepo.GetRefCommitID(pr.GetGitRefName())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
|
@ -191,8 +191,9 @@ export default {
|
|||
'no-invalid-double-slash-comments': true,
|
||||
'no-invalid-position-at-import-rule': [true, {ignoreAtRules: ['tailwind']}],
|
||||
'no-irregular-whitespace': true,
|
||||
'no-unknown-animations': null,
|
||||
'no-unknown-custom-properties': null,
|
||||
'no-unknown-animations': null, // disabled until stylelint supports multi-file linting
|
||||
'no-unknown-custom-media': null, // disabled until stylelint supports multi-file linting
|
||||
'no-unknown-custom-properties': null, // disabled until stylelint supports multi-file linting
|
||||
'number-max-precision': null,
|
||||
'plugin/declaration-block-no-ignored-properties': true,
|
||||
'property-allowed-list': null,
|
||||
|
|
|
@ -76,7 +76,8 @@
|
|||
{{ctx.Locale.Tr "admin.dashboard.system_status"}}
|
||||
</h4>
|
||||
{{/* TODO: make these stats work in multi-server deployments, likely needs per-server stats in DB */}}
|
||||
<div hx-get="{{$.Link}}/system_status" hx-swap="morph:innerHTML" hx-trigger="every 5s" hx-indicator=".divider" class="ui attached table segment">
|
||||
<div class="no-loading-indicator tw-hidden"></div>
|
||||
<div hx-get="{{$.Link}}/system_status" hx-swap="morph:innerHTML" hx-trigger="every 5s" hx-indicator=".no-loading-indicator" class="ui attached table segment">
|
||||
{{template "admin/system_status" .}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div class="ui ten wide column">
|
||||
{{template "org/team/navbar" .}}
|
||||
{{if .IsOrganizationOwner}}
|
||||
<div class="ui attached segment">
|
||||
<div class="ui top attached segment">
|
||||
<form class="ui form ignore-dirty tw-flex tw-flex-wrap tw-gap-2" action="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/add" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<input type="hidden" name="uid" value="{{.SignedUser.ID}}">
|
||||
|
@ -21,7 +21,7 @@
|
|||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="ui attached segment">
|
||||
<div class="ui{{if not .IsOrganizationOwner}} top{{end}} attached segment">
|
||||
<div class="flex-list">
|
||||
{{range .Team.Members}}
|
||||
<div class="flex-item tw-items-center">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="ui top attached tabular menu org-team-navbar">
|
||||
<div class="ui compact small menu small-menu-items org-team-navbar">
|
||||
<a class="item{{if .PageIsOrgTeamMembers}} active{{end}}" href="{{.OrgLink}}/teams/{{.Team.LowerName | PathEscape}}">{{svg "octicon-person"}} <strong>{{.Team.NumMembers}}</strong> {{ctx.Locale.Tr "org.lower_members"}}</a>
|
||||
<a class="item{{if .PageIsOrgTeamRepos}} active{{end}}" href="{{.OrgLink}}/teams/{{.Team.LowerName | PathEscape}}/repositories">{{svg "octicon-repo"}} <strong>{{.Team.NumRepos}}</strong> {{ctx.Locale.Tr "org.lower_repositories"}}</a>
|
||||
</div>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="ui attached segment">
|
||||
<div class="ui{{if not $canAddRemove}} top{{end}} attached segment">
|
||||
<div class="flex-list">
|
||||
{{range .Team.Repos}}
|
||||
<div class="flex-item tw-items-center">
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
{{end}}
|
||||
{{template "repo/commit_load_branches_and_tags" .}}
|
||||
</div>
|
||||
<div class="ui attached segment tw-flex tw-items-center tw-justify-between tw-py-1 commit-header-row tw-flex-wrap {{$class}}">
|
||||
<div class="ui{{if not .Commit.Signature}} bottom{{end}} attached segment tw-flex tw-items-center tw-justify-between tw-py-1 commit-header-row tw-flex-wrap {{$class}}">
|
||||
<div class="tw-flex tw-items-center author">
|
||||
{{if .Author}}
|
||||
{{ctx.AvatarUtils.Avatar .Author 28 "tw-mr-2"}}
|
||||
|
|
|
@ -235,7 +235,7 @@
|
|||
|
||||
{{if and (not $.Repository.IsArchived) (not .DiffNotAvailable)}}
|
||||
<template id="issue-comment-editor-template">
|
||||
<div class="ui comment form">
|
||||
<div class="ui form comment">
|
||||
{{template "shared/combomarkdowneditor" (dict
|
||||
"MarkdownPreviewUrl" (print $.Repository.Link "/markup")
|
||||
"MarkdownPreviewContext" $.RepoLink
|
||||
|
@ -249,7 +249,7 @@
|
|||
{{end}}
|
||||
<div class="text right edit buttons">
|
||||
<button class="ui cancel button">{{ctx.Locale.Tr "repo.issues.cancel"}}</button>
|
||||
<button class="ui primary save button">{{ctx.Locale.Tr "repo.issues.save"}}</button>
|
||||
<button class="ui primary button">{{ctx.Locale.Tr "repo.issues.save"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -30,20 +30,24 @@
|
|||
{{end}}
|
||||
<div class="divider"></div>
|
||||
{{$showSelfTooltip := (and $.IsSigned ($.Issue.IsPoster $.SignedUser.ID))}}
|
||||
{{if $showSelfTooltip}}
|
||||
<span class="tw-inline-block" data-tooltip-content="{{ctx.Locale.Tr "repo.diff.review.self_approve"}}">
|
||||
<button type="submit" name="type" value="approve" disabled class="ui submit primary tiny button btn-submit">{{ctx.Locale.Tr "repo.diff.review.approve"}}</button>
|
||||
</span>
|
||||
{{else}}
|
||||
<button type="submit" name="type" value="approve" class="ui submit primary tiny button btn-submit">{{ctx.Locale.Tr "repo.diff.review.approve"}}</button>
|
||||
{{if not $.Issue.IsClosed}}
|
||||
{{if $showSelfTooltip}}
|
||||
<span class="tw-inline-block" data-tooltip-content="{{ctx.Locale.Tr "repo.diff.review.self_approve"}}">
|
||||
<button type="submit" name="type" value="approve" disabled class="ui submit primary tiny button btn-submit">{{ctx.Locale.Tr "repo.diff.review.approve"}}</button>
|
||||
</span>
|
||||
{{else}}
|
||||
<button type="submit" name="type" value="approve" class="ui submit primary tiny button btn-submit">{{ctx.Locale.Tr "repo.diff.review.approve"}}</button>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<button type="submit" name="type" value="comment" class="ui submit tiny basic button btn-submit">{{ctx.Locale.Tr "repo.diff.review.comment"}}</button>
|
||||
{{if $showSelfTooltip}}
|
||||
<span class="tw-inline-block" data-tooltip-content="{{ctx.Locale.Tr "repo.diff.review.self_reject"}}">
|
||||
<button type="submit" name="type" value="reject" disabled class="ui submit red tiny button btn-submit">{{ctx.Locale.Tr "repo.diff.review.reject"}}</button>
|
||||
</span>
|
||||
{{else}}
|
||||
<button type="submit" name="type" value="reject" class="ui submit red tiny button btn-submit">{{ctx.Locale.Tr "repo.diff.review.reject"}}</button>
|
||||
{{if not $.Issue.IsClosed}}
|
||||
{{if $showSelfTooltip}}
|
||||
<span class="tw-inline-block" data-tooltip-content="{{ctx.Locale.Tr "repo.diff.review.self_reject"}}">
|
||||
<button type="submit" name="type" value="reject" disabled class="ui submit red tiny button btn-submit">{{ctx.Locale.Tr "repo.diff.review.reject"}}</button>
|
||||
</span>
|
||||
{{else}}
|
||||
<button type="submit" name="type" value="reject" class="ui submit red tiny button btn-submit">{{ctx.Locale.Tr "repo.diff.review.reject"}}</button>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
{{if .File}}
|
||||
<div class="diff-file-box">
|
||||
<div class="ui attached table segment">
|
||||
<div class="file-body file-code code-diff code-diff-unified unicode-escaped">
|
||||
|
@ -9,3 +10,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="tw-p-6 tw-text-center">
|
||||
{{ctx.Locale.Tr "repo.editor.no_changes_to_show"}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
|
@ -26,14 +26,14 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff">
|
||||
<div class="ui compact small menu small-menu-items repo-editor-menu">
|
||||
<a class="active item" data-tab="write">{{svg "octicon-code"}} {{if .IsNewFile}}{{ctx.Locale.Tr "repo.editor.new_file"}}{{else}}{{ctx.Locale.Tr "repo.editor.edit_file"}}{{end}}</a>
|
||||
<a class="item" data-tab="preview" data-url="{{.Repository.Link}}/markup" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL}}" data-markup-mode="file">{{svg "octicon-eye"}} {{ctx.Locale.Tr "preview"}}</a>
|
||||
{{if not .IsNewFile}}
|
||||
<a class="item" data-tab="diff" hx-params="context,content" hx-vals='{"context":"{{.BranchLink}}"}' hx-include="#edit_area" hx-swap="innerHTML" hx-target=".tab[data-tab='diff']" hx-indicator=".tab[data-tab='diff']" hx-post="{{.RepoLink}}/_preview/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">{{svg "octicon-diff"}} {{ctx.Locale.Tr "repo.editor.preview_changes"}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui bottom attached active tab segment" data-tab="write">
|
||||
<div class="ui active tab segment tw-rounded" data-tab="write">
|
||||
<textarea id="edit_area" name="content" class="tw-hidden" data-id="repo-{{.Repository.Name}}-{{.TreePath}}"
|
||||
data-url="{{.Repository.Link}}/markup"
|
||||
data-context="{{.RepoLink}}"
|
||||
|
@ -41,10 +41,10 @@
|
|||
data-line-wrap-extensions="{{.LineWrapExtensions}}">{{.FileContent}}</textarea>
|
||||
<div class="editor-loading is-loading"></div>
|
||||
</div>
|
||||
<div class="ui bottom attached tab segment markup" data-tab="preview">
|
||||
<div class="ui tab segment markup tw-rounded" data-tab="preview">
|
||||
{{ctx.Locale.Tr "loading"}}
|
||||
</div>
|
||||
<div class="ui bottom attached tab segment diff edit-diff" data-tab="diff">
|
||||
<div class="ui tab segment diff edit-diff" data-tab="diff">
|
||||
<div class="tw-p-16"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui top attached tabular menu" data-write="write">
|
||||
<div class="ui compact small menu small-menu-items repo-editor-menu">
|
||||
<a class="active item" data-tab="write">{{svg "octicon-code" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.editor.new_patch"}}</a>
|
||||
</div>
|
||||
<div class="ui bottom attached active tab segment" data-tab="write">
|
||||
<div class="ui active tab segment tw-rounded tw-p-0" data-tab="write">
|
||||
<textarea id="edit_area" name="content" class="tw-hidden" data-id="repo-{{.Repository.Name}}-patch"
|
||||
data-context="{{.RepoLink}}"
|
||||
data-line-wrap-extensions="{{.LineWrapExtensions}}">
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
{{with .Issue}}
|
||||
{{if eq $.Page.Project.CardType 1}}{{/* Images and Text*/}}
|
||||
{{$attachments := index $.Page.issuesAttachmentMap .ID}}
|
||||
{{if $attachments}}
|
||||
<div class="card-attachment-images">
|
||||
{{range (index $.Page.issuesAttachmentMap .ID)}}
|
||||
{{range $attachments}}
|
||||
<img src="{{.DownloadURL}}" alt="{{.Name}}" />
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<div class="content tw-p-0 tw-w-full">
|
||||
<div class="tw-flex tw-items-start">
|
||||
<div class="content tw-w-full">
|
||||
<div class="tw-flex tw-items-start tw-gap-[5px]">
|
||||
<div class="issue-card-icon">
|
||||
{{template "shared/issueicon" .}}
|
||||
</div>
|
||||
|
@ -18,7 +21,7 @@
|
|||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="meta tw-my-1">
|
||||
<div class="meta">
|
||||
<span class="text light grey muted-links">
|
||||
{{if not $.Page.Repository}}{{.Repo.FullName}}{{end}}#{{.Index}}
|
||||
{{$timeStr := TimeSinceUnix .GetLastEventTimestamp ctx.Locale}}
|
||||
|
@ -59,13 +62,15 @@
|
|||
</div>
|
||||
|
||||
{{if or .Labels .Assignees}}
|
||||
<div class="extra content labels-list tw-p-0 tw-pt-1">
|
||||
{{range .Labels}}
|
||||
<a target="_blank" href="{{$.Issue.Repo.Link}}/issues?labels={{.ID}}">{{RenderLabel ctx ctx.Locale .}}</a>
|
||||
{{end}}
|
||||
<div class="right floated">
|
||||
<div class="tw-flex tw-justify-between">
|
||||
<div class="labels-list tw-flex-1">
|
||||
{{range .Labels}}
|
||||
<a target="_blank" href="{{$.Issue.Repo.Link}}/issues?labels={{.ID}}">{{RenderLabel ctx ctx.Locale .}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-wrap tw-content-start tw-gap-1">
|
||||
{{range .Assignees}}
|
||||
<a target="_blank" href="{{.HomeLink}}" data-tooltip-content="{{ctx.Locale.Tr "repo.projects.column.assigned_to"}} {{.Name}}">{{ctx.AvatarUtils.Avatar . 28 "mini tw-mr-2"}}</a>
|
||||
<a target="_blank" href="{{.HomeLink}}" data-tooltip-content="{{ctx.Locale.Tr "repo.projects.column.assigned_to"}} {{.Name}}">{{ctx.AvatarUtils.Avatar . 28}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,24 +1,21 @@
|
|||
<div class="ui centered grid">
|
||||
<div class="twelve wide computer column">
|
||||
<div class="ui attached left aligned segment">
|
||||
<p>{{ctx.Locale.Tr "repo.issues.label_templates.info"}}</p>
|
||||
<br>
|
||||
<form class="ui form center" action="{{.Link}}/initialize" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="field">
|
||||
<div class="ui selection dropdown">
|
||||
<input type="hidden" name="template_name" value="Default">
|
||||
<div class="default text">{{ctx.Locale.Tr "repo.issues.label_templates.helper"}}</div>
|
||||
<div class="menu">
|
||||
{{range .LabelTemplateFiles}}
|
||||
<div class="item" data-value="{{.DisplayName}}">{{.DisplayName}}<br><i>({{.Description}})</i></div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{svg "octicon-triangle-down" 18 "dropdown icon"}}
|
||||
<p>{{ctx.Locale.Tr "repo.issues.label_templates.info"}}</p>
|
||||
<form class="ui form center" action="{{.Link}}/initialize" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="field">
|
||||
<div class="ui selection dropdown">
|
||||
<input type="hidden" name="template_name" value="Default">
|
||||
<div class="default text">{{ctx.Locale.Tr "repo.issues.label_templates.helper"}}</div>
|
||||
<div class="menu">
|
||||
{{range .LabelTemplateFiles}}
|
||||
<div class="item" data-value="{{.DisplayName}}">{{.DisplayName}}<br><i>({{.Description}})</i></div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{svg "octicon-triangle-down" 18 "dropdown icon"}}
|
||||
</div>
|
||||
<button type="submit" class="ui primary button">{{ctx.Locale.Tr "repo.issues.label_templates.use"}}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="ui primary button">{{ctx.Locale.Tr "repo.issues.label_templates.use"}}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -146,7 +146,7 @@
|
|||
</div>
|
||||
|
||||
<template id="issue-comment-editor-template">
|
||||
<div class="ui comment form">
|
||||
<div class="ui form comment">
|
||||
<div class="field">
|
||||
{{template "shared/combomarkdowneditor" (dict
|
||||
"MarkdownPreviewUrl" (print .Repository.Link "/markup")
|
||||
|
@ -164,8 +164,8 @@
|
|||
|
||||
<div class="field">
|
||||
<div class="text right edit">
|
||||
<button class="ui basic cancel button">{{ctx.Locale.Tr "repo.issues.cancel"}}</button>
|
||||
<button class="ui primary save button">{{ctx.Locale.Tr "repo.issues.save"}}</button>
|
||||
<button class="ui cancel button">{{ctx.Locale.Tr "repo.issues.cancel"}}</button>
|
||||
<button class="ui primary button">{{ctx.Locale.Tr "repo.issues.save"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<span class="ui small label">{{if .NumFiles}}{{.NumFiles}}{{else}}-{{end}}</span>
|
||||
</a>
|
||||
{{if or .Diff.TotalAddition .Diff.TotalDeletion}}
|
||||
<span class="item tw-ml-auto tw-pr-0 tw-font-bold tw-flex tw-items-center tw-gap-2">
|
||||
<span class="tw-ml-auto tw-pl-3 tw-whitespace-nowrap tw-pr-0 tw-font-bold tw-flex tw-items-center tw-gap-2">
|
||||
<span><span class="text green">{{if .Diff.TotalAddition}}+{{.Diff.TotalAddition}}{{end}}</span> <span class="text red">{{if .Diff.TotalDeletion}}-{{.Diff.TotalDeletion}}{{end}}</span></span>
|
||||
<span class="diff-stats-bar">
|
||||
<div class="diff-stats-add-bar" style="width: {{Eval 100 "*" .Diff.TotalAddition "/" "(" .Diff.TotalAddition "+" .Diff.TotalDeletion "+" 0.0 ")"}}%"></div>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<div class="ui container">
|
||||
{{template "base/alert" .}}
|
||||
{{template "repo/release_tag_header" .}}
|
||||
{{if .Releases}}
|
||||
<h4 class="ui top attached header">
|
||||
<div class="five wide column tw-flex tw-items-center">
|
||||
{{svg "octicon-tag" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.tags"}}
|
||||
|
@ -57,6 +58,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{template "base/paginate" .}}
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{template "base/head" .}}
|
||||
<div role="main" aria-label="{{.Title}}" class="page-content user notification">
|
||||
<div class="ui container">
|
||||
<div class="ui top attached tabular menu">
|
||||
<div class="ui compact small menu small-menu-items">
|
||||
<a href="{{AppSubUrl}}/notifications/subscriptions" class="{{if eq .Status 1}}active {{end}}item">
|
||||
{{ctx.Locale.Tr "notification.subscriptions"}}
|
||||
</a>
|
||||
|
@ -9,7 +9,7 @@
|
|||
{{ctx.Locale.Tr "notification.watching"}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="ui bottom attached active tab segment">
|
||||
<div class="ui top attached segment">
|
||||
{{if eq .Status 1}}
|
||||
<div class="tw-flex tw-justify-between">
|
||||
<div class="tw-flex">
|
||||
|
|
|
@ -111,7 +111,7 @@
|
|||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui attached bottom segment">
|
||||
<div class="ui bottom attached segment">
|
||||
<form class="ui form" action="{{AppSubUrl}}/user/settings/account/email" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="required field {{if .Err_Email}}error{{end}}">
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui attached bottom segment">
|
||||
<div class="ui bottom attached segment">
|
||||
<h5 class="ui top header">
|
||||
{{ctx.Locale.Tr "settings.generate_new_token"}}
|
||||
</h5>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui attached bottom segment">
|
||||
<div class="ui bottom attached segment">
|
||||
<form class="ui form ignore-dirty" action="{{.FormActionPath}}" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="field {{if .Err_AppName}}error{{end}}">
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui attached bottom segment">
|
||||
<div class="ui bottom attached segment">
|
||||
<h5 class="ui top header">
|
||||
{{ctx.Locale.Tr "settings.create_oauth2_application"}}
|
||||
</h5>
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui attached bottom segment">
|
||||
<div class="ui bottom attached segment">
|
||||
<form class="ui form" action="{{AppSubUrl}}/user/settings/security/openid" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="required field {{if .Err_OpenID}}error{{end}}">
|
||||
|
|
|
@ -5,12 +5,15 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
|
@ -176,3 +179,82 @@ func TestPullView_CodeOwner(t *testing.T) {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||
user1Session := loginUser(t, "user1")
|
||||
user2Session := loginUser(t, "user2")
|
||||
|
||||
// Have user1 create a fork of repo1.
|
||||
testRepoFork(t, user1Session, "user2", "repo1", "user1", "repo1")
|
||||
|
||||
t.Run("Submit approve/reject review on merged PR", func(t *testing.T) {
|
||||
// Create a merged PR (made by user1) in the upstream repo1.
|
||||
testEditFile(t, user1Session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||
resp := testPullCreate(t, user1Session, "user1", "repo1", false, "master", "master", "This is a pull title")
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
testPullMerge(t, user1Session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false)
|
||||
|
||||
// Grab the CSRF token.
|
||||
req := NewRequest(t, "GET", path.Join(elem[1], elem[2], "pulls", elem[4]))
|
||||
resp = user2Session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
// Submit an approve review on the PR.
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "approve", http.StatusUnprocessableEntity)
|
||||
|
||||
// Submit a reject review on the PR.
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "reject", http.StatusUnprocessableEntity)
|
||||
})
|
||||
|
||||
t.Run("Submit approve/reject review on closed PR", func(t *testing.T) {
|
||||
// Created a closed PR (made by user1) in the upstream repo1.
|
||||
testEditFileToNewBranch(t, user1Session, "user1", "repo1", "master", "a-test-branch", "README.md", "Hello, World (Editied...again)\n")
|
||||
resp := testPullCreate(t, user1Session, "user1", "repo1", false, "master", "a-test-branch", "This is a pull title")
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
testIssueClose(t, user1Session, elem[1], elem[2], elem[4])
|
||||
|
||||
// Grab the CSRF token.
|
||||
req := NewRequest(t, "GET", path.Join(elem[1], elem[2], "pulls", elem[4]))
|
||||
resp = user2Session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
// Submit an approve review on the PR.
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "approve", http.StatusUnprocessableEntity)
|
||||
|
||||
// Submit a reject review on the PR.
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "reject", http.StatusUnprocessableEntity)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func testSubmitReview(t *testing.T, session *TestSession, csrf, owner, repo, pullNumber, reviewType string, expectedSubmitStatus int) *httptest.ResponseRecorder {
|
||||
options := map[string]string{
|
||||
"_csrf": csrf,
|
||||
"commit_id": "",
|
||||
"content": "test",
|
||||
"type": reviewType,
|
||||
}
|
||||
|
||||
submitURL := path.Join(owner, repo, "pulls", pullNumber, "files", "reviews", "submit")
|
||||
req := NewRequestWithValues(t, "POST", submitURL, options)
|
||||
return session.MakeRequest(t, req, expectedSubmitStatus)
|
||||
}
|
||||
|
||||
func testIssueClose(t *testing.T, session *TestSession, owner, repo, issueNumber string) *httptest.ResponseRecorder {
|
||||
req := NewRequest(t, "GET", path.Join(owner, repo, "pulls", issueNumber))
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
closeURL := path.Join(owner, repo, "issues", issueNumber, "comments")
|
||||
|
||||
options := map[string]string{
|
||||
"_csrf": htmlDoc.GetCSRF(),
|
||||
"status": "close",
|
||||
}
|
||||
|
||||
req = NewRequestWithValues(t, "POST", closeURL, options)
|
||||
return session.MakeRequest(t, req, http.StatusOK)
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@ func InitTest(requireGitea bool) {
|
|||
// TODO: Speedup tests that rely on the event source ticker, confirm whether there is any bug or failure.
|
||||
// setting.UI.Notification.EventSourceUpdateTime = time.Second
|
||||
|
||||
setting.IsInTesting = true
|
||||
setting.AppWorkPath = giteaRoot
|
||||
setting.CustomPath = filepath.Join(setting.AppWorkPath, "custom")
|
||||
if requireGitea {
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.monaco-editor,
|
||||
.monaco-editor .overflow-guard {
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
/* these seem unthemeable */
|
||||
.monaco-scrollable-element > .scrollbar > .slider {
|
||||
background: var(--color-primary) !important;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
border: 1px solid var(--color-secondary);
|
||||
box-shadow: none;
|
||||
word-wrap: break-word;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.ui.card {
|
||||
|
|
|
@ -799,3 +799,23 @@
|
|||
.ui.segment .ui.tabular.menu .active.item:hover {
|
||||
background: var(--color-box-body);
|
||||
}
|
||||
|
||||
.small-menu-items {
|
||||
min-height: 35.4px !important; /* match .small.button in height */
|
||||
background: none !important; /* fomantic sets a color here which does not play well with active transparent color on the item, so unset and set the colors on the item */
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.small-menu-items .item {
|
||||
background: var(--color-menu) !important;
|
||||
padding-top: 6px !important;
|
||||
padding-bottom: 6px !important;
|
||||
}
|
||||
|
||||
.small-menu-items .item:hover {
|
||||
background: var(--color-hover) !important;
|
||||
}
|
||||
|
||||
.small-menu-items .item.active {
|
||||
background: var(--color-active) !important;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ These inconsistent layouts should be refactored to simple ones.
|
|||
.ui.modal form > .content {
|
||||
padding: 1.5em;
|
||||
background: var(--color-body);
|
||||
border-radius: 0 0 var(--border-radius) var(--border-radius);
|
||||
}
|
||||
|
||||
.ui.modal > .actions,
|
||||
|
@ -63,6 +64,7 @@ These inconsistent layouts should be refactored to simple ones.
|
|||
border-color: var(--color-secondary);
|
||||
padding: 1rem;
|
||||
text-align: right;
|
||||
border-radius: 0 0 var(--border-radius) var(--border-radius);
|
||||
}
|
||||
|
||||
.ui.modal .content > .actions {
|
||||
|
|
|
@ -152,7 +152,9 @@
|
|||
}
|
||||
|
||||
.ui.attached.segment:has(+ .ui[class*="top attached"].header),
|
||||
.ui.attached.segment:last-child {
|
||||
.ui.attached.segment:last-child,
|
||||
.ui.segment:has(+ .ui.segment:not(.attached)),
|
||||
.ui.attached.segment:has(+ .ui.modal) {
|
||||
border-radius: 0 0 0.28571429rem 0.28571429rem;
|
||||
}
|
||||
|
||||
|
@ -166,6 +168,10 @@
|
|||
.ui.segment[class*="top attached"]:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ui[class*="top attached"].segment:last-child {
|
||||
border-top-left-radius: 0.28571429rem;
|
||||
border-top-right-radius: 0.28571429rem;
|
||||
}
|
||||
|
||||
.ui.segment[class*="bottom attached"] {
|
||||
bottom: 0;
|
||||
|
|
|
@ -1586,6 +1586,7 @@ td .commit-summary {
|
|||
|
||||
.repository .diff-file-box .file-body.file-code {
|
||||
background: var(--color-code-bg);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.repository .diff-file-box .file-body.file-code .lines-num {
|
||||
|
@ -2382,6 +2383,22 @@ tbody.commit-list {
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* fix bottom border radius on diff files */
|
||||
.diff-file-body tr.tag-code:last-child {
|
||||
background: none;
|
||||
}
|
||||
.diff-file-body tr.tag-code:last-child > td {
|
||||
background: var(--color-box-body-highlight);
|
||||
}
|
||||
.diff-file-body tr.tag-code:last-child td:first-child,
|
||||
.diff-file-body tr.tag-code:last-child td:first-child * {
|
||||
border-bottom-left-radius: 3px;
|
||||
}
|
||||
.diff-file-body tr.tag-code:last-child td:last-child,
|
||||
.diff-file-body tr.tag-code:last-child td:last-child * {
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
|
||||
.resolved-placeholder {
|
||||
font-weight: var(--font-weight-normal) !important;
|
||||
border: 1px solid var(--color-secondary) !important;
|
||||
|
@ -2491,6 +2508,7 @@ tbody.commit-list {
|
|||
|
||||
.diff-file-header {
|
||||
padding: 5px 8px !important;
|
||||
box-shadow: 0 -1px 0 1px var(--color-body); /* prevent borders being visible behind top corners when sticky and scrolled */
|
||||
}
|
||||
|
||||
.diff-file-box[data-folded="true"] .diff-file-body {
|
||||
|
@ -2520,7 +2538,7 @@ tbody.commit-list {
|
|||
display: inline-block;
|
||||
background-color: var(--color-red);
|
||||
height: 12px;
|
||||
width: 40px;
|
||||
width: 44px;
|
||||
}
|
||||
|
||||
.diff-stats-bar .diff-stats-add-bar {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
.issue-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
align-items: start;
|
||||
border-radius: var(--border-radius);
|
||||
padding: 8px 10px;
|
||||
|
@ -17,7 +18,6 @@
|
|||
.issue-card-title {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.issue-card.sortable-chosen .issue-card-title {
|
||||
|
|
|
@ -25,25 +25,6 @@
|
|||
flex: 1;
|
||||
}
|
||||
|
||||
.small-menu-items {
|
||||
min-height: 35.4px !important; /* match .small.button in height */
|
||||
background: none !important; /* fomantic sets a color here which does not play well with active transparent color on the item, so unset and set the colors on the item */
|
||||
}
|
||||
|
||||
.small-menu-items .item {
|
||||
background: var(--color-menu) !important;
|
||||
padding-top: 6px !important;
|
||||
padding-bottom: 6px !important;
|
||||
}
|
||||
|
||||
.small-menu-items .item:hover {
|
||||
background: var(--color-hover) !important;
|
||||
}
|
||||
|
||||
.small-menu-items .item.active {
|
||||
background: var(--color-active) !important;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.list-header-search {
|
||||
order: 0;
|
||||
|
|
|
@ -6,18 +6,10 @@
|
|||
// This file must be imported before any lazy-loading is being attempted.
|
||||
__webpack_public_path__ = `${window.config?.assetUrlPrefix ?? '/assets'}/`;
|
||||
|
||||
const filteredErrors = new Set([
|
||||
'getModifierState is not a function', // https://github.com/microsoft/monaco-editor/issues/4325
|
||||
]);
|
||||
|
||||
export function showGlobalErrorMessage(msg) {
|
||||
const pageContent = document.querySelector('.page-content');
|
||||
if (!pageContent) return;
|
||||
|
||||
for (const filteredError of filteredErrors) {
|
||||
if (msg.includes(filteredError)) return;
|
||||
}
|
||||
|
||||
// compact the message to a data attribute to avoid too many duplicated messages
|
||||
const msgCompact = msg.replace(/\W/g, '').trim();
|
||||
let msgDiv = pageContent.querySelector(`.js-global-error[data-global-error-msg-compact="${msgCompact}"]`);
|
||||
|
|
|
@ -98,6 +98,7 @@ export async function createMonaco(textarea, filename, editorOpts) {
|
|||
'input.foreground': getColor('--color-input-text'),
|
||||
'scrollbar.shadow': getColor('--color-shadow'),
|
||||
'progressBar.background': getColor('--color-primary'),
|
||||
'focusBorder': '#0000', // prevent blue border
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export function handleGlobalEnterQuickSubmit(target) {
|
||||
const form = target.closest('form');
|
||||
let form = target.closest('form');
|
||||
if (form) {
|
||||
if (!form.checkValidity()) {
|
||||
form.reportValidity();
|
||||
|
@ -9,5 +9,10 @@ export function handleGlobalEnterQuickSubmit(target) {
|
|||
// here use the event to trigger the submit event (instead of calling `submit()` method directly)
|
||||
// otherwise the `areYouSure` handler won't be executed, then there will be an annoying "confirm to leave" dialog
|
||||
form.dispatchEvent(new SubmitEvent('submit', {bubbles: true, cancelable: true}));
|
||||
return;
|
||||
}
|
||||
form = target.closest('.ui.form');
|
||||
if (form) {
|
||||
form.querySelector('.ui.primary.button')?.click();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ import {attachRefIssueContextPopup} from './contextpopup.js';
|
|||
import {POST} from '../modules/fetch.js';
|
||||
|
||||
function initEditPreviewTab($form) {
|
||||
const $tabMenu = $form.find('.tabular.menu');
|
||||
const $tabMenu = $form.find('.repo-editor-menu');
|
||||
$tabMenu.find('.item').tab();
|
||||
const $previewTab = $tabMenu.find(`.item[data-tab="${$tabMenu.data('preview')}"]`);
|
||||
const $previewTab = $tabMenu.find('a[data-tab="preview"]');
|
||||
if ($previewTab.length) {
|
||||
$previewTab.on('click', async function () {
|
||||
const $this = $(this);
|
||||
|
@ -24,13 +24,15 @@ function initEditPreviewTab($form) {
|
|||
const formData = new FormData();
|
||||
formData.append('mode', mode);
|
||||
formData.append('context', context);
|
||||
formData.append('text', $form.find(`.tab[data-tab="${$tabMenu.data('write')}"] textarea`).val());
|
||||
formData.append('text', $form.find('.tab[data-tab="write"] textarea').val());
|
||||
formData.append('file_path', $treePathEl.val());
|
||||
try {
|
||||
const response = await POST($this.data('url'), {data: formData});
|
||||
const data = await response.text();
|
||||
const $previewPanel = $form.find(`.tab[data-tab="${$tabMenu.data('preview')}"]`);
|
||||
renderPreviewPanelContent($previewPanel, data);
|
||||
const $previewPanel = $form.find('.tab[data-tab="preview"]');
|
||||
if ($previewPanel.length) {
|
||||
renderPreviewPanelContent($previewPanel, data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
|
@ -175,10 +177,10 @@ export function initRepoEditor() {
|
|||
})();
|
||||
}
|
||||
|
||||
export function renderPreviewPanelContent($panelPreviewer, data) {
|
||||
$panelPreviewer.html(data);
|
||||
export function renderPreviewPanelContent($previewPanel, data) {
|
||||
$previewPanel.html(data);
|
||||
initMarkupContent();
|
||||
|
||||
const $refIssues = $panelPreviewer.find('p .ref-issue');
|
||||
const $refIssues = $previewPanel.find('p .ref-issue');
|
||||
attachRefIssueContextPopup($refIssues);
|
||||
}
|
||||
|
|
|
@ -162,8 +162,8 @@ async function onEditContent(event) {
|
|||
editContentZone.innerHTML = document.getElementById('issue-comment-editor-template').innerHTML;
|
||||
comboMarkdownEditor = await initComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor'));
|
||||
comboMarkdownEditor.attachedDropzoneInst = await setupDropzone(editContentZone.querySelector('.dropzone'));
|
||||
editContentZone.querySelector('.cancel.button').addEventListener('click', cancelAndReset);
|
||||
editContentZone.querySelector('.save.button').addEventListener('click', saveAndRefresh);
|
||||
editContentZone.querySelector('.ui.cancel.button').addEventListener('click', cancelAndReset);
|
||||
editContentZone.querySelector('.ui.primary.button').addEventListener('click', saveAndRefresh);
|
||||
}
|
||||
|
||||
// Show write/preview tab and copy raw content as needed
|
||||
|
|
Loading…
Reference in New Issue