mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-08 18:04:14 +01:00
Merge pull request '[gitea] week 16 cherry pick' (#3212) from algernon/forgejo:wcp/week-16 into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3212 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
This commit is contained in:
commit
e4fa133c47
86 changed files with 545 additions and 459 deletions
|
@ -94,6 +94,9 @@ cpu.out
|
|||
/.air
|
||||
/.go-licenses
|
||||
|
||||
# Files and folders that were previously generated
|
||||
/public/assets/img/webpack
|
||||
|
||||
# Snapcraft
|
||||
snap/.snapcraft/
|
||||
parts/
|
||||
|
|
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -1,5 +1,6 @@
|
|||
* text=auto eol=lf
|
||||
*.tmpl linguist-language=go-html-template
|
||||
*.pb.go linguist-generated
|
||||
/assets/*.json linguist-generated
|
||||
/public/assets/img/svg/*.svg linguist-generated
|
||||
/templates/swagger/v1_json.tmpl linguist-generated
|
||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -101,6 +101,9 @@ cpu.out
|
|||
/.go-licenses
|
||||
/.cur-deadcode-out
|
||||
|
||||
# Files and folders that were previously generated
|
||||
/public/assets/img/webpack
|
||||
|
||||
# Snapcraft
|
||||
/gitea_a*.txt
|
||||
snap/.snapcraft/
|
||||
|
|
2
Makefile
2
Makefile
|
@ -312,7 +312,7 @@ clean:
|
|||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
||||
@GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
||||
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
|
||||
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
|
||||
@# whitespace before it
|
||||
|
|
|
@ -69,6 +69,7 @@ func newFileCollector(fileFilter string, batchSize int) (*fileCollector, error)
|
|||
co.includePatterns = append(co.includePatterns, regexp.MustCompile(`.*\.go$`))
|
||||
|
||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`.*\bbindata\.go$`))
|
||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`\.pb\.go$`))
|
||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/gitea-repositories-meta`))
|
||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/integration/migration-test`))
|
||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`modules/git/tests`))
|
||||
|
@ -203,17 +204,6 @@ Example:
|
|||
`, "file-batch-exec")
|
||||
}
|
||||
|
||||
func getGoVersion() string {
|
||||
goModFile, err := os.ReadFile("go.mod")
|
||||
if err != nil {
|
||||
log.Fatalf(`Faild to read "go.mod": %v`, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
goModVersionRegex := regexp.MustCompile(`go \d+\.\d+`)
|
||||
goModVersionLine := goModVersionRegex.Find(goModFile)
|
||||
return string(goModVersionLine[3:])
|
||||
}
|
||||
|
||||
func newFileCollectorFromMainOptions(mainOptions map[string]string) (fc *fileCollector, err error) {
|
||||
fileFilter := mainOptions["file-filter"]
|
||||
if fileFilter == "" {
|
||||
|
@ -278,7 +268,8 @@ func main() {
|
|||
log.Print("the -d option is not supported by gitea-fmt")
|
||||
}
|
||||
cmdErrors = append(cmdErrors, giteaFormatGoImports(files, containsString(subArgs, "-w")))
|
||||
cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("GOFUMPT_PACKAGE"), "-extra", "-lang", getGoVersion()}, substArgs...)))
|
||||
cmdErrors = append(cmdErrors, passThroughCmd("gofmt", append([]string{"-w", "-r", "interface{} -> any"}, substArgs...)))
|
||||
cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("GOFUMPT_PACKAGE"), "-extra"}, substArgs...)))
|
||||
default:
|
||||
log.Fatalf("unknown cmd: %s %v", subCmd, subArgs)
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ func showWebStartupMessage(msg string) {
|
|||
log.Info("* WorkPath: %s", setting.AppWorkPath)
|
||||
log.Info("* CustomPath: %s", setting.CustomPath)
|
||||
log.Info("* ConfigFile: %s", setting.CustomConf)
|
||||
log.Info("%s", msg)
|
||||
log.Info("%s", msg) // show startup message
|
||||
}
|
||||
|
||||
func serveInstall(ctx *cli.Context) error {
|
||||
|
|
|
@ -44,6 +44,9 @@ func (schedules ScheduleList) LoadTriggerUser(ctx context.Context) error {
|
|||
schedule.TriggerUser = user_model.NewActionsUser()
|
||||
} else {
|
||||
schedule.TriggerUser = users[schedule.TriggerUserID]
|
||||
if schedule.TriggerUser == nil {
|
||||
schedule.TriggerUser = user_model.NewGhostUser()
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
@ -227,7 +228,9 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
|
|||
if runner.RepoID != 0 {
|
||||
jobCond = builder.Eq{"repo_id": runner.RepoID}
|
||||
} else if runner.OwnerID != 0 {
|
||||
jobCond = builder.In("repo_id", builder.Select("id").From("repository").Where(builder.Eq{"owner_id": runner.OwnerID}))
|
||||
jobCond = builder.In("repo_id", builder.Select("`repository`.id").From("repository").
|
||||
Join("INNER", "repo_unit", "`repository`.id = `repo_unit`.repo_id").
|
||||
Where(builder.Eq{"`repository`.owner_id": runner.OwnerID, "`repo_unit`.type": unit.TypeActions}))
|
||||
}
|
||||
if jobCond.IsValid() {
|
||||
jobCond = builder.In("run_id", builder.Select("id").From("action_run").Where(jobCond))
|
||||
|
|
|
@ -76,23 +76,14 @@ func calcFingerprintNative(publicKeyContent string) (string, error) {
|
|||
// CalcFingerprint calculate public key's fingerprint
|
||||
func CalcFingerprint(publicKeyContent string) (string, error) {
|
||||
// Call the method based on configuration
|
||||
var (
|
||||
fnName, fp string
|
||||
err error
|
||||
)
|
||||
if len(setting.SSH.KeygenPath) == 0 {
|
||||
fnName = "calcFingerprintNative"
|
||||
fp, err = calcFingerprintNative(publicKeyContent)
|
||||
} else {
|
||||
fnName = "calcFingerprintSSHKeygen"
|
||||
fp, err = calcFingerprintSSHKeygen(publicKeyContent)
|
||||
}
|
||||
useNative := setting.SSH.KeygenPath == ""
|
||||
calcFn := util.Iif(useNative, calcFingerprintNative, calcFingerprintSSHKeygen)
|
||||
fp, err := calcFn(publicKeyContent)
|
||||
if err != nil {
|
||||
if IsErrKeyUnableVerify(err) {
|
||||
log.Info("%s", publicKeyContent)
|
||||
return "", err
|
||||
}
|
||||
return "", fmt.Errorf("%s: %w", fnName, err)
|
||||
return "", fmt.Errorf("CalcFingerprint(%s): %w", util.Iif(useNative, "native", "ssh-keygen"), err)
|
||||
}
|
||||
return fp, nil
|
||||
}
|
||||
|
|
|
@ -144,6 +144,11 @@ func (app *OAuth2Application) TableName() string {
|
|||
|
||||
// ContainsRedirectURI checks if redirectURI is allowed for app
|
||||
func (app *OAuth2Application) ContainsRedirectURI(redirectURI string) bool {
|
||||
// OAuth2 requires the redirect URI to be an exact match, no dynamic parts are allowed.
|
||||
// https://stackoverflow.com/questions/55524480/should-dynamic-query-parameters-be-present-in-the-redirection-uri-for-an-oauth2
|
||||
// https://www.rfc-editor.org/rfc/rfc6819#section-5.2.3.3
|
||||
// https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
||||
// https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-12#section-3.1
|
||||
contains := func(s string) bool {
|
||||
s = strings.TrimSuffix(strings.ToLower(s), "/")
|
||||
for _, u := range app.RedirectURIs {
|
||||
|
|
|
@ -53,7 +53,7 @@ func (repo *Repository) IsDependenciesEnabled(ctx context.Context) bool {
|
|||
var u *RepoUnit
|
||||
var err error
|
||||
if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil {
|
||||
log.Trace("%s", err)
|
||||
log.Trace("IsDependenciesEnabled: %v", err)
|
||||
return setting.Service.DefaultEnableDependencies
|
||||
}
|
||||
return u.IssuesConfig().EnableDependencies
|
||||
|
|
|
@ -35,7 +35,7 @@ func (o *Option[T]) UnmarshalYAML(value *yaml.Node) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o Option[T]) MarshalYAML() (interface{}, error) {
|
||||
func (o Option[T]) MarshalYAML() (any, error) {
|
||||
if !o.Has() {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@ package session
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/web/middleware"
|
||||
|
||||
"gitea.com/go-chi/session"
|
||||
)
|
||||
|
||||
|
@ -18,6 +21,10 @@ type Store interface {
|
|||
|
||||
// RegenerateSession regenerates the underlying session and returns the new store
|
||||
func RegenerateSession(resp http.ResponseWriter, req *http.Request) (Store, error) {
|
||||
// Ensure that a cookie with a trailing slash does not take precedence over
|
||||
// the cookie written by the middleware.
|
||||
middleware.DeleteLegacySiteCookie(resp, setting.SessionConfig.CookieName)
|
||||
|
||||
s, err := session.RegenerateSession(resp, req)
|
||||
return s, err
|
||||
}
|
||||
|
|
|
@ -142,35 +142,39 @@ type remoteAddress struct {
|
|||
Password string
|
||||
}
|
||||
|
||||
func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteName string, ignoreOriginalURL bool) remoteAddress {
|
||||
a := remoteAddress{}
|
||||
|
||||
remoteURL := m.OriginalURL
|
||||
if ignoreOriginalURL || remoteURL == "" {
|
||||
var err error
|
||||
remoteURL, err = git.GetRemoteAddress(ctx, m.RepoPath(), remoteName)
|
||||
if err != nil {
|
||||
log.Error("GetRemoteURL %v", err)
|
||||
return a
|
||||
}
|
||||
func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteName string) remoteAddress {
|
||||
ret := remoteAddress{}
|
||||
remoteURL, err := git.GetRemoteAddress(ctx, m.RepoPath(), remoteName)
|
||||
if err != nil {
|
||||
log.Error("GetRemoteURL %v", err)
|
||||
return ret
|
||||
}
|
||||
|
||||
u, err := giturl.Parse(remoteURL)
|
||||
if err != nil {
|
||||
log.Error("giturl.Parse %v", err)
|
||||
return a
|
||||
return ret
|
||||
}
|
||||
|
||||
if u.Scheme != "ssh" && u.Scheme != "file" {
|
||||
if u.User != nil {
|
||||
a.Username = u.User.Username()
|
||||
a.Password, _ = u.User.Password()
|
||||
ret.Username = u.User.Username()
|
||||
ret.Password, _ = u.User.Password()
|
||||
}
|
||||
u.User = nil
|
||||
}
|
||||
a.Address = u.String()
|
||||
|
||||
return a
|
||||
// The URL stored in the git repo could contain authentication,
|
||||
// erase it, or it will be shown in the UI.
|
||||
u.User = nil
|
||||
ret.Address = u.String()
|
||||
// Why not use m.OriginalURL to set ret.Address?
|
||||
// It should be OK to use it, since m.OriginalURL should be the same as the authentication-erased URL from the Git repository.
|
||||
// However, the old code has already stored authentication in m.OriginalURL when updating mirror settings.
|
||||
// That means we need to use "giturl.Parse" for m.OriginalURL again to ensure authentication is erased.
|
||||
// Instead of doing this, why not directly use the authentication-erased URL from the Git repository?
|
||||
// It should be the same as long as there are no bugs.
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func FilenameIsImage(filename string) bool {
|
||||
|
|
|
@ -213,6 +213,14 @@ func ToPointer[T any](val T) *T {
|
|||
return &val
|
||||
}
|
||||
|
||||
// Iif is an "inline-if", it returns "trueVal" if "condition" is true, otherwise "falseVal"
|
||||
func Iif[T any](condition bool, trueVal, falseVal T) T {
|
||||
if condition {
|
||||
return trueVal
|
||||
}
|
||||
return falseVal
|
||||
}
|
||||
|
||||
func ReserveLineBreakForTextarea(input string) string {
|
||||
// Since the content is from a form which is a textarea, the line endings are \r\n.
|
||||
// It's a standard behavior of HTML.
|
||||
|
|
|
@ -45,10 +45,32 @@ func SetSiteCookie(resp http.ResponseWriter, name, value string, maxAge int) {
|
|||
SameSite: setting.SessionConfig.SameSite,
|
||||
}
|
||||
resp.Header().Add("Set-Cookie", cookie.String())
|
||||
if maxAge < 0 {
|
||||
// There was a bug in "setting.SessionConfig.CookiePath" code, the old default value of it was empty "".
|
||||
// So we have to delete the cookie on path="" again, because some old code leaves cookies on path="".
|
||||
cookie.Path = strings.TrimSuffix(setting.SessionConfig.CookiePath, "/")
|
||||
resp.Header().Add("Set-Cookie", cookie.String())
|
||||
}
|
||||
// Previous versions would use a cookie path with a trailing /.
|
||||
// These are more specific than cookies without a trailing /, so
|
||||
// we need to delete these if they exist.
|
||||
DeleteLegacySiteCookie(resp, name)
|
||||
}
|
||||
|
||||
// DeleteLegacySiteCookie deletes the cookie with the given name at the cookie
|
||||
// path with a trailing /, which would unintentionally override the cookie.
|
||||
func DeleteLegacySiteCookie(resp http.ResponseWriter, name string) {
|
||||
if setting.SessionConfig.CookiePath == "" || strings.HasSuffix(setting.SessionConfig.CookiePath, "/") {
|
||||
// If the cookie path ends with /, no legacy cookies will take
|
||||
// precedence, so do nothing. The exception is that cookies with no
|
||||
// path could override other cookies, but it's complicated and we don't
|
||||
// currently handle that.
|
||||
return
|
||||
}
|
||||
|
||||
cookie := &http.Cookie{
|
||||
Name: name,
|
||||
Value: "",
|
||||
MaxAge: -1,
|
||||
Path: setting.SessionConfig.CookiePath + "/",
|
||||
Domain: setting.SessionConfig.Domain,
|
||||
Secure: setting.SessionConfig.Secure,
|
||||
HttpOnly: true,
|
||||
SameSite: setting.SessionConfig.SameSite,
|
||||
}
|
||||
resp.Header().Add("Set-Cookie", cookie.String())
|
||||
}
|
||||
|
|
|
@ -210,21 +210,21 @@ PART 1: INITIAL CONTRIBUTOR AND DESIGNATED WEB SITE
|
|||
|
||||
The Initial Contributor is:
|
||||
____________________________________________________
|
||||
|
||||
|
||||
[Enter full name of Initial Contributor]
|
||||
|
||||
Address of Initial Contributor:
|
||||
________________________________________________
|
||||
|
||||
|
||||
________________________________________________
|
||||
|
||||
|
||||
________________________________________________
|
||||
|
||||
|
||||
[Enter address above]
|
||||
|
||||
The Designated Web Site is:
|
||||
__________________________________________________
|
||||
|
||||
|
||||
[Enter URL for Designated Web Site of Initial Contributor]
|
||||
|
||||
NOTE: The Initial Contributor is to complete this Part 1, along with Parts 2, 3, and 5, and, if applicable, Parts 4 and 6.
|
||||
|
@ -237,27 +237,27 @@ The date on which the Initial Work was first available under this License: _____
|
|||
|
||||
PART 3: GOVERNING JURISDICTION
|
||||
|
||||
For the purposes of this License, the Governing Jurisdiction is _________________________________________________.
[Initial Contributor to Enter Governing Jurisdiction here]
|
||||
For the purposes of this License, the Governing Jurisdiction is _________________________________________________. [Initial Contributor to Enter Governing Jurisdiction here]
|
||||
|
||||
PART 4: THIRD PARTIES
|
||||
|
||||
For the purposes of this License, "Third Party" has the definition set forth below in the ONE paragraph selected by the Initial Contributor from paragraphs A, B, C, D and E when the Initial Work is distributed or otherwise made available by the Initial Contributor. To select one of the following paragraphs, the Initial Contributor must place an "X" or "x" in the selection box alongside the one respective paragraph selected.
|
||||
SELECTION
|
||||
|
||||
|
||||
BOX PARAGRAPH
|
||||
[ ] A. "THIRD PARTY" means any third party.
|
||||
|
||||
|
||||
[ ] B. "THIRD PARTY" means any third party except for any of the following: (a) a wholly owned subsidiary of the Subsequent Contributor in question; (b) a legal entity (the "PARENT") that wholly owns the Subsequent Contributor in question; or (c) a wholly owned subsidiary of the wholly owned subsidiary in (a) or of the Parent in (b).
|
||||
|
||||
|
||||
[ ] C. "THIRD PARTY" means any third party except for any of the following: (a) any Person directly or indirectly owning a majority of the voting interest in the Subsequent Contributor or (b) any Person in which the Subsequent Contributor directly or indirectly owns a majority voting interest.
|
||||
|
||||
|
||||
[ ] D. "THIRD PARTY" means any third party except for any Person directly or indirectly controlled by the Subsequent Contributor. For purposes of this definition, "control" shall mean the power to direct or cause the direction of, the management and policies of such Person whether through the ownership of voting interests, by contract, or otherwise.
|
||||
|
||||
|
||||
[ ] E. "THIRD PARTY" means any third party except for any Person directly or indirectly controlling, controlled by, or under common control with the Subsequent Contributor. For purposes of this definition, "control" shall mean the power to direct or cause the direction of, the management and policies of such Person whether through the ownership of voting interests, by contract, or otherwise.
|
||||
[ ] A. "THIRD PARTY" means any third party.
|
||||
|
||||
|
||||
[ ] B. "THIRD PARTY" means any third party except for any of the following: (a) a wholly owned subsidiary of the Subsequent Contributor in question; (b) a legal entity (the "PARENT") that wholly owns the Subsequent Contributor in question; or (c) a wholly owned subsidiary of the wholly owned subsidiary in (a) or of the Parent in (b).
|
||||
|
||||
|
||||
[ ] C. "THIRD PARTY" means any third party except for any of the following: (a) any Person directly or indirectly owning a majority of the voting interest in the Subsequent Contributor or (b) any Person in which the Subsequent Contributor directly or indirectly owns a majority voting interest.
|
||||
|
||||
|
||||
[ ] D. "THIRD PARTY" means any third party except for any Person directly or indirectly controlled by the Subsequent Contributor. For purposes of this definition, "control" shall mean the power to direct or cause the direction of, the management and policies of such Person whether through the ownership of voting interests, by contract, or otherwise.
|
||||
|
||||
|
||||
[ ] E. "THIRD PARTY" means any third party except for any Person directly or indirectly controlling, controlled by, or under common control with the Subsequent Contributor. For purposes of this definition, "control" shall mean the power to direct or cause the direction of, the management and policies of such Person whether through the ownership of voting interests, by contract, or otherwise.
|
||||
The default definition of "THIRD PARTY" is the definition set forth in paragraph A, if NONE OR MORE THAN ONE of paragraphs A, B, C, D or E in this Part 4 are selected by the Initial Contributor.
|
||||
|
||||
PART 5: NOTICE
|
||||
|
@ -271,8 +271,8 @@ PART 6: PATENT LICENSING TERMS
|
|||
For the purposes of this License, paragraphs A, B, C, D and E of this Part 6 of Exhibit A are only incorporated and form part of the terms of the License if the Initial Contributor places an "X" or "x" in the selection box alongside the YES answer to the question immediately below.
|
||||
|
||||
Is this a Patents-Included License pursuant to Section 2.2 of the License?
|
||||
YES [ ]
|
||||
NO [ ]
|
||||
YES [ ]
|
||||
NO [ ]
|
||||
|
||||
By default, if YES is not selected by the Initial Contributor, the answer is NO.
|
||||
|
||||
|
|
|
@ -4,5 +4,5 @@ Any user of this software should understand that IBM cannot provide technical su
|
|||
|
||||
Any person who transfers this source code or any derivative work must include the IBM copyright notice, this paragraph, and the preceding two paragraphs in the transferred software.
|
||||
|
||||
COPYRIGHT I B M CORPORATION 2002
|
||||
LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
|
||||
COPYRIGHT I B M CORPORATION 2002
|
||||
LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
|
||||
|
|
|
@ -12,15 +12,15 @@ The Licensor grants you a worldwide, royalty-free, perpetual, non-exclusive lice
|
|||
This licence does not affect your freedom under fair dealing or fair use or any other copyright or database right exceptions and limitations.
|
||||
|
||||
You are free to:
|
||||
copy, publish, distribute and transmit the Information;
|
||||
copy, publish, distribute and transmit the Information;
|
||||
adapt the Information;
|
||||
exploit the Information for Non-Commercial purposes for example, by combining it with other information in your own product or application.
|
||||
|
||||
You are not permitted to:
|
||||
exercise any of the rights granted to you by this licence in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation.
|
||||
exercise any of the rights granted to you by this licence in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation.
|
||||
|
||||
You must, where you do any of the above:
|
||||
acknowledge the source of the Information by including any attribution statement specified by the Information Provider(s) and, where possible, provide a link to this licence;
|
||||
acknowledge the source of the Information by including any attribution statement specified by the Information Provider(s) and, where possible, provide a link to this licence;
|
||||
|
||||
If the Information Provider does not provide a specific attribution statement, you must use the following:
|
||||
Contains information licensed under the Non-Commercial Government Licence v2.0.
|
||||
|
|
|
@ -2,7 +2,7 @@ Netscape Public LIcense version 1.1
|
|||
|
||||
AMENDMENTS
|
||||
|
||||
The Netscape Public License Version 1.1 ("NPL") consists of the Mozilla Public License Version 1.1 with the following Amendments, including Exhibit A-Netscape Public License. Files identified with "Exhibit A-Netscape Public License" are governed by the Netscape Public License Version 1.1.
|
||||
The Netscape Public License Version 1.1 ("NPL") consists of the Mozilla Public License Version 1.1 with the following Amendments, including Exhibit A-Netscape Public License. Files identified with "Exhibit A-Netscape Public License" are governed by the Netscape Public License Version 1.1.
|
||||
|
||||
Additional Terms applicable to the Netscape Public License.
|
||||
|
||||
|
@ -28,7 +28,7 @@ Additional Terms applicable to the Netscape Public License.
|
|||
Notwithstanding the limitations of Section 11 above, the provisions regarding litigation in Section 11(a), (b) and (c) of the License shall apply to all disputes relating to this License.
|
||||
|
||||
EXHIBIT A-Netscape Public License.
|
||||
|
||||
|
||||
"The contents of this file are subject to the Netscape Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/NPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License.
|
||||
|
@ -37,8 +37,8 @@ The Original Code is Mozilla Communicator client code, released March 31, 1998.
|
|||
|
||||
The Initial Developer of the Original Code is Netscape Communications Corporation. Portions created by Netscape are Copyright (C) 1998-1999 Netscape Communications Corporation. All Rights Reserved.
|
||||
Contributor(s): ______________________________________.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the _____ license (the "[___] License"), in which case the provisions of [______] License are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the [____] License and not to allow others to use your version of this file under the NPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the [___] License. If you do not delete the provisions above, a recipient may use your version of this file under either the NPL or the [___] License."
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the _____ license (the "[___] License"), in which case the provisions of [______] License are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the [____] License and not to allow others to use your version of this file under the NPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the [___] License. If you do not delete the provisions above, a recipient may use your version of this file under either the NPL or the [___] License."
|
||||
|
||||
|
||||
Mozilla Public License Version 1.1
|
||||
|
|
|
@ -6,7 +6,7 @@ OPEN CASCADE releases and makes publicly available the source code of the softwa
|
|||
It is not the purpose of this license to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this license has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
|
||||
|
||||
Please read this license carefully and completely before downloading this software. By downloading, using, modifying, distributing and sublicensing this software, you indicate your acceptance to be bound by the terms and conditions of this license. If you do not want to accept or cannot accept for any reasons the terms and conditions of this license, please do not download or use in any manner this software.
|
||||
|
||||
|
||||
1. Definitions
|
||||
|
||||
Unless there is something in the subject matter or in the context inconsistent therewith, the capitalized terms used in this License shall have the following meaning.
|
||||
|
@ -26,13 +26,13 @@ Unless there is something in the subject matter or in the context inconsistent t
|
|||
"Software": means the Original Code, the Modifications, the combination of Original Code and any Modifications or any respective portions thereof.
|
||||
|
||||
"You" or "Your": means an individual or a legal entity exercising rights under this License
|
||||
|
||||
|
||||
2. Acceptance of license
|
||||
By using, reproducing, modifying, distributing or sublicensing the Software or any portion thereof, You expressly indicate Your acceptance of the terms and conditions of this License and undertake to act in accordance with all the provisions of this License applicable to You.
|
||||
|
||||
|
||||
3. Scope and purpose
|
||||
This License applies to the Software and You may not use, reproduce, modify, distribute, sublicense or circulate the Software, or any portion thereof, except as expressly provided under this License. Any attempt to otherwise use, reproduce, modify, distribute or sublicense the Software is void and will automatically terminate Your rights under this License.
|
||||
|
||||
|
||||
4. Contributor license
|
||||
Subject to the terms and conditions of this License, the Initial Developer and each of the Contributors hereby grant You a world-wide, royalty-free, irrevocable and non-exclusive license under the Applicable Intellectual Property Rights they own or control, to use, reproduce, modify, distribute and sublicense the Software provided that:
|
||||
|
||||
|
|
|
@ -10,20 +10,20 @@ The Licensor grants you a worldwide, royalty-free, perpetual, non-exclusive lice
|
|||
This licence does not affect your freedom under fair dealing or fair use or any other copyright or database right exceptions and limitations.
|
||||
|
||||
You are free to:
|
||||
copy, publish, distribute and transmit the Information;
|
||||
copy, publish, distribute and transmit the Information;
|
||||
adapt the Information;
|
||||
exploit the Information commercially for example, by combining it with other Information, or by including it in your own product or application.
|
||||
|
||||
You must, where you do any of the above:
|
||||
acknowledge the source of the Information by including any attribution statement specified by the Information Provider(s) and, where possible, provide a link to this licence;
|
||||
If the Information Provider does not provide a specific attribution statement, or if you are using Information from several Information Providers and multiple attributions are not practical in your product or application, you may consider using the following:
Contains public sector information licensed under the Open Government Licence v1.0.
|
||||
acknowledge the source of the Information by including any attribution statement specified by the Information Provider(s) and, where possible, provide a link to this licence;
|
||||
If the Information Provider does not provide a specific attribution statement, or if you are using Information from several Information Providers and multiple attributions are not practical in your product or application, you may consider using the following: Contains public sector information licensed under the Open Government Licence v1.0.
|
||||
ensure that you do not use the Information in a way that suggests any official status or that the Information Provider endorses you or your use of the Information;
|
||||
ensure that you do not mislead others or misrepresent the Information or its source;
|
||||
ensure that your use of the Information does not breach the Data Protection Act 1998 or the Privacy and Electronic Communications (EC Directive) Regulations 2003.
|
||||
|
||||
These are important conditions of this licence and if you fail to comply with them the rights granted to you under this licence, or any similar licence granted by the Licensor, will end automatically.
|
||||
|
||||
Exemptions
|
||||
Exemptions
|
||||
|
||||
This licence does not cover the use of:
|
||||
- personal data in the Information;
|
||||
|
@ -48,22 +48,22 @@ Definitions
|
|||
|
||||
In this licence, the terms below have the following meanings:
|
||||
|
||||
‘Information’
means information protected by copyright or by database right (for example, literary and artistic works, content, data and source code) offered for use under the terms of this licence.
|
||||
‘Information’ means information protected by copyright or by database right (for example, literary and artistic works, content, data and source code) offered for use under the terms of this licence.
|
||||
|
||||
‘Information Provider’
means the person or organisation providing the Information under this licence.
|
||||
‘Information Provider’ means the person or organisation providing the Information under this licence.
|
||||
|
||||
‘Licensor’
means any Information Provider which has the authority to offer Information under the terms of this licence or the Controller of Her Majesty’s Stationery Office, who has the authority to offer Information subject to Crown copyright and Crown database rights and Information subject to copyright and database right that has been assigned to or acquired by the Crown, under the terms of this licence.
|
||||
‘Licensor’ means any Information Provider which has the authority to offer Information under the terms of this licence or the Controller of Her Majesty’s Stationery Office, who has the authority to offer Information subject to Crown copyright and Crown database rights and Information subject to copyright and database right that has been assigned to or acquired by the Crown, under the terms of this licence.
|
||||
|
||||
‘Use’
as a verb, means doing any act which is restricted by copyright or database right, whether in the original medium or in any other medium, and includes without limitation distributing, copying, adapting, modifying as may be technically necessary to use it in a different mode or format.
|
||||
‘Use’ as a verb, means doing any act which is restricted by copyright or database right, whether in the original medium or in any other medium, and includes without limitation distributing, copying, adapting, modifying as may be technically necessary to use it in a different mode or format.
|
||||
|
||||
‘You’
means the natural or legal person, or body of persons corporate or incorporate, acquiring rights under this licence.
|
||||
‘You’ means the natural or legal person, or body of persons corporate or incorporate, acquiring rights under this licence.
|
||||
|
||||
About the Open Government Licence
|
||||
The Controller of Her Majesty’s Stationery Office (HMSO) has developed this licence as a tool to enable Information Providers in the public sector to license the use and re-use of their Information under a common open licence. The Controller invites public sector bodies owning their own copyright and database rights to permit the use of their Information under this licence.
|
||||
|
||||
The Controller of HMSO has authority to license Information subject to copyright and database right owned by the Crown. The extent of the Controller’s offer to license this Information under the terms of this licence is set out in the UK Government Licensing Framework.
|
||||
The Controller of HMSO has authority to license Information subject to copyright and database right owned by the Crown. The extent of the Controller’s offer to license this Information under the terms of this licence is set out in the UK Government Licensing Framework.
|
||||
|
||||
This is version 1.0 of the Open Government Licence. The Controller of HMSO may, from time to time, issue new versions of the Open Government Licence. However, you may continue to use Information licensed under this version should you wish to do so.
|
||||
These terms have been aligned to be interoperable with any Creative Commons Attribution Licence, which covers copyright, and Open Data Commons Attribution License, which covers database rights and applicable copyrights.
|
||||
|
||||
Further context, best practice and guidance can be found in the UK Government Licensing Framework section on The National Archives website.
|
||||
Further context, best practice and guidance can be found in the UK Government Licensing Framework section on The National Archives website.
|
||||
|
|
|
@ -100,7 +100,8 @@ If it is impossible for You to comply with any of the terms of this License with
|
|||
5.1 Failure to Comply
|
||||
The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60-days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30-days after Your receipt of the notice.
|
||||
|
||||
5.2 Patent Infringement Claims
If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate.
|
||||
5.2 Patent Infringement Claims
|
||||
If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate.
|
||||
|
||||
5.3 Additional Compliance Terms
|
||||
Notwithstanding the foregoing in this Section 5, for purposes of this Section, if You breach Section 3.1 (Distribution of Source Form), Section 3.2 (Distribution of Executable Form), Section 3.3 (Distribution of a Larger Work), or Section 3.4 (Notices), then becoming compliant as described in Section 5.1 must also include, no later than 30 days after receipt by You of notice of such violation by a Contributor, making the Covered Software available in Source Code Form as required by this License on a publicly available computer network for a period of no less than three (3) years.
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
# Solderpad Hardware Licence Version 2.0
|
||||
|
||||
This licence (the “Licence”) operates as a wraparound licence to the Apache License Version 2.0 (the “Apache License”) and grants to You the rights, and imposes the obligations, set out in the Apache License (which can be found here: http://apache.org/licenses/LICENSE-2.0), with the following extensions. It must be read in conjunction with the Apache License. Section 1 below modifies definitions in the Apache License, and section 2 below replaces sections 2 of the Apache License. You may, at your option, choose to treat any Work released under this License as released under the Apache License (thus ignoring all sections written below entirely). Words in italics indicate changes rom the Apache License, but are indicative and not to be taken into account in interpretation.
|
||||
This licence (the “Licence”) operates as a wraparound licence to the Apache License Version 2.0 (the “Apache License”) and grants to You the rights, and imposes the obligations, set out in the Apache License (which can be found here: http://apache.org/licenses/LICENSE-2.0), with the following extensions. It must be read in conjunction with the Apache License. Section 1 below modifies definitions in the Apache License, and section 2 below replaces sections 2 of the Apache License. You may, at your option, choose to treat any Work released under this License as released under the Apache License (thus ignoring all sections written below entirely). Words in italics indicate changes rom the Apache License, but are indicative and not to be taken into account in interpretation.
|
||||
|
||||
1. The definitions set out in the Apache License are modified as follows:
|
||||
|
||||
Copyright any reference to ‘copyright’ (whether capitalised or not) includes ‘Rights’ (as defined below).
|
||||
Copyright any reference to ‘copyright’ (whether capitalised or not) includes ‘Rights’ (as defined below).
|
||||
|
||||
Contribution also includes any design, as well as any work of authorship.
|
||||
Contribution also includes any design, as well as any work of authorship.
|
||||
|
||||
Derivative Works shall not include works that remain reversibly separable from, or merely link (or bind by name) or physically connect to or interoperate with the interfaces of the Work and Derivative Works thereof.
|
||||
Derivative Works shall not include works that remain reversibly separable from, or merely link (or bind by name) or physically connect to or interoperate with the interfaces of the Work and Derivative Works thereof.
|
||||
|
||||
Object form shall mean any form resulting from mechanical transformation or translation of a Source form or the application of a Source form to physical material, including but not limited to compiled object code, generated documentation, the instantiation of a hardware design or physical object and conversions to other media types, including intermediate forms such as bytecodes, FPGA bitstreams, moulds, artwork and semiconductor topographies (mask works).
|
||||
Object form shall mean any form resulting from mechanical transformation or translation of a Source form or the application of a Source form to physical material, including but not limited to compiled object code, generated documentation, the instantiation of a hardware design or physical object and conversions to other media types, including intermediate forms such as bytecodes, FPGA bitstreams, moulds, artwork and semiconductor topographies (mask works).
|
||||
|
||||
Rights means copyright and any similar right including design right (whether registered or unregistered), semiconductor topography (mask) rights and database rights (but excluding Patents and Trademarks).
|
||||
Rights means copyright and any similar right including design right (whether registered or unregistered), semiconductor topography (mask) rights and database rights (but excluding Patents and Trademarks).
|
||||
|
||||
Source form shall mean the preferred form for making modifications, including but not limited to source code, net lists, board layouts, CAD files, documentation source, and configuration files.
|
||||
Work also includes a design or work of authorship, whether in Source form or other Object form.
|
||||
Source form shall mean the preferred form for making modifications, including but not limited to source code, net lists, board layouts, CAD files, documentation source, and configuration files.
|
||||
Work also includes a design or work of authorship, whether in Source form or other Object form.
|
||||
|
||||
2. Grant of Licence
|
||||
|
||||
2.1 Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable license under the Rights to reproduce, prepare Derivative Works of, make, adapt, repair, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form and do anything in relation to the Work as if the Rights did not exist.
|
||||
2.1 Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable license under the Rights to reproduce, prepare Derivative Works of, make, adapt, repair, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form and do anything in relation to the Work as if the Rights did not exist.
|
||||
|
|
|
@ -19,7 +19,7 @@ The following definitions shall replace the corresponding definitions in the Apa
|
|||
"License" shall mean this Solderpad Hardware License version 2.1, being the terms and conditions for use, manufacture, instantiation, adaptation, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the Rights owner or entity authorized by the Rights owner that is granting the License.
|
||||
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship or design. For the purposes of this License, Derivative Works shall not include works that remain reversibly separable from, or merely link (or bind by name) or physically connect to or interoperate with the Work and Derivative Works thereof.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form or the application of a Source form to physical material, including but not limited to compiled object code, generated documentation, the instantiation of a hardware design or physical object or material and conversions to other media types, including intermediate forms such as bytecodes, FPGA bitstreams, moulds, artwork and semiconductor topographies (mask works).
|
||||
|
|
|
@ -36,13 +36,13 @@ Sun Industry Standards Source License - Version 1.1
|
|||
|
||||
2.0 SOURCE CODE LICENSE
|
||||
|
||||
2.1 The Initial Developer Grant The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims:
|
||||
2.1 The Initial Developer Grant The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and
|
||||
|
||||
(b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof).
|
||||
(c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License.
|
||||
(d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices, including but not limited to Modifications.
|
||||
(d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices, including but not limited to Modifications.
|
||||
|
||||
3.0 DISTRIBUTION OBLIGATIONS
|
||||
|
||||
|
@ -92,14 +92,14 @@ This License represents the complete agreement concerning subject matter hereof.
|
|||
|
||||
EXHIBIT A - Sun Standards License
|
||||
|
||||
"The contents of this file are subject to the Sun Standards License Version 1.1 (the "License"); You may not use this file except in compliance with the License. You may obtain a copy of the License at _______________________________.
|
||||
"The contents of this file are subject to the Sun Standards License Version 1.1 (the "License"); You may not use this file except in compliance with the License. You may obtain a copy of the License at _______________________________.
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||
express or implied. See the License for the specific language governing rights and limitations under the License.
|
||||
|
||||
The Original Code is ______________________________________.
|
||||
|
||||
The Initial Developer of the Original Code is:
|
||||
The Initial Developer of the Original Code is:
|
||||
Sun Microsystems, Inc..
|
||||
|
||||
Portions created by: _______________________________________
|
||||
|
|
|
@ -4,7 +4,7 @@ Copyright (c) 1994-2002 World Wide Web Consortium, (Massachusetts Institute of T
|
|||
|
||||
This W3C work (including software, documents, or other related items) is being provided by the copyright holders under the following license. By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its documentation, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications, that you make:
|
||||
Permission to use, copy, modify, and distribute this software and its documentation, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications, that you make:
|
||||
|
||||
1. The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
|
||||
|
||||
|
|
|
@ -311,7 +311,7 @@ func SearchIssues(ctx *context.APIContext) {
|
|||
|
||||
ctx.SetLinkHeader(int(total), limit)
|
||||
ctx.SetTotalCountHeader(total)
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues))
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, ctx.Doer, issues))
|
||||
}
|
||||
|
||||
// ListIssues list the issues of a repository
|
||||
|
@ -548,7 +548,7 @@ func ListIssues(ctx *context.APIContext) {
|
|||
|
||||
ctx.SetLinkHeader(int(total), listOptions.PageSize)
|
||||
ctx.SetTotalCountHeader(total)
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues))
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, ctx.Doer, issues))
|
||||
}
|
||||
|
||||
func getUserIDForFilter(ctx *context.APIContext, queryName string) int64 {
|
||||
|
@ -614,7 +614,7 @@ func GetIssue(ctx *context.APIContext) {
|
|||
ctx.NotFound()
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue))
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, ctx.Doer, issue))
|
||||
}
|
||||
|
||||
// CreateIssue create an issue of a repository
|
||||
|
@ -737,7 +737,7 @@ func CreateIssue(ctx *context.APIContext) {
|
|||
ctx.Error(http.StatusInternalServerError, "GetIssueByID", err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, issue))
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, issue))
|
||||
}
|
||||
|
||||
// EditIssue modify an issue of a repository
|
||||
|
@ -913,7 +913,7 @@ func EditIssue(ctx *context.APIContext) {
|
|||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, issue))
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, issue))
|
||||
}
|
||||
|
||||
func DeleteIssue(ctx *context.APIContext) {
|
||||
|
|
|
@ -108,7 +108,7 @@ func ListIssueAttachments(ctx *context.APIContext) {
|
|||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue).Attachments)
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, ctx.Doer, issue).Attachments)
|
||||
}
|
||||
|
||||
// CreateIssueAttachment creates an attachment and saves the given file
|
||||
|
|
|
@ -153,7 +153,7 @@ func GetIssueDependencies(ctx *context.APIContext) {
|
|||
blockerIssues = append(blockerIssues, &blocker.Issue)
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, blockerIssues))
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, ctx.Doer, blockerIssues))
|
||||
}
|
||||
|
||||
// CreateIssueDependency create a new issue dependencies
|
||||
|
@ -214,7 +214,7 @@ func CreateIssueDependency(ctx *context.APIContext) {
|
|||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, target))
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, target))
|
||||
}
|
||||
|
||||
// RemoveIssueDependency remove an issue dependency
|
||||
|
@ -275,7 +275,7 @@ func RemoveIssueDependency(ctx *context.APIContext) {
|
|||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, target))
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, target))
|
||||
}
|
||||
|
||||
// GetIssueBlocks list issues that are blocked by this issue
|
||||
|
@ -381,7 +381,7 @@ func GetIssueBlocks(ctx *context.APIContext) {
|
|||
issues = append(issues, &depMeta.Issue)
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues))
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, ctx.Doer, issues))
|
||||
}
|
||||
|
||||
// CreateIssueBlocking block the issue given in the body by the issue in path
|
||||
|
@ -438,7 +438,7 @@ func CreateIssueBlocking(ctx *context.APIContext) {
|
|||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, dependency))
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, dependency))
|
||||
}
|
||||
|
||||
// RemoveIssueBlocking unblock the issue given in the body by the issue in path
|
||||
|
@ -495,7 +495,7 @@ func RemoveIssueBlocking(ctx *context.APIContext) {
|
|||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, dependency))
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, dependency))
|
||||
}
|
||||
|
||||
func getParamsIssue(ctx *context.APIContext) *issues_model.Issue {
|
||||
|
|
|
@ -207,7 +207,7 @@ func ListPinnedIssues(ctx *context.APIContext) {
|
|||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues))
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, ctx.Doer, issues))
|
||||
}
|
||||
|
||||
// ListPinnedPullRequests returns a list of all pinned PRs
|
||||
|
|
|
@ -138,7 +138,7 @@ func ListTrackedTimes(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
ctx.SetTotalCountHeader(count)
|
||||
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes))
|
||||
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, ctx.Doer, trackedTimes))
|
||||
}
|
||||
|
||||
// AddTime add time manual to the given issue
|
||||
|
@ -225,7 +225,7 @@ func AddTime(ctx *context.APIContext) {
|
|||
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, convert.ToTrackedTime(ctx, trackedTime))
|
||||
ctx.JSON(http.StatusOK, convert.ToTrackedTime(ctx, user, trackedTime))
|
||||
}
|
||||
|
||||
// ResetIssueTime reset time manual to the given issue
|
||||
|
@ -455,7 +455,7 @@ func ListTrackedTimesByUser(ctx *context.APIContext) {
|
|||
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes))
|
||||
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, ctx.Doer, trackedTimes))
|
||||
}
|
||||
|
||||
// ListTrackedTimesByRepository lists all tracked times of the repository
|
||||
|
@ -567,7 +567,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
ctx.SetTotalCountHeader(count)
|
||||
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes))
|
||||
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, ctx.Doer, trackedTimes))
|
||||
}
|
||||
|
||||
// ListMyTrackedTimes lists all tracked times of the current user
|
||||
|
@ -629,5 +629,5 @@ func ListMyTrackedTimes(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
ctx.SetTotalCountHeader(count)
|
||||
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes))
|
||||
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, ctx.Doer, trackedTimes))
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ func GenerateActionsRunnerToken(ctx *context.PrivateContext) {
|
|||
defer rd.Close()
|
||||
|
||||
if err := json.NewDecoder(rd).Decode(&genRequest); err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("JSON Decode failed: %v", err)
|
||||
ctx.JSON(http.StatusInternalServerError, private.Response{
|
||||
Err: err.Error(),
|
||||
})
|
||||
|
@ -36,7 +36,7 @@ func GenerateActionsRunnerToken(ctx *context.PrivateContext) {
|
|||
|
||||
owner, repo, err := parseScope(ctx, genRequest.Scope)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("parseScope failed: %v", err)
|
||||
ctx.JSON(http.StatusInternalServerError, private.Response{
|
||||
Err: err.Error(),
|
||||
})
|
||||
|
@ -46,18 +46,18 @@ func GenerateActionsRunnerToken(ctx *context.PrivateContext) {
|
|||
if errors.Is(err, util.ErrNotExist) || (token != nil && !token.IsActive) {
|
||||
token, err = actions_model.NewRunnerToken(ctx, owner, repo)
|
||||
if err != nil {
|
||||
err := fmt.Sprintf("error while creating runner token: %v", err)
|
||||
log.Error("%v", err)
|
||||
errMsg := fmt.Sprintf("error while creating runner token: %v", err)
|
||||
log.Error("NewRunnerToken failed: %v", errMsg)
|
||||
ctx.JSON(http.StatusInternalServerError, private.Response{
|
||||
Err: err,
|
||||
Err: errMsg,
|
||||
})
|
||||
return
|
||||
}
|
||||
} else if err != nil {
|
||||
err := fmt.Sprintf("could not get unactivated runner token: %v", err)
|
||||
log.Error("%v", err)
|
||||
errMsg := fmt.Sprintf("could not get unactivated runner token: %v", err)
|
||||
log.Error("GetLatestRunnerToken failed: %v", errMsg)
|
||||
ctx.JSON(http.StatusInternalServerError, private.Response{
|
||||
Err: err,
|
||||
Err: errMsg,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env []
|
|||
_ = stdoutWriter.Close()
|
||||
err := readAndVerifyCommitsFromShaReader(stdoutReader, repo, env)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("readAndVerifyCommitsFromShaReader failed: %v", err)
|
||||
cancel()
|
||||
}
|
||||
_ = stdoutReader.Close()
|
||||
|
@ -66,7 +66,6 @@ func readAndVerifyCommitsFromShaReader(input io.ReadCloser, repo *git.Repository
|
|||
line := scanner.Text()
|
||||
err := readAndVerifyCommit(line, repo, env)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ func SendEmail(ctx *context.PrivateContext) {
|
|||
defer rd.Close()
|
||||
|
||||
if err := json.NewDecoder(rd).Decode(&mail); err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("JSON Decode failed: %v", err)
|
||||
ctx.JSON(http.StatusInternalServerError, private.Response{
|
||||
Err: err.Error(),
|
||||
})
|
||||
|
|
|
@ -403,7 +403,6 @@ func EditUserPost(ctx *context.Context) {
|
|||
ctx.Data["Err_Password"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("auth.password_pwned"), tplUserEdit, &form)
|
||||
case password.IsErrIsPwnedRequest(err):
|
||||
log.Error("%s", err.Error())
|
||||
ctx.Data["Err_Password"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("auth.password_pwned_err"), tplUserEdit, &form)
|
||||
default:
|
||||
|
|
|
@ -214,7 +214,6 @@ func ResetPasswdPost(ctx *context.Context) {
|
|||
case errors.Is(err, password.ErrIsPwned):
|
||||
ctx.RenderWithErr(ctx.Tr("auth.password_pwned"), tplResetPassword, nil)
|
||||
case password.IsErrIsPwnedRequest(err):
|
||||
log.Error("%s", err.Error())
|
||||
ctx.RenderWithErr(ctx.Tr("auth.password_pwned_err"), tplResetPassword, nil)
|
||||
default:
|
||||
ctx.ServerError("UpdateAuth", err)
|
||||
|
@ -298,7 +297,6 @@ func MustChangePasswordPost(ctx *context.Context) {
|
|||
ctx.Data["Err_Password"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("auth.password_pwned"), tplMustChangePassword, &form)
|
||||
case password.IsErrIsPwnedRequest(err):
|
||||
log.Error("%s", err.Error())
|
||||
ctx.Data["Err_Password"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("auth.password_pwned_err"), tplMustChangePassword, &form)
|
||||
default:
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -195,14 +194,15 @@ func NewProjectPost(ctx *context.Context) {
|
|||
|
||||
// ChangeProjectStatus updates the status of a project between "open" and "close"
|
||||
func ChangeProjectStatus(ctx *context.Context) {
|
||||
toClose := false
|
||||
var toClose bool
|
||||
switch ctx.Params(":action") {
|
||||
case "open":
|
||||
toClose = false
|
||||
case "close":
|
||||
toClose = true
|
||||
default:
|
||||
ctx.Redirect(ctx.ContextUser.HomeLink() + "/-/projects")
|
||||
ctx.JSONRedirect(ctx.ContextUser.HomeLink() + "/-/projects")
|
||||
return
|
||||
}
|
||||
id := ctx.ParamsInt64(":id")
|
||||
|
||||
|
@ -210,7 +210,7 @@ func ChangeProjectStatus(ctx *context.Context) {
|
|||
ctx.NotFoundOrServerError("ChangeProjectStatusByRepoIDAndID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
ctx.Redirect(ctx.ContextUser.HomeLink() + "/-/projects?state=" + url.QueryEscape(ctx.Params(":action")))
|
||||
ctx.JSONRedirect(fmt.Sprintf("%s/-/projects/%d", ctx.ContextUser.HomeLink(), id))
|
||||
}
|
||||
|
||||
// DeleteProject delete a project
|
||||
|
|
|
@ -2174,7 +2174,7 @@ func GetIssueInfo(ctx *context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, convert.ToIssue(ctx, issue))
|
||||
ctx.JSON(http.StatusOK, convert.ToIssue(ctx, ctx.Doer, issue))
|
||||
}
|
||||
|
||||
// UpdateIssueTitle change issue's title
|
||||
|
@ -2708,7 +2708,7 @@ func SearchIssues(ctx *context.Context) {
|
|||
}
|
||||
|
||||
ctx.SetTotalCountHeader(total)
|
||||
ctx.JSON(http.StatusOK, convert.ToIssueList(ctx, issues))
|
||||
ctx.JSON(http.StatusOK, convert.ToIssueList(ctx, ctx.Doer, issues))
|
||||
}
|
||||
|
||||
func getUserIDForFilter(ctx *context.Context, queryName string) int64 {
|
||||
|
@ -2878,7 +2878,7 @@ func ListIssues(ctx *context.Context) {
|
|||
}
|
||||
|
||||
ctx.SetTotalCountHeader(total)
|
||||
ctx.JSON(http.StatusOK, convert.ToIssueList(ctx, issues))
|
||||
ctx.JSON(http.StatusOK, convert.ToIssueList(ctx, ctx.Doer, issues))
|
||||
}
|
||||
|
||||
func BatchDeleteIssues(ctx *context.Context) {
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
|
@ -180,14 +179,10 @@ func ChangeProjectStatus(ctx *context.Context) {
|
|||
id := ctx.ParamsInt64(":id")
|
||||
|
||||
if err := project_model.ChangeProjectStatusByRepoIDAndID(ctx, ctx.Repo.Repository.ID, id, toClose); err != nil {
|
||||
if project_model.IsErrProjectNotExist(err) {
|
||||
ctx.NotFound("", err)
|
||||
} else {
|
||||
ctx.ServerError("ChangeProjectStatusByIDAndRepoID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("ChangeProjectStatusByRepoIDAndID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
ctx.JSONRedirect(ctx.Repo.RepoLink + "/projects?state=" + url.QueryEscape(ctx.Params(":action")))
|
||||
ctx.JSONRedirect(fmt.Sprintf("%s/projects/%d", ctx.Repo.RepoLink, id))
|
||||
}
|
||||
|
||||
// DeleteProject delete a project
|
||||
|
|
|
@ -376,7 +376,7 @@ func Action(ctx *context.Context) {
|
|||
}
|
||||
|
||||
if redirectViaJSON {
|
||||
ctx.JSON(http.StatusOK, map[string]interface{}{
|
||||
ctx.JSON(http.StatusOK, map[string]any{
|
||||
"redirect": ctx.ContextUser.HomeLink(),
|
||||
})
|
||||
return
|
||||
|
|
|
@ -74,7 +74,6 @@ func AccountPost(ctx *context.Context) {
|
|||
case errors.Is(err, password.ErrIsPwned):
|
||||
ctx.Flash.Error(ctx.Tr("auth.password_pwned"))
|
||||
case password.IsErrIsPwnedRequest(err):
|
||||
log.Error("%s", err.Error())
|
||||
ctx.Flash.Error(ctx.Tr("auth.password_pwned_err"))
|
||||
default:
|
||||
ctx.ServerError("UpdateAuth", err)
|
||||
|
|
|
@ -20,7 +20,7 @@ func TestCreateAuthorizationToken(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, "", token)
|
||||
claims := jwt.MapClaims{}
|
||||
_, err = jwt.ParseWithClaims(token, claims, func(t *jwt.Token) (interface{}, error) {
|
||||
_, err = jwt.ParseWithClaims(token, claims, func(t *jwt.Token) (any, error) {
|
||||
return setting.GetGeneralTokenSigningSecret(), nil
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
|
|
@ -49,7 +49,7 @@ func (n *actionsNotifier) NewIssue(ctx context.Context, issue *issues_model.Issu
|
|||
newNotifyInputFromIssue(issue, webhook_module.HookEventIssues).WithPayload(&api.IssuePayload{
|
||||
Action: api.HookIssueOpened,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, issue.Poster, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, issue.Poster, nil),
|
||||
}).Notify(withMethod(ctx, "NewIssue"))
|
||||
|
@ -89,7 +89,7 @@ func (n *actionsNotifier) IssueChangeContent(ctx context.Context, doer *user_mod
|
|||
WithPayload(&api.IssuePayload{
|
||||
Action: api.HookIssueEdited,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
}).
|
||||
|
@ -127,7 +127,7 @@ func (n *actionsNotifier) IssueChangeStatus(ctx context.Context, doer *user_mode
|
|||
}
|
||||
apiIssue := &api.IssuePayload{
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ func notifyIssueChange(ctx context.Context, doer *user_model.User, issue *issues
|
|||
WithPayload(&api.IssuePayload{
|
||||
Action: action,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
}).
|
||||
|
@ -293,7 +293,7 @@ func notifyIssueCommentChange(ctx context.Context, doer *user_model.User, commen
|
|||
|
||||
payload := &api.IssueCommentPayload{
|
||||
Action: action,
|
||||
Issue: convert.ToAPIIssue(ctx, comment.Issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, comment.Issue),
|
||||
Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment),
|
||||
Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
|
|
|
@ -560,12 +560,9 @@ func DetectAndHandleSchedules(ctx context.Context, repo *repo_model.Repository)
|
|||
}
|
||||
|
||||
// We need a notifyInput to call handleSchedules
|
||||
// Here we use the commit author as the Doer of the notifyInput
|
||||
commitUser, err := user_model.GetUserByEmail(ctx, commit.Author.Email)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get user by email: %w", err)
|
||||
}
|
||||
notifyInput := newNotifyInput(repo, commitUser, webhook_module.HookEventSchedule)
|
||||
// if repo is a mirror, commit author maybe an external user,
|
||||
// so we use action user as the Doer of the notifyInput
|
||||
notifyInput := newNotifyInput(repo, user_model.NewActionsUser(), webhook_module.HookEventSchedule)
|
||||
|
||||
return handleSchedules(ctx, scheduleWorkflows, commit, notifyInput, repo.DefaultBranch)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
session_module "code.gitea.io/gitea/modules/session"
|
||||
|
||||
chiSession "gitea.com/go-chi/session"
|
||||
"github.com/gorilla/sessions"
|
||||
|
@ -65,7 +66,7 @@ func (st *SessionsStore) Save(r *http.Request, w http.ResponseWriter, session *s
|
|||
chiStore := chiSession.GetSession(r)
|
||||
|
||||
if session.IsNew {
|
||||
_, _ = chiSession.RegenerateSession(w, r)
|
||||
_, _ = session_module.RegenerateSession(w, r)
|
||||
session.IsNew = false
|
||||
}
|
||||
|
||||
|
|
|
@ -79,11 +79,11 @@ func VerifyCaptcha(ctx *Context, tpl base.TplName, form any) {
|
|||
case setting.CfTurnstile:
|
||||
valid, err = turnstile.Verify(ctx, ctx.Req.Form.Get(cfTurnstileResponseField))
|
||||
default:
|
||||
ctx.ServerError("Unknown Captcha Type", fmt.Errorf("Unknown Captcha Type: %s", setting.Service.CaptchaType))
|
||||
ctx.ServerError("Unknown Captcha Type", fmt.Errorf("unknown Captcha Type: %s", setting.Service.CaptchaType))
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
log.Debug("%v", err)
|
||||
log.Debug("Captcha Verify failed: %v", err)
|
||||
}
|
||||
|
||||
if !valid {
|
||||
|
|
|
@ -18,19 +18,19 @@ import (
|
|||
api "code.gitea.io/gitea/modules/structs"
|
||||
)
|
||||
|
||||
func ToIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue {
|
||||
return toIssue(ctx, issue, WebAssetDownloadURL)
|
||||
func ToIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) *api.Issue {
|
||||
return toIssue(ctx, doer, issue, WebAssetDownloadURL)
|
||||
}
|
||||
|
||||
// ToAPIIssue converts an Issue to API format
|
||||
// it assumes some fields assigned with values:
|
||||
// Required - Poster, Labels,
|
||||
// Optional - Milestone, Assignee, PullRequest
|
||||
func ToAPIIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue {
|
||||
return toIssue(ctx, issue, APIAssetDownloadURL)
|
||||
func ToAPIIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) *api.Issue {
|
||||
return toIssue(ctx, doer, issue, APIAssetDownloadURL)
|
||||
}
|
||||
|
||||
func toIssue(ctx context.Context, issue *issues_model.Issue, getDownloadURL func(repo *repo_model.Repository, attach *repo_model.Attachment) string) *api.Issue {
|
||||
func toIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, getDownloadURL func(repo *repo_model.Repository, attach *repo_model.Attachment) string) *api.Issue {
|
||||
if err := issue.LoadLabels(ctx); err != nil {
|
||||
return &api.Issue{}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ func toIssue(ctx context.Context, issue *issues_model.Issue, getDownloadURL func
|
|||
apiIssue := &api.Issue{
|
||||
ID: issue.ID,
|
||||
Index: issue.Index,
|
||||
Poster: ToUser(ctx, issue.Poster, nil),
|
||||
Poster: ToUser(ctx, issue.Poster, doer),
|
||||
Title: issue.Title,
|
||||
Body: issue.Content,
|
||||
Attachments: toAttachments(issue.Repo, issue.Attachments, getDownloadURL),
|
||||
|
@ -114,25 +114,25 @@ func toIssue(ctx context.Context, issue *issues_model.Issue, getDownloadURL func
|
|||
}
|
||||
|
||||
// ToIssueList converts an IssueList to API format
|
||||
func ToIssueList(ctx context.Context, il issues_model.IssueList) []*api.Issue {
|
||||
func ToIssueList(ctx context.Context, doer *user_model.User, il issues_model.IssueList) []*api.Issue {
|
||||
result := make([]*api.Issue, len(il))
|
||||
for i := range il {
|
||||
result[i] = ToIssue(ctx, il[i])
|
||||
result[i] = ToIssue(ctx, doer, il[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ToAPIIssueList converts an IssueList to API format
|
||||
func ToAPIIssueList(ctx context.Context, il issues_model.IssueList) []*api.Issue {
|
||||
func ToAPIIssueList(ctx context.Context, doer *user_model.User, il issues_model.IssueList) []*api.Issue {
|
||||
result := make([]*api.Issue, len(il))
|
||||
for i := range il {
|
||||
result[i] = ToAPIIssue(ctx, il[i])
|
||||
result[i] = ToAPIIssue(ctx, doer, il[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ToTrackedTime converts TrackedTime to API format
|
||||
func ToTrackedTime(ctx context.Context, t *issues_model.TrackedTime) (apiT *api.TrackedTime) {
|
||||
func ToTrackedTime(ctx context.Context, doer *user_model.User, t *issues_model.TrackedTime) (apiT *api.TrackedTime) {
|
||||
apiT = &api.TrackedTime{
|
||||
ID: t.ID,
|
||||
IssueID: t.IssueID,
|
||||
|
@ -141,7 +141,7 @@ func ToTrackedTime(ctx context.Context, t *issues_model.TrackedTime) (apiT *api.
|
|||
Created: t.Created,
|
||||
}
|
||||
if t.Issue != nil {
|
||||
apiT.Issue = ToAPIIssue(ctx, t.Issue)
|
||||
apiT.Issue = ToAPIIssue(ctx, doer, t.Issue)
|
||||
}
|
||||
if t.User != nil {
|
||||
apiT.UserName = t.User.Name
|
||||
|
@ -192,10 +192,10 @@ func ToStopWatches(ctx context.Context, sws []*issues_model.Stopwatch) (api.Stop
|
|||
}
|
||||
|
||||
// ToTrackedTimeList converts TrackedTimeList to API format
|
||||
func ToTrackedTimeList(ctx context.Context, tl issues_model.TrackedTimeList) api.TrackedTimeList {
|
||||
func ToTrackedTimeList(ctx context.Context, doer *user_model.User, tl issues_model.TrackedTimeList) api.TrackedTimeList {
|
||||
result := make([]*api.TrackedTime, 0, len(tl))
|
||||
for _, t := range tl {
|
||||
result = append(result, ToTrackedTime(ctx, t))
|
||||
result = append(result, ToTrackedTime(ctx, doer, t))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu
|
|||
return nil
|
||||
}
|
||||
|
||||
comment.TrackedTime = ToTrackedTime(ctx, c.Time)
|
||||
comment.TrackedTime = ToTrackedTime(ctx, doer, c.Time)
|
||||
}
|
||||
|
||||
if c.RefIssueID != 0 {
|
||||
|
@ -129,7 +129,7 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu
|
|||
log.Error("GetIssueByID(%d): %v", c.RefIssueID, err)
|
||||
return nil
|
||||
}
|
||||
comment.RefIssue = ToAPIIssue(ctx, issue)
|
||||
comment.RefIssue = ToAPIIssue(ctx, doer, issue)
|
||||
}
|
||||
|
||||
if c.RefCommentID != 0 {
|
||||
|
@ -180,7 +180,7 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu
|
|||
}
|
||||
|
||||
if c.DependentIssue != nil {
|
||||
comment.DependentIssue = ToAPIIssue(ctx, c.DependentIssue)
|
||||
comment.DependentIssue = ToAPIIssue(ctx, doer, c.DependentIssue)
|
||||
}
|
||||
|
||||
return comment
|
||||
|
|
|
@ -33,7 +33,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u
|
|||
return nil
|
||||
}
|
||||
|
||||
apiIssue := ToAPIIssue(ctx, pr.Issue)
|
||||
apiIssue := ToAPIIssue(ctx, doer, pr.Issue)
|
||||
if err := pr.LoadBaseRepo(ctx); err != nil {
|
||||
log.Error("GetRepositoryById[%d]: %v", pr.ID, err)
|
||||
return nil
|
||||
|
|
|
@ -72,6 +72,11 @@ func (g *GitBucketDownloader) LogString() string {
|
|||
// NewGitBucketDownloader creates a GitBucket downloader
|
||||
func NewGitBucketDownloader(ctx context.Context, baseURL, userName, password, token, repoOwner, repoName string) *GitBucketDownloader {
|
||||
githubDownloader := NewGithubDownloaderV3(ctx, baseURL, userName, password, token, repoOwner, repoName)
|
||||
// Gitbucket 4.40 uses different internal hard-coded perPage values.
|
||||
// Issues, PRs, and other major parts use 25. Release page uses 10.
|
||||
// Some API doesn't support paging yet. Sounds difficult, but using
|
||||
// minimum number among them worked out very well.
|
||||
githubDownloader.maxPerPage = 10
|
||||
githubDownloader.SkipReactions = true
|
||||
githubDownloader.SkipReviews = true
|
||||
return &GitBucketDownloader{
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
system_model "code.gitea.io/gitea/models/system"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
giturl "code.gitea.io/gitea/modules/git/url"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/lfs"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
@ -30,10 +31,15 @@ const gitShortEmptySha = "0000000"
|
|||
|
||||
// UpdateAddress writes new address to Git repository and database
|
||||
func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error {
|
||||
u, err := giturl.Parse(addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid addr: %v", err)
|
||||
}
|
||||
|
||||
remoteName := m.GetRemoteName()
|
||||
repoPath := m.GetRepository(ctx).RepoPath()
|
||||
// Remove old remote
|
||||
_, _, err := git.NewCommand(ctx, "remote", "rm").AddDynamicArguments(remoteName).RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
_, _, err = git.NewCommand(ctx, "remote", "rm").AddDynamicArguments(remoteName).RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
||||
return err
|
||||
}
|
||||
|
@ -70,7 +76,9 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error
|
|||
}
|
||||
}
|
||||
|
||||
m.Repo.OriginalURL = addr
|
||||
// erase authentication before storing in database
|
||||
u.User = nil
|
||||
m.Repo.OriginalURL = u.String()
|
||||
return repo_model.UpdateRepositoryCols(ctx, m.Repo, "original_url")
|
||||
}
|
||||
|
||||
|
@ -449,19 +457,17 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
var gitRepo *git.Repository
|
||||
if len(results) == 0 {
|
||||
log.Trace("SyncMirrors [repo: %-v]: no branches updated", m.Repo)
|
||||
} else {
|
||||
log.Trace("SyncMirrors [repo: %-v]: %d branches updated", m.Repo, len(results))
|
||||
gitRepo, err = gitrepo.OpenRepository(ctx, m.Repo)
|
||||
if err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to OpenRepository: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
defer gitRepo.Close()
|
||||
gitRepo, err := gitrepo.OpenRepository(ctx, m.Repo)
|
||||
if err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to OpenRepository: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
defer gitRepo.Close()
|
||||
|
||||
log.Trace("SyncMirrors [repo: %-v]: %d branches updated", m.Repo, len(results))
|
||||
if len(results) > 0 {
|
||||
if ok := checkAndUpdateEmptyRepository(ctx, m, gitRepo, results); !ok {
|
||||
log.Error("SyncMirrors [repo: %-v]: checkAndUpdateEmptyRepository: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -534,16 +540,24 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool {
|
|||
}
|
||||
log.Trace("SyncMirrors [repo: %-v]: done notifying updated branches/tags - now updating last commit time", m.Repo)
|
||||
|
||||
// Get latest commit date and update to current repository updated time
|
||||
commitDate, err := git.GetLatestCommitTime(ctx, m.Repo.RepoPath())
|
||||
isEmpty, err := gitRepo.IsEmpty()
|
||||
if err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to GetLatestCommitDate: %v", m.Repo, err)
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to check empty git repo: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
if !isEmpty {
|
||||
// Get latest commit date and update to current repository updated time
|
||||
commitDate, err := git.GetLatestCommitTime(ctx, m.Repo.RepoPath())
|
||||
if err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to GetLatestCommitDate: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if err = repo_model.UpdateRepositoryUpdatedTime(ctx, m.RepoID, commitDate); err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to update repository 'updated_unix': %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if err = repo_model.UpdateRepositoryUpdatedTime(ctx, m.RepoID, commitDate); err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to update repository 'updated_unix': %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
|
||||
log.Trace("SyncMirrors [repo: %-v]: Successfully updated", m.Repo)
|
||||
|
|
|
@ -91,7 +91,7 @@ func AutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues
|
|||
// NewPullRequest notifies new pull request to notifiers
|
||||
func NewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) {
|
||||
if err := pr.LoadIssue(ctx); err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("LoadIssue failed: %v", err)
|
||||
return
|
||||
}
|
||||
if err := pr.Issue.LoadPoster(ctx); err != nil {
|
||||
|
@ -112,7 +112,7 @@ func PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *iss
|
|||
// PullRequestReview notifies new pull request review
|
||||
func PullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) {
|
||||
if err := review.LoadReviewer(ctx); err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("LoadReviewer failed: %v", err)
|
||||
return
|
||||
}
|
||||
for _, notifier := range notifiers {
|
||||
|
|
|
@ -28,7 +28,7 @@ func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_mod
|
|||
|
||||
t, err := NewTemporaryUploadRepository(ctx, repo)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("NewTemporaryUploadRepository failed: %v", err)
|
||||
}
|
||||
defer t.Close()
|
||||
if err := t.Clone(opts.OldBranch, false); err != nil {
|
||||
|
|
|
@ -111,7 +111,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user
|
|||
|
||||
t, err := NewTemporaryUploadRepository(ctx, repo)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("NewTemporaryUploadRepository failed: %v", err)
|
||||
}
|
||||
defer t.Close()
|
||||
if err := t.Clone(opts.OldBranch, true); err != nil {
|
||||
|
|
|
@ -143,7 +143,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
|
|||
|
||||
t, err := NewTemporaryUploadRepository(ctx, repo)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("NewTemporaryUploadRepository failed: %v", err)
|
||||
}
|
||||
defer t.Close()
|
||||
hasOldBranch := true
|
||||
|
|
|
@ -67,7 +67,7 @@ func (m *webhookNotifier) IssueClearLabels(ctx context.Context, doer *user_model
|
|||
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{
|
||||
Action: api.HookIssueLabelCleared,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
})
|
||||
|
@ -168,7 +168,7 @@ func (m *webhookNotifier) IssueChangeAssignee(ctx context.Context, doer *user_mo
|
|||
permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
|
||||
apiIssue := &api.IssuePayload{
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ func (m *webhookNotifier) IssueChangeTitle(ctx context.Context, doer *user_model
|
|||
From: oldTitle,
|
||||
},
|
||||
},
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
})
|
||||
|
@ -250,7 +250,7 @@ func (m *webhookNotifier) IssueChangeStatus(ctx context.Context, doer *user_mode
|
|||
} else {
|
||||
apiIssue := &api.IssuePayload{
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
CommitID: commitID,
|
||||
|
@ -281,7 +281,7 @@ func (m *webhookNotifier) NewIssue(ctx context.Context, issue *issues_model.Issu
|
|||
if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{
|
||||
Action: api.HookIssueOpened,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, issue.Poster, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, issue.Poster, nil),
|
||||
}); err != nil {
|
||||
|
@ -349,7 +349,7 @@ func (m *webhookNotifier) IssueChangeContent(ctx context.Context, doer *user_mod
|
|||
From: oldContent,
|
||||
},
|
||||
},
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
})
|
||||
|
@ -384,7 +384,7 @@ func (m *webhookNotifier) UpdateComment(ctx context.Context, doer *user_model.Us
|
|||
permission, _ := access_model.GetUserRepoPermission(ctx, c.Issue.Repo, doer)
|
||||
if err := PrepareWebhooks(ctx, EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{
|
||||
Action: api.HookIssueCommentEdited,
|
||||
Issue: convert.ToAPIIssue(ctx, c.Issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, c.Issue),
|
||||
Comment: convert.ToAPIComment(ctx, c.Issue.Repo, c),
|
||||
Changes: &api.ChangesPayload{
|
||||
Body: &api.ChangesFromPayload{
|
||||
|
@ -412,7 +412,7 @@ func (m *webhookNotifier) CreateIssueComment(ctx context.Context, doer *user_mod
|
|||
permission, _ := access_model.GetUserRepoPermission(ctx, repo, doer)
|
||||
if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{
|
||||
Action: api.HookIssueCommentCreated,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Comment: convert.ToAPIComment(ctx, repo, comment),
|
||||
Repository: convert.ToRepo(ctx, repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
|
@ -449,7 +449,7 @@ func (m *webhookNotifier) DeleteComment(ctx context.Context, doer *user_model.Us
|
|||
permission, _ := access_model.GetUserRepoPermission(ctx, comment.Issue.Repo, doer)
|
||||
if err := PrepareWebhooks(ctx, EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{
|
||||
Action: api.HookIssueCommentDeleted,
|
||||
Issue: convert.ToAPIIssue(ctx, comment.Issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, comment.Issue),
|
||||
Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment),
|
||||
Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
|
@ -533,7 +533,7 @@ func (m *webhookNotifier) IssueChangeLabels(ctx context.Context, doer *user_mode
|
|||
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{
|
||||
Action: api.HookIssueLabelUpdated,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
})
|
||||
|
@ -575,7 +575,7 @@ func (m *webhookNotifier) IssueChangeMilestone(ctx context.Context, doer *user_m
|
|||
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueMilestone, &api.IssuePayload{
|
||||
Action: hookAction,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
})
|
||||
|
|
|
@ -209,7 +209,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
|||
if isOldWikiExist {
|
||||
err := gitRepo.RemoveFilesFromIndex(oldWikiPath)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("RemoveFilesFromIndex failed: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -219,18 +219,18 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
|||
|
||||
objectHash, err := gitRepo.HashObject(strings.NewReader(content))
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("HashObject failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := gitRepo.AddObjectToIndex("100644", objectHash, newWikiPath); err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("AddObjectToIndex failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
tree, err := gitRepo.WriteTree()
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("WriteTree failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -255,7 +255,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
|||
|
||||
commitHash, err := gitRepo.CommitTree(doer.NewGitSig(), committer, tree, commitTreeOpts)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("CommitTree failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -270,11 +270,11 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
|||
0,
|
||||
),
|
||||
}); err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("Push failed: %v", err)
|
||||
if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("Push: %w", err)
|
||||
return fmt.Errorf("failed to push: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -62,10 +62,7 @@
|
|||
|
||||
<div class="ui modal admin" id="detail-modal">
|
||||
<div class="header">{{ctx.Locale.Tr "admin.notices.view_detail_header"}}</div>
|
||||
<div class="content">
|
||||
<div class="sub header"></div>
|
||||
<pre></pre>
|
||||
</div>
|
||||
<div class="content"><pre></pre></div>
|
||||
</div>
|
||||
|
||||
{{template "admin/layout_footer" .}}
|
||||
|
|
|
@ -13,11 +13,9 @@
|
|||
<div class="ui four wide column">
|
||||
{{template "shared/user/profile_big_avatar" .}}
|
||||
</div>
|
||||
<div class="ui twelve wide column">
|
||||
<div class="tw-mb-4">
|
||||
<div class="ui twelve wide column tw-mb-4">
|
||||
{{template "user/overview/header" .}}
|
||||
</div>
|
||||
{{template "projects/list" .}}
|
||||
{{template "projects/list" .}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{template "base/head" .}}
|
||||
<div role="main" aria-label="{{.Title}}" class="page-content repository projects view-project">
|
||||
{{template "shared/user/org_profile_avatar" .}}
|
||||
<div class="ui container">
|
||||
<div class="ui container tw-mb-4">
|
||||
{{template "user/overview/header" .}}
|
||||
</div>
|
||||
<div class="ui container fluid padded">
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
{{end}}
|
||||
{{end}}
|
||||
<div class="ui top attached header clearing segment tw-relative commit-header {{$class}}">
|
||||
<div class="tw-flex tw-mb-4 tw-flex-wrap">
|
||||
<div class="tw-flex tw-mb-4 tw-gap-1">
|
||||
<h3 class="tw-mb-0 tw-flex-1"><span class="commit-summary" title="{{.Commit.Summary}}">{{RenderCommitMessage $.Context .Commit.Message ($.Repository.ComposeMetas ctx)}}</span>{{template "repo/commit_statuses" dict "Status" .CommitStatus "Statuses" .CommitStatuses}}</h3>
|
||||
{{if not $.PageIsWiki}}
|
||||
<div>
|
||||
<div class="commit-header-buttons">
|
||||
<a class="ui primary tiny button" href="{{.SourcePath}}">
|
||||
{{ctx.Locale.Tr "repo.diff.browse_source"}}
|
||||
</a>
|
||||
|
|
|
@ -111,7 +111,7 @@
|
|||
{{$isReviewFile := and $.IsSigned $.PageIsPullFiles (not $.IsArchived) $.IsShowingAllCommits}}
|
||||
<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}} tw-mt-0" id="diff-{{$file.NameHash}}" data-old-filename="{{$file.OldName}}" data-new-filename="{{$file.Name}}" {{if or ($file.ShouldBeHidden) (not $isExpandable)}}data-folded="true"{{end}}>
|
||||
<h4 class="diff-file-header sticky-2nd-row ui top attached header tw-font-normal tw-flex tw-items-center tw-justify-between tw-flex-wrap">
|
||||
<div class="diff-file-name tw-flex tw-items-center gt-gap-2 tw-flex-wrap">
|
||||
<div class="diff-file-name tw-flex tw-flex-1 tw-items-center tw-gap-1 tw-flex-wrap">
|
||||
<button class="fold-file btn interact-bg tw-p-1{{if not $isExpandable}} tw-invisible{{end}}">
|
||||
{{if $file.ShouldBeHidden}}
|
||||
{{svg "octicon-chevron-right" 18}}
|
||||
|
@ -128,21 +128,23 @@
|
|||
{{template "repo/diff/stats" dict "file" . "root" $}}
|
||||
{{end}}
|
||||
</div>
|
||||
<span class="file tw-font-mono"><a class="muted file-link" title="{{if $file.IsRenamed}}{{$file.OldName}} → {{end}}{{$file.Name}}" href="#diff-{{$file.NameHash}}">{{if $file.IsRenamed}}{{$file.OldName}} → {{end}}{{$file.Name}}</a>{{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}}</span>
|
||||
<button class="btn interact-fg tw-p-2" data-clipboard-text="{{$file.Name}}">{{svg "octicon-copy" 14}}</button>
|
||||
{{if $file.IsGenerated}}
|
||||
<span class="ui label">{{ctx.Locale.Tr "repo.diff.generated"}}</span>
|
||||
{{end}}
|
||||
{{if $file.IsVendored}}
|
||||
<span class="ui label">{{ctx.Locale.Tr "repo.diff.vendored"}}</span>
|
||||
{{end}}
|
||||
{{if and $file.Mode $file.OldMode}}
|
||||
{{$old := ctx.Locale.Tr ($file.ModeTranslationKey $file.OldMode)}}
|
||||
{{$new := ctx.Locale.Tr ($file.ModeTranslationKey $file.Mode)}}
|
||||
<span class="tw-ml-4 tw-font-mono">{{ctx.Locale.Tr "git.filemode.changed_filemode" $old $new}}</span>
|
||||
{{else if $file.Mode}}
|
||||
<span class="tw-ml-4 tw-font-mono">{{ctx.Locale.Tr ($file.ModeTranslationKey $file.Mode)}}</span>
|
||||
{{end}}
|
||||
<span class="file tw-flex tw-items-center tw-font-mono tw-flex-1"><a class="muted file-link" title="{{if $file.IsRenamed}}{{$file.OldName}} → {{end}}{{$file.Name}}" href="#diff-{{$file.NameHash}}">{{if $file.IsRenamed}}{{$file.OldName}} → {{end}}{{$file.Name}}</a>
|
||||
{{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}}
|
||||
<button class="btn interact-fg tw-p-2" data-clipboard-text="{{$file.Name}}">{{svg "octicon-copy" 14}}</button>
|
||||
{{if $file.IsGenerated}}
|
||||
<span class="ui label">{{ctx.Locale.Tr "repo.diff.generated"}}</span>
|
||||
{{end}}
|
||||
{{if $file.IsVendored}}
|
||||
<span class="ui label">{{ctx.Locale.Tr "repo.diff.vendored"}}</span>
|
||||
{{end}}
|
||||
{{if and $file.Mode $file.OldMode}}
|
||||
{{$old := ctx.Locale.Tr ($file.ModeTranslationKey $file.OldMode)}}
|
||||
{{$new := ctx.Locale.Tr ($file.ModeTranslationKey $file.Mode)}}
|
||||
<span class="tw-mx-2 tw-font-mono tw-whitespace-nowrap">{{ctx.Locale.Tr "git.filemode.changed_filemode" $old $new}}</span>
|
||||
{{else if $file.Mode}}
|
||||
<span class="tw-mx-2 tw-font-mono tw-whitespace-nowrap">{{ctx.Locale.Tr ($file.ModeTranslationKey $file.Mode)}}</span>
|
||||
{{end}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="diff-file-header-actions tw-flex tw-items-center tw-gap-1 tw-flex-wrap">
|
||||
{{if $showFileViewToggle}}
|
||||
|
|
|
@ -58,8 +58,11 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{template "repo/sub_menu" .}}
|
||||
{{$n := len .TreeNames}}
|
||||
{{$l := Eval $n "-" 1}}
|
||||
{{$isHomepage := (eq $n 0)}}
|
||||
<div class="repo-button-row">
|
||||
<div class="tw-flex tw-items-center tw-flex-wrap tw-gap-y-2">
|
||||
<div class="tw-flex tw-items-center tw-gap-y-2">
|
||||
{{template "repo/branch_dropdown" dict "root" . "ContainerClasses" "tw-mr-1"}}
|
||||
{{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
|
||||
{{$cmpBranch := ""}}
|
||||
|
@ -74,9 +77,7 @@
|
|||
</a>
|
||||
{{end}}
|
||||
<!-- Show go to file and breadcrumbs if not on home page -->
|
||||
{{$n := len .TreeNames}}
|
||||
{{$l := Eval $n "-" 1}}
|
||||
{{if eq $n 0}}
|
||||
{{if $isHomepage}}
|
||||
<a href="{{.Repository.Link}}/find/{{.BranchNameSubURL}}" class="ui compact basic button">{{ctx.Locale.Tr "repo.find_file.go_to_file"}}</a>
|
||||
{{end}}
|
||||
|
||||
|
@ -100,20 +101,20 @@
|
|||
</button>
|
||||
{{end}}
|
||||
|
||||
{{if and (eq $n 0) (.Repository.IsTemplate)}}
|
||||
{{if and $isHomepage (.Repository.IsTemplate)}}
|
||||
<a role="button" class="ui primary compact button" href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}">
|
||||
{{ctx.Locale.Tr "repo.use_template"}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if ne $n 0}}
|
||||
{{if (not $isHomepage)}}
|
||||
<span class="breadcrumb repo-path tw-ml-1">
|
||||
<a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{StringUtils.EllipsisString .Repository.Name 30}}</a>
|
||||
{{- range $i, $v := .TreeNames -}}
|
||||
<span class="breadcrumb-divider">/</span>
|
||||
{{- if eq $i $l -}}
|
||||
<span class="active section" title="{{$v}}">{{StringUtils.EllipsisString $v 30}}</span>
|
||||
<span class="active section" title="{{$v}}">{{$v}}</span>
|
||||
{{- else -}}
|
||||
{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{StringUtils.EllipsisString $v 30}}</a></span>
|
||||
{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{$v}}</a></span>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
</span>
|
||||
|
@ -121,7 +122,7 @@
|
|||
</div>
|
||||
<div class="tw-flex tw-items-center">
|
||||
<!-- Only show clone panel in repository home page -->
|
||||
{{if eq $n 0}}
|
||||
{{if $isHomepage}}
|
||||
<div class="clone-panel ui action tiny input">
|
||||
{{template "repo/clone_buttons" .}}
|
||||
<button class="ui small jump dropdown icon button" data-tooltip-content="{{ctx.Locale.Tr "repo.more_operations"}}">
|
||||
|
@ -144,7 +145,7 @@
|
|||
</div>
|
||||
{{template "repo/cite/cite_modal" .}}
|
||||
{{end}}
|
||||
{{if and (ne $n 0) (not .IsViewFile) (not .IsBlame)}}
|
||||
{{if and (not $isHomepage) (not .IsViewFile) (not .IsBlame)}}
|
||||
<a class="ui button" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}">
|
||||
{{svg "octicon-history" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.file_history"}}
|
||||
</a>
|
||||
|
|
|
@ -156,7 +156,7 @@
|
|||
<label for="interval">{{ctx.Locale.Tr "repo.mirror_interval" .MinimumMirrorInterval}}</label>
|
||||
<input id="interval" name="interval" value="{{.PullMirror.Interval}}">
|
||||
</div>
|
||||
{{$address := MirrorRemoteAddress $.Context .Repository .PullMirror.GetRemoteName false}}
|
||||
{{$address := MirrorRemoteAddress $.Context .Repository .PullMirror.GetRemoteName}}
|
||||
<div class="field {{if .Err_MirrorAddress}}error{{end}}">
|
||||
<label for="mirror_address">{{ctx.Locale.Tr "repo.mirror_address"}}</label>
|
||||
<input id="mirror_address" name="mirror_address" value="{{$address.Address}}" required>
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
{{end}}
|
||||
|
||||
{{if not .ReadmeInList}}
|
||||
<div id="repo-file-commit-box" class="ui top attached header list-header tw-mb-4">
|
||||
<div>
|
||||
<div id="repo-file-commit-box" class="ui top attached header list-header tw-mb-4 tw-flex tw-justify-between">
|
||||
<div class="latest-commit">
|
||||
{{template "repo/latest_commit" .}}
|
||||
</div>
|
||||
{{if .LatestCommit}}
|
||||
{{if .LatestCommit.Committer}}
|
||||
<div class="ui text grey right age">
|
||||
<div class="text grey age">
|
||||
{{TimeSince .LatestCommit.Committer.When ctx.Locale}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
<table id="repo-files-table" class="ui single line table tw-mt-0" {{if .HasFilesWithoutLatestCommit}}hx-indicator="tr.notready td.message span" hx-trigger="load" hx-swap="morph" hx-post="{{.LastCommitLoaderURL}}"{{end}}>
|
||||
<thead>
|
||||
<tr class="commit-list">
|
||||
<th colspan="2">
|
||||
{{template "repo/latest_commit" .}}
|
||||
<th class="tw-overflow-hidden" colspan="2">
|
||||
<div class="tw-flex">
|
||||
<div class="latest-commit">
|
||||
{{template "repo/latest_commit" .}}
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th class="text grey right age">{{if .LatestCommit}}{{if .LatestCommit.Committer}}{{TimeSince .LatestCommit.Committer.When ctx.Locale}}{{end}}{{end}}</th>
|
||||
</tr>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div role="main" aria-label="{{.Title}}" class="page-content user notification" id="notification_div" data-sequence-number="{{.SequenceNumber}}">
|
||||
<div class="ui container">
|
||||
{{$notificationUnreadCount := call .NotificationUnreadCount}}
|
||||
<div class="tw-flex tw-items-center tw-justify-between tw-mb-4">
|
||||
<div class="tw-flex tw-items-center tw-justify-between tw-mb-[--page-spacing]">
|
||||
<div class="small-menu-items ui compact tiny menu">
|
||||
<a class="{{if eq .Status 1}}active {{end}}item" href="{{AppSubUrl}}/notifications?q=unread">
|
||||
{{ctx.Locale.Tr "notification.unread"}}
|
||||
|
|
|
@ -13,11 +13,9 @@
|
|||
<div class="ui four wide column">
|
||||
{{template "shared/user/profile_big_avatar" .}}
|
||||
</div>
|
||||
<div class="ui twelve wide column">
|
||||
<div class="tw-mb-4">
|
||||
<div class="ui twelve wide column tw-mb-4">
|
||||
{{template "user/overview/header" .}}
|
||||
</div>
|
||||
{{template "package/shared/versionlist" .}}
|
||||
{{template "package/shared/versionlist" .}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -13,11 +13,9 @@
|
|||
<div class="ui four wide column">
|
||||
{{template "shared/user/profile_big_avatar" .}}
|
||||
</div>
|
||||
<div class="ui twelve wide column">
|
||||
<div class="tw-mb-4">
|
||||
<div class="ui twelve wide column tw-mb-4">
|
||||
{{template "user/overview/header" .}}
|
||||
</div>
|
||||
{{template "package/shared/list" .}}
|
||||
{{template "package/shared/list" .}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -6,11 +6,8 @@
|
|||
<div class="ui four wide column">
|
||||
{{template "shared/user/profile_big_avatar" .}}
|
||||
</div>
|
||||
<div class="ui twelve wide column">
|
||||
<div class="tw-mb-4">
|
||||
{{template "user/overview/header" .}}
|
||||
</div>
|
||||
|
||||
<div class="ui twelve wide column tw-mb-4">
|
||||
{{template "user/overview/header" .}}
|
||||
{{if eq .TabName "activity"}}
|
||||
{{if .ContextUser.KeepActivityPrivate}}
|
||||
<div class="ui info message">
|
||||
|
|
|
@ -621,7 +621,7 @@ func VerifyJSONSchema(t testing.TB, resp *httptest.ResponseRecorder, schemaFile
|
|||
schema, err := jsonschema.Compile(schemaFilePath)
|
||||
assert.NoError(t, err)
|
||||
|
||||
var data interface{}
|
||||
var data any
|
||||
err = json.Unmarshal(resp.Body.Bytes(), &data)
|
||||
assert.NoError(t, err)
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
}
|
||||
|
||||
.run-list-item-right {
|
||||
flex: 0 0 15%;
|
||||
flex: 0 0 min(20%, 130px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
|
|
|
@ -24,7 +24,21 @@
|
|||
--repo-header-issue-min-height: 41px;
|
||||
--min-height-textarea: 132px; /* padding + 6 lines + border = calc(1.57142em + 6lh + 2px), but lh is not fully supported */
|
||||
--tab-size: 4;
|
||||
--checkbox-size: 16px; /* height and width of checkbox and radio inputs */
|
||||
--checkbox-size: 15px; /* height and width of checkbox and radio inputs */
|
||||
--page-spacing: 16px; /* space between page elements */
|
||||
--page-margin-x: 32px; /* minimum space on left and right side of page */
|
||||
}
|
||||
|
||||
@media (min-width: 768px) and (max-width: 1200px) {
|
||||
:root {
|
||||
--page-margin-x: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
:root {
|
||||
--page-margin-x: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
:root * {
|
||||
|
@ -594,11 +608,14 @@ img.ui.avatar,
|
|||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
/* add padding to all content when there is no .secondary.nav. this uses padding instead of
|
||||
margin because with the negative margin on .ui.grid we would have to set margin-top: 0,
|
||||
but that does not work universally for all pages */
|
||||
/* add margin to all pages when there is no .secondary.nav */
|
||||
.page-content > :first-child:not(.secondary-nav) {
|
||||
padding-top: 14px;
|
||||
margin-top: var(--page-spacing);
|
||||
}
|
||||
/* if .ui.grid is the first child the first grid-column has 'padding-top: 1rem' which we need
|
||||
to compensate here */
|
||||
.page-content > :first-child.ui.grid {
|
||||
margin-top: calc(var(--page-spacing) - 1rem);
|
||||
}
|
||||
|
||||
.ui.pagination.menu .active.item {
|
||||
|
@ -1256,6 +1273,7 @@ overflow-menu .ui.label {
|
|||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
overflow-wrap: anywhere;
|
||||
line-height: inherit; /* needed for inline code preview in markup */
|
||||
}
|
||||
|
||||
.blame .code-inner {
|
||||
|
|
|
@ -249,21 +249,6 @@ textarea:focus,
|
|||
.user.signup form .optional .title {
|
||||
margin-left: 250px !important;
|
||||
}
|
||||
.user.activate form .inline.field > input,
|
||||
.user.forgot.password form .inline.field > input,
|
||||
.user.reset.password form .inline.field > input,
|
||||
.user.link-account form .inline.field > input,
|
||||
.user.signin form .inline.field > input,
|
||||
.user.signup form .inline.field > input,
|
||||
.user.activate form .inline.field > textarea,
|
||||
.user.forgot.password form .inline.field > textarea,
|
||||
.user.reset.password form .inline.field > textarea,
|
||||
.user.link-account form .inline.field > textarea,
|
||||
.user.signin form .inline.field > textarea,
|
||||
.user.signup form .inline.field > textarea,
|
||||
.oauth-login-link {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
|
@ -310,14 +295,7 @@ textarea:focus,
|
|||
.user.reset.password form .inline.field > label,
|
||||
.user.link-account form .inline.field > label,
|
||||
.user.signin form .inline.field > label,
|
||||
.user.signup form .inline.field > label,
|
||||
.user.activate form input,
|
||||
.user.forgot.password form input,
|
||||
.user.reset.password form input,
|
||||
.user.link-account form input,
|
||||
.user.signin form input,
|
||||
.user.signup form input,
|
||||
.oauth-login-link {
|
||||
.user.signup form .inline.field > label {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
@ -435,9 +413,9 @@ textarea:focus,
|
|||
.repository.new.repo form label,
|
||||
.repository.new.migrate form label,
|
||||
.repository.new.fork form label,
|
||||
.repository.new.repo form input,
|
||||
.repository.new.migrate form input,
|
||||
.repository.new.fork form input,
|
||||
.repository.new.repo form .inline.field > input,
|
||||
.repository.new.migrate form .inline.field > input,
|
||||
.repository.new.fork form .inline.field > input,
|
||||
.repository.new.fork form .field a,
|
||||
.repository.new.repo form .selection.dropdown,
|
||||
.repository.new.migrate form .selection.dropdown,
|
||||
|
|
|
@ -20,7 +20,7 @@ input[type="radio"] {
|
|||
.ui.checkbox input[type="checkbox"],
|
||||
.ui.checkbox input[type="radio"] {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: 1px;
|
||||
left: 0;
|
||||
width: var(--checkbox-size);
|
||||
height: var(--checkbox-size);
|
||||
|
|
|
@ -49,30 +49,11 @@
|
|||
/* overwrite width of containers inside the main page content div (div with class "page-content") */
|
||||
.page-content .ui.ui.ui.container:not(.fluid) {
|
||||
width: 1280px;
|
||||
max-width: calc(100% - 64px);
|
||||
max-width: calc(100% - calc(2 * var(--page-margin-x)));
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.ui.container.fluid.padded {
|
||||
padding: 0 32px;
|
||||
}
|
||||
|
||||
/* enable fluid page widths for medium size viewports */
|
||||
@media (min-width: 768px) and (max-width: 1200px) {
|
||||
.page-content .ui.ui.ui.container:not(.fluid) {
|
||||
max-width: calc(100% - 32px);
|
||||
}
|
||||
.ui.container.fluid.padded {
|
||||
padding: 0 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.page-content .ui.ui.ui.container:not(.fluid) {
|
||||
max-width: calc(100% - 16px);
|
||||
}
|
||||
.ui.container.fluid.padded {
|
||||
padding: 0 8px;
|
||||
}
|
||||
padding: 0 var(--page-margin-x);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
.flex-container {
|
||||
display: flex !important;
|
||||
gap: 16px;
|
||||
gap: var(--page-spacing);
|
||||
margin-top: var(--page-spacing);
|
||||
}
|
||||
|
||||
.flex-container-nav {
|
||||
|
|
|
@ -126,6 +126,12 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ui.list .list > .item [class*="right floated"],
|
||||
.ui.list > .item [class*="right floated"] {
|
||||
float: right;
|
||||
margin: 0 0 0 1em;
|
||||
}
|
||||
|
||||
.ui.menu .ui.list > .item,
|
||||
.ui.menu .ui.list .list > .item {
|
||||
display: list-item;
|
||||
|
|
|
@ -177,12 +177,44 @@
|
|||
}
|
||||
}
|
||||
|
||||
.repository.file.list .repo-path {
|
||||
word-break: break-word;
|
||||
.commit-summary {
|
||||
flex: 1;
|
||||
overflow-wrap: anywhere;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.repository.file.list #repo-files-table {
|
||||
table-layout: fixed;
|
||||
.commit-header .commit-summary,
|
||||
td .commit-summary {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.latest-commit {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.latest-commit .sha {
|
||||
display: none;
|
||||
}
|
||||
.latest-commit .commit-summary {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.repo-path {
|
||||
display: flex;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
/* this is what limits the commit table width to a value that works on all viewport sizes */
|
||||
#repo-files-table th:first-of-type {
|
||||
max-width: calc(calc(min(100vw, 1280px)) - 145px - calc(2 * var(--page-margin-x)));
|
||||
}
|
||||
|
||||
.repository.file.list #repo-files-table thead th {
|
||||
|
@ -262,7 +294,6 @@
|
|||
}
|
||||
|
||||
.repository.file.list #repo-files-table td.age {
|
||||
width: 120px;
|
||||
color: var(--color-text-light-1);
|
||||
}
|
||||
|
||||
|
@ -1223,10 +1254,6 @@
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.repository #commits-table td.message {
|
||||
text-overflow: unset;
|
||||
}
|
||||
|
||||
.repository #commits-table.ui.basic.striped.table tbody tr:nth-child(2n) {
|
||||
background-color: var(--color-light) !important;
|
||||
}
|
||||
|
@ -2153,6 +2180,20 @@
|
|||
display: inline-block !important;
|
||||
}
|
||||
|
||||
.commit-header-buttons {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: flex-start;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.commit-header-buttons {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
|
||||
.settings.webhooks .list > .item:not(:first-child),
|
||||
.settings.githooks .list > .item:not(:first-child),
|
||||
.settings.actions .list > .item:not(:first-child) {
|
||||
|
@ -2384,7 +2425,7 @@ tbody.commit-list {
|
|||
.author-wrapper {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: calc(100% - 50px);
|
||||
max-width: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
@ -2409,10 +2450,6 @@ tbody.commit-list {
|
|||
tr.commit-list {
|
||||
width: 100%;
|
||||
}
|
||||
th .message-wrapper {
|
||||
display: block;
|
||||
max-width: calc(100vw - 70px);
|
||||
}
|
||||
.author-wrapper {
|
||||
max-width: 80px;
|
||||
}
|
||||
|
@ -2422,27 +2459,18 @@ tbody.commit-list {
|
|||
tr.commit-list {
|
||||
width: 723px;
|
||||
}
|
||||
th .message-wrapper {
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) and (max-width: 1200px) {
|
||||
tr.commit-list {
|
||||
width: 933px;
|
||||
}
|
||||
th .message-wrapper {
|
||||
max-width: 350px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1201px) {
|
||||
tr.commit-list {
|
||||
width: 1127px;
|
||||
}
|
||||
th .message-wrapper {
|
||||
max-width: 525px;
|
||||
}
|
||||
}
|
||||
|
||||
.commit-list .commit-status-link {
|
||||
|
@ -2770,7 +2798,7 @@ tbody.commit-list {
|
|||
.repository.file.list #repo-files-table .entry td.message,
|
||||
.repository.file.list #repo-files-table .commit-list td.message,
|
||||
.repository.file.list #repo-files-table .entry span.commit-summary,
|
||||
.repository.file.list #repo-files-table .commit-list span.commit-summary {
|
||||
.repository.file.list #repo-files-table .commit-list tr span.commit-summary {
|
||||
display: none !important;
|
||||
}
|
||||
.repository.view.issue .comment-list .timeline,
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
--color-console-fg-subtle: #bec4c8;
|
||||
--color-console-bg: #171b1e;
|
||||
--color-console-border: #2e353b;
|
||||
--color-console-hover-bg: #e8e8ff16;
|
||||
--color-console-hover-bg: #292d31;
|
||||
--color-console-active-bg: #2e353b;
|
||||
--color-console-menu-bg: #252b30;
|
||||
--color-console-menu-border: #424b51;
|
||||
|
|
|
@ -63,12 +63,12 @@
|
|||
/* console colors - used for actions console and console files */
|
||||
--color-console-fg: #f8f8f9;
|
||||
--color-console-fg-subtle: #bec4c8;
|
||||
--color-console-bg: #181b1d;
|
||||
--color-console-border: #313538;
|
||||
--color-console-hover-bg: #ffffff16;
|
||||
--color-console-active-bg: #313538;
|
||||
--color-console-menu-bg: #272b2e;
|
||||
--color-console-menu-border: #464a4d;
|
||||
--color-console-bg: #171b1e;
|
||||
--color-console-border: #2e353b;
|
||||
--color-console-hover-bg: #292d31;
|
||||
--color-console-active-bg: #2e353b;
|
||||
--color-console-menu-bg: #252b30;
|
||||
--color-console-menu-border: #424b51;
|
||||
/* named colors */
|
||||
--color-red: #db2828;
|
||||
--color-orange: #f2711c;
|
||||
|
|
|
@ -526,8 +526,16 @@ export function initRepositoryActionView() {
|
|||
|
||||
.action-summary {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
margin: 0 0 0 28px;
|
||||
margin-left: 28px;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.action-commit-summary {
|
||||
margin-left: 0;
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================ */
|
||||
|
@ -540,6 +548,14 @@ export function initRepositoryActionView() {
|
|||
top: 12px;
|
||||
max-height: 100vh;
|
||||
overflow-y: auto;
|
||||
background: var(--color-body);
|
||||
z-index: 2; /* above .job-info-header */
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.action-view-left {
|
||||
position: static; /* can not sticky because multiple jobs would overlap into right view */
|
||||
}
|
||||
}
|
||||
|
||||
.job-artifacts-title {
|
||||
|
@ -701,7 +717,9 @@ export function initRepositoryActionView() {
|
|||
position: sticky;
|
||||
top: 0;
|
||||
height: 60px;
|
||||
z-index: 1;
|
||||
z-index: 1; /* above .job-step-container */
|
||||
background: var(--color-console-bg);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.job-info-header:has(+ .job-step-container) {
|
||||
|
@ -739,7 +757,7 @@ export function initRepositoryActionView() {
|
|||
|
||||
.job-step-container .job-step-summary.step-expandable:hover {
|
||||
color: var(--color-console-fg);
|
||||
background-color: var(--color-console-hover-bg);
|
||||
background: var(--color-console-hover-bg);
|
||||
}
|
||||
|
||||
.job-step-container .job-step-summary .step-summary-msg {
|
||||
|
@ -757,17 +775,15 @@ export function initRepositoryActionView() {
|
|||
top: 60px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@media (max-width: 767.98px) {
|
||||
.action-view-body {
|
||||
flex-direction: column;
|
||||
}
|
||||
.action-view-left, .action-view-right {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.action-view-left {
|
||||
max-width: none;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -207,13 +207,13 @@ export function initAdminCommon() {
|
|||
|
||||
// Notice
|
||||
if (document.querySelector('.admin.notice')) {
|
||||
const $detailModal = document.getElementById('detail-modal');
|
||||
const detailModal = document.getElementById('detail-modal');
|
||||
|
||||
// Attach view detail modals
|
||||
$('.view-detail').on('click', function () {
|
||||
$detailModal.find('.content pre').text($(this).parents('tr').find('.notice-description').text());
|
||||
$detailModal.find('.sub.header').text(this.closest('tr')?.querySelector('relative-time')?.getAttribute('title'));
|
||||
$detailModal.modal('show');
|
||||
const description = this.closest('tr').querySelector('.notice-description').textContent;
|
||||
detailModal.querySelector('.content pre').textContent = description;
|
||||
$(detailModal).modal('show');
|
||||
return false;
|
||||
});
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import $ from 'jquery';
|
||||
import {hideElem, showElem} from '../utils/dom.js';
|
||||
import {GET} from '../modules/fetch.js';
|
||||
|
||||
export function initRepoGraphGit() {
|
||||
const graphContainer = document.getElementById('git-graph-container');
|
||||
if (!graphContainer) return;
|
||||
|
||||
$('#flow-color-monochrome').on('click', () => {
|
||||
$('#flow-color-monochrome').addClass('active');
|
||||
$('#flow-color-colored').removeClass('active');
|
||||
$('#git-graph-container').removeClass('colored').addClass('monochrome');
|
||||
document.getElementById('flow-color-monochrome')?.addEventListener('click', () => {
|
||||
document.getElementById('flow-color-monochrome').classList.add('active');
|
||||
document.getElementById('flow-color-colored')?.classList.remove('active');
|
||||
graphContainer.classList.remove('colored');
|
||||
graphContainer.classList.add('monochrome');
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
params.set('mode', 'monochrome');
|
||||
const queryString = params.toString();
|
||||
|
@ -17,29 +19,31 @@ export function initRepoGraphGit() {
|
|||
} else {
|
||||
window.history.replaceState({}, '', window.location.pathname);
|
||||
}
|
||||
$('.pagination a').each((_, that) => {
|
||||
const href = that.getAttribute('href');
|
||||
if (!href) return;
|
||||
for (const link of document.querySelectorAll('.pagination a')) {
|
||||
const href = link.getAttribute('href');
|
||||
if (!href) continue;
|
||||
const url = new URL(href, window.location);
|
||||
const params = url.searchParams;
|
||||
params.set('mode', 'monochrome');
|
||||
url.search = `?${params.toString()}`;
|
||||
that.setAttribute('href', url.href);
|
||||
});
|
||||
link.setAttribute('href', url.href);
|
||||
}
|
||||
});
|
||||
$('#flow-color-colored').on('click', () => {
|
||||
$('#flow-color-colored').addClass('active');
|
||||
$('#flow-color-monochrome').removeClass('active');
|
||||
$('#git-graph-container').addClass('colored').removeClass('monochrome');
|
||||
$('.pagination a').each((_, that) => {
|
||||
const href = that.getAttribute('href');
|
||||
if (!href) return;
|
||||
|
||||
document.getElementById('flow-color-colored')?.addEventListener('click', () => {
|
||||
document.getElementById('flow-color-colored').classList.add('active');
|
||||
document.getElementById('flow-color-monochrome')?.classList.remove('active');
|
||||
graphContainer.classList.add('colored');
|
||||
graphContainer.classList.remove('monochrome');
|
||||
for (const link of document.querySelectorAll('.pagination a')) {
|
||||
const href = link.getAttribute('href');
|
||||
if (!href) continue;
|
||||
const url = new URL(href, window.location);
|
||||
const params = url.searchParams;
|
||||
params.delete('mode');
|
||||
url.search = `?${params.toString()}`;
|
||||
that.setAttribute('href', url.href);
|
||||
});
|
||||
link.setAttribute('href', url.href);
|
||||
}
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
params.delete('mode');
|
||||
const queryString = params.toString();
|
||||
|
@ -56,20 +60,21 @@ export function initRepoGraphGit() {
|
|||
const ajaxUrl = new URL(url);
|
||||
ajaxUrl.searchParams.set('div-only', 'true');
|
||||
window.history.replaceState({}, '', queryString ? `?${queryString}` : window.location.pathname);
|
||||
$('#pagination').empty();
|
||||
$('#rel-container').addClass('tw-hidden');
|
||||
$('#rev-container').addClass('tw-hidden');
|
||||
$('#loading-indicator').removeClass('tw-hidden');
|
||||
document.getElementById('pagination').innerHTML = '';
|
||||
hideElem('#rel-container');
|
||||
hideElem('#rev-container');
|
||||
showElem('#loading-indicator');
|
||||
(async () => {
|
||||
const response = await GET(String(ajaxUrl));
|
||||
const html = await response.text();
|
||||
const $div = $(html);
|
||||
$('#pagination').html($div.find('#pagination').html());
|
||||
$('#rel-container').html($div.find('#rel-container').html());
|
||||
$('#rev-container').html($div.find('#rev-container').html());
|
||||
$('#loading-indicator').addClass('tw-hidden');
|
||||
$('#rel-container').removeClass('tw-hidden');
|
||||
$('#rev-container').removeClass('tw-hidden');
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = html;
|
||||
document.getElementById('pagination').innerHTML = div.getElementById('pagination').innerHTML;
|
||||
document.getElementById('rel-container').innerHTML = div.getElementById('rel-container').innerHTML;
|
||||
document.getElementById('rev-container').innerHTML = div.getElementById('rev-container').innerHTML;
|
||||
hideElem('#loading-indicator');
|
||||
showElem('#rel-container');
|
||||
showElem('#rev-container');
|
||||
})();
|
||||
};
|
||||
const dropdownSelected = params.getAll('branch');
|
||||
|
@ -77,8 +82,9 @@ export function initRepoGraphGit() {
|
|||
dropdownSelected.splice(0, 0, '...flow-hide-pr-refs');
|
||||
}
|
||||
|
||||
$('#flow-select-refs-dropdown').dropdown('set selected', dropdownSelected);
|
||||
$('#flow-select-refs-dropdown').dropdown({
|
||||
const flowSelectRefsDropdown = document.getElementById('flow-select-refs-dropdown');
|
||||
$(flowSelectRefsDropdown).dropdown('set selected', dropdownSelected);
|
||||
$(flowSelectRefsDropdown).dropdown({
|
||||
clearable: true,
|
||||
fullTextSeach: 'exact',
|
||||
onRemove(toRemove) {
|
||||
|
@ -104,36 +110,46 @@ export function initRepoGraphGit() {
|
|||
updateGraph();
|
||||
},
|
||||
});
|
||||
$('#git-graph-container').on('mouseenter', '#rev-list li', (e) => {
|
||||
const flow = $(e.currentTarget).data('flow');
|
||||
if (flow === 0) return;
|
||||
$(`#flow-${flow}`).addClass('highlight');
|
||||
$(e.currentTarget).addClass('hover');
|
||||
$(`#rev-list li[data-flow='${flow}']`).addClass('highlight');
|
||||
|
||||
graphContainer.addEventListener('mouseenter', (e) => {
|
||||
if (e.target.matches('#rev-list li')) {
|
||||
const flow = e.target.getAttribute('data-flow');
|
||||
if (flow === '0') return;
|
||||
document.getElementById(`flow-${flow}`)?.classList.add('highlight');
|
||||
e.target.classList.add('hover');
|
||||
for (const item of document.querySelectorAll(`#rev-list li[data-flow='${flow}']`)) {
|
||||
item.classList.add('highlight');
|
||||
}
|
||||
} else if (e.target.matches('#rel-container .flow-group')) {
|
||||
e.target.classList.add('highlight');
|
||||
const flow = e.target.getAttribute('data-flow');
|
||||
for (const item of document.querySelectorAll(`#rev-list li[data-flow='${flow}']`)) {
|
||||
item.classList.add('highlight');
|
||||
}
|
||||
} else if (e.target.matches('#rel-container .flow-commit')) {
|
||||
const rev = e.target.getAttribute('data-rev');
|
||||
document.querySelector(`#rev-list li#commit-${rev}`)?.classList.add('hover');
|
||||
}
|
||||
});
|
||||
$('#git-graph-container').on('mouseleave', '#rev-list li', (e) => {
|
||||
const flow = $(e.currentTarget).data('flow');
|
||||
if (flow === 0) return;
|
||||
$(`#flow-${flow}`).removeClass('highlight');
|
||||
$(e.currentTarget).removeClass('hover');
|
||||
$(`#rev-list li[data-flow='${flow}']`).removeClass('highlight');
|
||||
});
|
||||
$('#git-graph-container').on('mouseenter', '#rel-container .flow-group', (e) => {
|
||||
$(e.currentTarget).addClass('highlight');
|
||||
const flow = $(e.currentTarget).data('flow');
|
||||
$(`#rev-list li[data-flow='${flow}']`).addClass('highlight');
|
||||
});
|
||||
$('#git-graph-container').on('mouseleave', '#rel-container .flow-group', (e) => {
|
||||
$(e.currentTarget).removeClass('highlight');
|
||||
const flow = $(e.currentTarget).data('flow');
|
||||
$(`#rev-list li[data-flow='${flow}']`).removeClass('highlight');
|
||||
});
|
||||
$('#git-graph-container').on('mouseenter', '#rel-container .flow-commit', (e) => {
|
||||
const rev = $(e.currentTarget).data('rev');
|
||||
$(`#rev-list li#commit-${rev}`).addClass('hover');
|
||||
});
|
||||
$('#git-graph-container').on('mouseleave', '#rel-container .flow-commit', (e) => {
|
||||
const rev = $(e.currentTarget).data('rev');
|
||||
$(`#rev-list li#commit-${rev}`).removeClass('hover');
|
||||
|
||||
graphContainer.addEventListener('mouseleave', (e) => {
|
||||
if (e.target.matches('#rev-list li')) {
|
||||
const flow = e.target.getAttribute('data-flow');
|
||||
if (flow === '0') return;
|
||||
document.getElementById(`flow-${flow}`)?.classList.remove('highlight');
|
||||
e.target.classList.remove('hover');
|
||||
for (const item of document.querySelectorAll(`#rev-list li[data-flow='${flow}']`)) {
|
||||
item.classList.remove('highlight');
|
||||
}
|
||||
} else if (e.target.matches('#rel-container .flow-group')) {
|
||||
e.target.classList.remove('highlight');
|
||||
const flow = e.target.getAttribute('data-flow');
|
||||
for (const item of document.querySelectorAll(`#rev-list li[data-flow='${flow}']`)) {
|
||||
item.classList.remove('highlight');
|
||||
}
|
||||
} else if (e.target.matches('#rel-container .flow-commit')) {
|
||||
const rev = e.target.getAttribute('data-rev');
|
||||
document.querySelector(`#rev-list li#commit-${rev}`)?.classList.remove('hover');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -449,12 +449,10 @@ export function initRepoPullRequestReview() {
|
|||
offset += $('.diff-detail-box').outerHeight() + $(diffHeader).outerHeight();
|
||||
}
|
||||
|
||||
document.getElementById(`show-outdated-${id}`).classList.add('tw-hidden');
|
||||
document.getElementById(`code-comments-${id}`).classList.remove('tw-hidden');
|
||||
document.getElementById(`code-preview-${id}`).classList.remove('tw-hidden');
|
||||
document.getElementById(`hide-outdated-${id}`).classList.remove('tw-hidden');
|
||||
hideElem(`#show-outdated-${id}`);
|
||||
showElem(`#code-comments-${id}, #code-preview-${id}, #hide-outdated-${id}`);
|
||||
// if the comment box is folded, expand it
|
||||
if (ancestorDiffBox.getAttribute('data-folded') === 'true') {
|
||||
if (ancestorDiffBox?.getAttribute('data-folded') === 'true') {
|
||||
setFileFolding(ancestorDiffBox, ancestorDiffBox.querySelector('.fold-file'), false);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue