mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-13 02:02:53 +09:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9879e23c57 | ||
|
|
56a3b50136 | ||
|
|
9a8532d928 | ||
|
|
d29a0fc3be | ||
|
|
04517e17d6 | ||
|
|
3a222ee416 | ||
|
|
add85f5a85 | ||
|
|
76ad83f05e | ||
|
|
714ecd9f1e | ||
|
|
a08856606e | ||
|
|
7be2d7b136 | ||
|
|
6f3596e33c | ||
|
|
0305a73633 | ||
|
|
6cd1ccef3d | ||
|
|
ea0fe83888 | ||
|
|
1cec7f5ab5 | ||
|
|
1cb1101d44 | ||
|
|
653dff4e57 | ||
|
|
b661bbaed7 | ||
|
|
20ae184967 | ||
|
|
15b44496ec | ||
|
|
0d0ff5e32a | ||
|
|
f25f7c592f | ||
|
|
e8cf04bad7 | ||
|
|
251fdaaf41 | ||
|
|
f572fb906f | ||
|
|
9340269d84 | ||
|
|
34650b925b | ||
|
|
718e0db12e | ||
|
|
6110ddc280 |
@@ -9,7 +9,6 @@ linters:
|
||||
- unused
|
||||
- structcheck
|
||||
- varcheck
|
||||
- golint
|
||||
- dupl
|
||||
#- gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time.
|
||||
- gofmt
|
||||
|
||||
31
CHANGELOG.md
31
CHANGELOG.md
@@ -4,6 +4,37 @@ This changelog goes through all the changes that have been made in each release
|
||||
without substantial changes to our git log; to see the highlights of what has
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
|
||||
## [1.15.7](https://github.com/go-gitea/gitea/releases/tag/v1.15.7) - 2021-12-01
|
||||
|
||||
* ENHANCEMENTS
|
||||
* Only allow webhook to send requests to allowed hosts (#17482) (#17510)
|
||||
* Fix login redirection links (#17451) (#17473)
|
||||
* BUGFIXES
|
||||
* Fix database inconsistent when admin change user email (#17549) (#17840)
|
||||
* Use correct user on releases (#17806) (#17818)
|
||||
* Fix commit count in tag view (#17698) (#17790)
|
||||
* Fix close issue but time watcher still running (#17643) (#17761)
|
||||
* Fix Migrate Description (#17692) (#17727)
|
||||
* Fix bug when project board get open issue number (#17703) (#17726)
|
||||
* Return 400 but not 500 when request archive with wrong format (#17691) (#17700)
|
||||
* Fix bug when read mysql database max lifetime (#17682) (#17690)
|
||||
* Fix database deadlock when update issue labels (#17649) (#17665)
|
||||
* Fix bug on detect issue/comment writer (#17592)
|
||||
* Remove appSubUrl from pasted images (#17572) (#17588)
|
||||
* Make `ParsePatch` more robust (#17573) (#17580)
|
||||
* Fix stats upon searching issues (#17566) (#17578)
|
||||
* Escape issue titles in comments list (#17555) (#17556)
|
||||
* Fix zero created time bug on commit api (#17546) (#17547)
|
||||
* Fix database keyword quote problem on migration v161 (#17522) (#17523)
|
||||
* Fix email with + when active (#17518) (#17520)
|
||||
* Stop double encoding blame commit messages (#17498) (#17500)
|
||||
* Quote the table name in CountOrphanedObjects (#17487) (#17488)
|
||||
* Run Migrate in Install rather than just SyncTables (#17475) (#17486)
|
||||
* BUILD
|
||||
* Fix golangci-lint warnings (#17598 et al) (#17668)
|
||||
* MISC
|
||||
* Preserve color when inverting emojis (#17797) (#17799)
|
||||
|
||||
## [1.15.6](https://github.com/go-gitea/gitea/releases/tag/v1.15.6) - 2021-10-28
|
||||
|
||||
* BUGFIXES
|
||||
|
||||
3
build.go
3
build.go
@@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//+build vendor
|
||||
//go:build vendor
|
||||
// +build vendor
|
||||
|
||||
package main
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// gocovmerge takes the results from multiple `go test -coverprofile` runs and
|
||||
// merges them into one profile
|
||||
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
@@ -43,7 +43,11 @@ func runDocs(ctx *cli.Context) error {
|
||||
// Clean up markdown. The following bug was fixed in v2, but is present in v1.
|
||||
// It affects markdown output (even though the issue is referring to man pages)
|
||||
// https://github.com/urfave/cli/issues/1040
|
||||
docs = docs[strings.Index(docs, "#"):]
|
||||
firstHashtagIndex := strings.Index(docs, "#")
|
||||
|
||||
if firstHashtagIndex > 0 {
|
||||
docs = docs[firstHashtagIndex:]
|
||||
}
|
||||
}
|
||||
|
||||
out := os.Stdout
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build bindata
|
||||
// +build bindata
|
||||
|
||||
package cmd
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !bindata
|
||||
// +build !bindata
|
||||
|
||||
package cmd
|
||||
|
||||
@@ -194,6 +194,10 @@ func listen(m http.Handler, handleRedirector bool) error {
|
||||
listenAddr = net.JoinHostPort(listenAddr, setting.HTTPPort)
|
||||
}
|
||||
log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL)
|
||||
// This can be useful for users, many users do wrong to their config and get strange behaviors behind a reverse-proxy.
|
||||
// A user may fix the configuration mistake when he sees this log.
|
||||
// And this is also very helpful to maintainers to provide help to users to resolve their configuration problems.
|
||||
log.Info("AppURL(ROOT_URL): %s", setting.AppURL)
|
||||
|
||||
if setting.LFS.StartServer {
|
||||
log.Info("LFS server enabled")
|
||||
|
||||
@@ -1388,6 +1388,13 @@ PATH =
|
||||
;; Deliver timeout in seconds
|
||||
;DELIVER_TIMEOUT = 5
|
||||
;;
|
||||
;; Webhook can only call allowed hosts for security reasons. Comma separated list, eg: external, 192.168.1.0/24, *.mydomain.com
|
||||
;; Built-in: loopback (for localhost), private (for LAN/intranet), external (for public hosts on internet), * (for all hosts)
|
||||
;; CIDR list: 1.2.3.0/8, 2001:db8::/32
|
||||
;; Wildcard hosts: *.mydomain.com, 192.168.100.*
|
||||
;; Default to * for 1.15.x, external for 1.16 and later
|
||||
;ALLOWED_HOST_LIST = *
|
||||
;;
|
||||
;; Allow insecure certification
|
||||
;SKIP_TLS_VERIFY = false
|
||||
;;
|
||||
|
||||
@@ -545,6 +545,14 @@ Define allowed algorithms and their minimum key length (use -1 to disable a type
|
||||
|
||||
- `QUEUE_LENGTH`: **1000**: Hook task queue length. Use caution when editing this value.
|
||||
- `DELIVER_TIMEOUT`: **5**: Delivery timeout (sec) for shooting webhooks.
|
||||
- `ALLOWED_HOST_LIST`: `*`: Default to `*` for 1.15.x, `external` for 1.16 and later. Webhook can only call allowed hosts for security reasons. Comma separated list.
|
||||
- Built-in networks:
|
||||
- `loopback`: 127.0.0.0/8 for IPv4 and ::1/128 for IPv6, localhost is included.
|
||||
- `private`: RFC 1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and RFC 4193 (FC00::/7). Also called LAN/Intranet.
|
||||
- `external`: A valid non-private unicast IP, you can access all hosts on public internet.
|
||||
- `*`: All hosts are allowed.
|
||||
- CIDR list: `1.2.3.0/8` for IPv4 and `2001:db8::/32` for IPv6
|
||||
- Wildcard hosts: `*.mydomain.com`, `192.168.100.*`
|
||||
- `SKIP_TLS_VERIFY`: **false**: Allow insecure certification.
|
||||
- `PAGING_NUM`: **10**: Number of webhook history events that are shown in one page.
|
||||
- `PROXY_URL`: ****: Proxy server URL, support http://, https//, socks://, blank will follow environment http_proxy/https_proxy
|
||||
|
||||
44
integrations/api_repo_archive_test.go
Normal file
44
integrations/api_repo_archive_test.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAPIDownloadArchive(t *testing.T) {
|
||||
defer prepareTestEnv(t)()
|
||||
|
||||
repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
|
||||
user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
|
||||
session := loginUser(t, user2.LowerName)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
|
||||
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master.zip", user2.Name, repo.Name))
|
||||
link.RawQuery = url.Values{"token": {token}}.Encode()
|
||||
resp := MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
|
||||
bs, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 320, len(bs))
|
||||
|
||||
link, _ = url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master.tar.gz", user2.Name, repo.Name))
|
||||
link.RawQuery = url.Values{"token": {token}}.Encode()
|
||||
resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
|
||||
bs, err = io.ReadAll(resp.Body)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 266, len(bs))
|
||||
|
||||
link, _ = url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master", user2.Name, repo.Name))
|
||||
link.RawQuery = url.Values{"token": {token}}.Encode()
|
||||
MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusBadRequest)
|
||||
}
|
||||
@@ -302,7 +302,7 @@ func DeleteOrphanedIssues() error {
|
||||
// CountOrphanedObjects count subjects with have no existing refobject anymore
|
||||
func CountOrphanedObjects(subject, refobject, joinCond string) (int64, error) {
|
||||
return x.Table("`"+subject+"`").
|
||||
Join("LEFT", refobject, joinCond).
|
||||
Join("LEFT", "`"+refobject+"`", joinCond).
|
||||
Where(builder.IsNull{"`" + refobject + "`.id"}).
|
||||
Count("id")
|
||||
}
|
||||
|
||||
@@ -1517,12 +1517,12 @@ func GetIssueStats(opts *IssueStatsOptions) (*IssueStats, error) {
|
||||
func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats, error) {
|
||||
stats := &IssueStats{}
|
||||
|
||||
countSession := func(opts *IssueStatsOptions) *xorm.Session {
|
||||
countSession := func(opts *IssueStatsOptions, issueIDs []int64) *xorm.Session {
|
||||
sess := x.
|
||||
Where("issue.repo_id = ?", opts.RepoID)
|
||||
|
||||
if len(opts.IssueIDs) > 0 {
|
||||
sess.In("issue.id", opts.IssueIDs)
|
||||
if len(issueIDs) > 0 {
|
||||
sess.In("issue.id", issueIDs)
|
||||
}
|
||||
|
||||
if len(opts.Labels) > 0 && opts.Labels != "0" {
|
||||
@@ -1572,13 +1572,13 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats,
|
||||
}
|
||||
|
||||
var err error
|
||||
stats.OpenCount, err = countSession(opts).
|
||||
stats.OpenCount, err = countSession(opts, issueIDs).
|
||||
And("issue.is_closed = ?", false).
|
||||
Count(new(Issue))
|
||||
if err != nil {
|
||||
return stats, err
|
||||
}
|
||||
stats.ClosedCount, err = countSession(opts).
|
||||
stats.ClosedCount, err = countSession(opts, issueIDs).
|
||||
And("issue.is_closed = ?", true).
|
||||
Count(new(Issue))
|
||||
return stats, err
|
||||
|
||||
@@ -13,6 +13,26 @@ import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
// ErrIssueStopwatchNotExist represents an error that stopwatch is not exist
|
||||
type ErrIssueStopwatchNotExist struct {
|
||||
UserID int64
|
||||
IssueID int64
|
||||
}
|
||||
|
||||
func (err ErrIssueStopwatchNotExist) Error() string {
|
||||
return fmt.Sprintf("issue stopwatch doesn't exist[uid: %d, issue_id: %d", err.UserID, err.IssueID)
|
||||
}
|
||||
|
||||
// ErrIssueStopwatchAlreadyExist represents an error that stopwatch is already exist
|
||||
type ErrIssueStopwatchAlreadyExist struct {
|
||||
UserID int64
|
||||
IssueID int64
|
||||
}
|
||||
|
||||
func (err ErrIssueStopwatchAlreadyExist) Error() string {
|
||||
return fmt.Sprintf("issue stopwatch already exists[uid: %d, issue_id: %d", err.UserID, err.IssueID)
|
||||
}
|
||||
|
||||
// Stopwatch represents a stopwatch for time tracking.
|
||||
type Stopwatch struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
@@ -74,91 +94,141 @@ func hasUserStopwatch(e Engine, userID int64) (exists bool, sw *Stopwatch, err e
|
||||
return
|
||||
}
|
||||
|
||||
// FinishIssueStopwatchIfPossible if stopwatch exist then finish it otherwise ignore
|
||||
func FinishIssueStopwatchIfPossible(user *User, issue *Issue) error {
|
||||
_, exists, err := getStopwatch(x, user.ID, issue.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
return FinishIssueStopwatch(user, issue)
|
||||
}
|
||||
|
||||
// CreateOrStopIssueStopwatch will create or remove a stopwatch and will log it into issue's timeline.
|
||||
func CreateOrStopIssueStopwatch(user *User, issue *Issue) error {
|
||||
_, exists, err := getStopwatch(x, user.ID, issue.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
return FinishIssueStopwatch(user, issue)
|
||||
}
|
||||
return CreateIssueStopwatch(user, issue)
|
||||
}
|
||||
|
||||
// FinishIssueStopwatch if stopwatch exist then finish it otherwise return an error
|
||||
func FinishIssueStopwatch(user *User, issue *Issue) error {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := createOrStopIssueStopwatch(sess, user, issue); err != nil {
|
||||
if err := finishIssueStopwatch(sess, user, issue); err != nil {
|
||||
return err
|
||||
}
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func createOrStopIssueStopwatch(e *xorm.Session, user *User, issue *Issue) error {
|
||||
func finishIssueStopwatch(e *xorm.Session, user *User, issue *Issue) error {
|
||||
sw, exists, err := getStopwatch(e, user.ID, issue.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return ErrIssueStopwatchNotExist{
|
||||
UserID: user.ID,
|
||||
IssueID: issue.ID,
|
||||
}
|
||||
}
|
||||
|
||||
// Create tracked time out of the time difference between start date and actual date
|
||||
timediff := time.Now().Unix() - int64(sw.CreatedUnix)
|
||||
|
||||
// Create TrackedTime
|
||||
tt := &TrackedTime{
|
||||
Created: time.Now(),
|
||||
IssueID: issue.ID,
|
||||
UserID: user.ID,
|
||||
Time: timediff,
|
||||
}
|
||||
|
||||
if _, err := e.Insert(tt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := issue.loadRepo(e); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := createComment(e, &CreateCommentOptions{
|
||||
Doer: user,
|
||||
Issue: issue,
|
||||
Repo: issue.Repo,
|
||||
Content: SecToTime(timediff),
|
||||
Type: CommentTypeStopTracking,
|
||||
TimeID: tt.ID,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = e.Delete(sw)
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateIssueStopwatch creates a stopwatch if not exist, otherwise return an error
|
||||
func CreateIssueStopwatch(user *User, issue *Issue) error {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := createIssueStopwatch(sess, user, issue); err != nil {
|
||||
return err
|
||||
}
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func createIssueStopwatch(e *xorm.Session, user *User, issue *Issue) error {
|
||||
if err := issue.loadRepo(e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if another stopwatch is running: stop it
|
||||
exists, sw, err := hasUserStopwatch(e, user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
// Create tracked time out of the time difference between start date and actual date
|
||||
timediff := time.Now().Unix() - int64(sw.CreatedUnix)
|
||||
|
||||
// Create TrackedTime
|
||||
tt := &TrackedTime{
|
||||
Created: time.Now(),
|
||||
IssueID: issue.ID,
|
||||
UserID: user.ID,
|
||||
Time: timediff,
|
||||
}
|
||||
|
||||
if _, err := e.Insert(tt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := createComment(e, &CreateCommentOptions{
|
||||
Doer: user,
|
||||
Issue: issue,
|
||||
Repo: issue.Repo,
|
||||
Content: SecToTime(timediff),
|
||||
Type: CommentTypeStopTracking,
|
||||
TimeID: tt.ID,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := e.Delete(sw); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// if another stopwatch is running: stop it
|
||||
exists, sw, err := hasUserStopwatch(e, user.ID)
|
||||
issue, err := getIssueByID(e, sw.IssueID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
issue, err := getIssueByID(e, sw.IssueID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := createOrStopIssueStopwatch(e, user, issue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create stopwatch
|
||||
sw = &Stopwatch{
|
||||
UserID: user.ID,
|
||||
IssueID: issue.ID,
|
||||
}
|
||||
|
||||
if _, err := e.Insert(sw); err != nil {
|
||||
if err := finishIssueStopwatch(e, user, issue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := createComment(e, &CreateCommentOptions{
|
||||
Doer: user,
|
||||
Issue: issue,
|
||||
Repo: issue.Repo,
|
||||
Type: CommentTypeStartTracking,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
// Create stopwatch
|
||||
sw = &Stopwatch{
|
||||
UserID: user.ID,
|
||||
IssueID: issue.ID,
|
||||
}
|
||||
|
||||
if _, err := e.Insert(sw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := issue.loadRepo(e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := createComment(e, &CreateCommentOptions{
|
||||
Doer: user,
|
||||
Issue: issue,
|
||||
Repo: issue.Repo,
|
||||
Type: CommentTypeStartTracking,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -417,3 +419,43 @@ func TestIssue_ResolveMentions(t *testing.T) {
|
||||
// Private repo, whole team
|
||||
testSuccess("user17", "big_test_private_4", "user15", []string{"user17/owners"}, []int64{18})
|
||||
}
|
||||
|
||||
func TestCorrectIssueStats(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
|
||||
// Because the condition is to have chunked database look-ups,
|
||||
// We have to more issues than `maxQueryParameters`, we will insert.
|
||||
// maxQueryParameters + 10 issues into the testDatabase.
|
||||
// Each new issues will have a constant description "Bugs are nasty"
|
||||
// Which will be used later on.
|
||||
|
||||
issueAmount := maxQueryParameters + 10
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < issueAmount; i++ {
|
||||
wg.Add(1)
|
||||
go func(i int) {
|
||||
testInsertIssue(t, fmt.Sprintf("Issue %d", i+1), "Bugs are nasty", 0)
|
||||
wg.Done()
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
// Now we will get all issueID's that match the "Bugs are nasty" query.
|
||||
total, ids, err := SearchIssueIDsByKeyword("Bugs are nasty", []int64{1}, issueAmount, 0)
|
||||
|
||||
// Just to be sure.
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, issueAmount, total)
|
||||
|
||||
// Now we will call the GetIssueStats with these IDs and if working,
|
||||
// get the correct stats back.
|
||||
issueStats, err := GetIssueStats(&IssueStatsOptions{
|
||||
RepoID: 1,
|
||||
IssueIDs: ids,
|
||||
})
|
||||
|
||||
// Now check the values.
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, issueStats.OpenCount, issueAmount)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
@@ -762,8 +763,14 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
|
||||
}
|
||||
tableSQL := string(res[0]["sql"])
|
||||
|
||||
// Get the string offset for column definitions: `CREATE TABLE ( column-definitions... )`
|
||||
columnDefinitionsIndex := strings.Index(tableSQL, "(")
|
||||
if columnDefinitionsIndex < 0 {
|
||||
return errors.New("couldn't find column definitions")
|
||||
}
|
||||
|
||||
// Separate out the column definitions
|
||||
tableSQL = tableSQL[strings.Index(tableSQL, "("):]
|
||||
tableSQL = tableSQL[columnDefinitionsIndex:]
|
||||
|
||||
// Remove the required columnNames
|
||||
for _, name := range columnNames {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
@@ -40,8 +42,17 @@ func convertTaskTypeToString(x *xorm.Engine) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// to keep the migration could be rerun
|
||||
exist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "hook_task", "type")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exist {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i, s := range hookTaskTypes {
|
||||
if _, err := x.Exec("UPDATE hook_task set typ = ? where type=?", s, i); err != nil {
|
||||
if _, err := x.Exec("UPDATE hook_task set typ = ? where `type`=?", s, i); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@@ -19,6 +20,22 @@ func renameTaskErrorsToMessage(x *xorm.Engine) error {
|
||||
Status int `xorm:"index"`
|
||||
}
|
||||
|
||||
// This migration maybe rerun so that we should check if it has been run
|
||||
messageExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "task", "message")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if messageExist {
|
||||
errorsExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "task", "errors")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !errorsExist {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
@@ -29,6 +46,13 @@ func renameTaskErrorsToMessage(x *xorm.Engine) error {
|
||||
return fmt.Errorf("error on Sync2: %v", err)
|
||||
}
|
||||
|
||||
if messageExist {
|
||||
// if both errors and message exist, drop message at first
|
||||
if err := dropTableColumns(sess, "task", "message"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case setting.Database.UseMySQL:
|
||||
if _, err := sess.Exec("ALTER TABLE `task` CHANGE errors message text"); err != nil {
|
||||
|
||||
@@ -179,16 +179,35 @@ func syncTables() error {
|
||||
return x.StoreEngine("InnoDB").Sync2(tables...)
|
||||
}
|
||||
|
||||
// NewTestEngine sets a new test xorm.Engine
|
||||
func NewTestEngine() (err error) {
|
||||
// NewInstallTestEngine creates a new xorm.Engine for testing during install
|
||||
//
|
||||
// This function will cause the basic database schema to be created
|
||||
func NewInstallTestEngine(ctx context.Context, migrateFunc func(*xorm.Engine) error) (err error) {
|
||||
x, err = GetNewEngine()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Connect to database: %v", err)
|
||||
return fmt.Errorf("failed to connect to database: %w", err)
|
||||
}
|
||||
|
||||
x.SetMapper(names.GonicMapper{})
|
||||
x.SetLogger(NewXORMLogger(!setting.IsProd()))
|
||||
x.ShowSQL(!setting.IsProd())
|
||||
|
||||
x.SetDefaultContext(ctx)
|
||||
|
||||
if err = x.Ping(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We have to run migrateFunc here in case the user is re-running installation on a previously created DB.
|
||||
// If we do not then table schemas will be changed and there will be conflicts when the migrations run properly.
|
||||
//
|
||||
// Installation should only be being re-run if users want to recover an old database.
|
||||
// However, we should think carefully about should we support re-install on an installed instance,
|
||||
// as there may be other problems due to secret reinitialization.
|
||||
if err = migrateFunc(x); err != nil {
|
||||
return fmt.Errorf("migrate: %v", err)
|
||||
}
|
||||
|
||||
return syncTables()
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,9 @@ func (p *Project) NumClosedIssues() int {
|
||||
func (p *Project) NumOpenIssues() int {
|
||||
c, err := x.Table("project_issue").
|
||||
Join("INNER", "issue", "project_issue.issue_id=issue.id").
|
||||
Where("project_issue.project_id=? AND issue.is_closed=?", p.ID, false).Count("issue.id")
|
||||
Where("project_issue.project_id=? AND issue.is_closed=?", p.ID, false).
|
||||
Cols("issue_id").
|
||||
Count()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -77,9 +77,6 @@ var (
|
||||
// ErrEmailNotActivated e-mail address has not been activated error
|
||||
ErrEmailNotActivated = errors.New("E-mail address has not been activated")
|
||||
|
||||
// ErrUserNameIllegal user name contains illegal characters error
|
||||
ErrUserNameIllegal = errors.New("User name contains illegal characters")
|
||||
|
||||
// ErrLoginSourceNotActived login source is not actived error
|
||||
ErrLoginSourceNotActived = errors.New("Login source is not actived")
|
||||
|
||||
@@ -1072,18 +1069,46 @@ func validateUser(u *User) error {
|
||||
return ValidateEmail(u.Email)
|
||||
}
|
||||
|
||||
func updateUser(e Engine, u *User) error {
|
||||
func updateUser(e Engine, u *User, changePrimaryEmail bool) error {
|
||||
if err := validateUser(u); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if changePrimaryEmail {
|
||||
var emailAddress EmailAddress
|
||||
has, err := e.Where("lower_email=?", strings.ToLower(u.Email)).Get(&emailAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has {
|
||||
// 1. Update old primary email
|
||||
if _, err = e.Where("uid=? AND is_primary=?", u.ID, true).Cols("is_primary").Update(&EmailAddress{
|
||||
IsPrimary: false,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
emailAddress.Email = u.Email
|
||||
emailAddress.UID = u.ID
|
||||
emailAddress.IsActivated = true
|
||||
emailAddress.IsPrimary = true
|
||||
if _, err := e.Insert(&emailAddress); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if _, err := e.ID(emailAddress).Cols("is_primary").Update(&EmailAddress{
|
||||
IsPrimary: true,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err := e.ID(u.ID).AllCols().Update(u)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateUser updates user's information.
|
||||
func UpdateUser(u *User) error {
|
||||
return updateUser(x, u)
|
||||
func UpdateUser(u *User, changePrimaryEmail bool) error {
|
||||
return updateUser(x, u, changePrimaryEmail)
|
||||
}
|
||||
|
||||
// UpdateUserCols update user according special columns
|
||||
@@ -1112,7 +1137,7 @@ func UpdateUserSetting(u *User) (err error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = updateUser(sess, u); err != nil {
|
||||
if err = updateUser(sess, u, false); err != nil {
|
||||
return err
|
||||
}
|
||||
return sess.Commit()
|
||||
|
||||
@@ -475,17 +475,17 @@ func TestUpdateUser(t *testing.T) {
|
||||
user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||
|
||||
user.KeepActivityPrivate = true
|
||||
assert.NoError(t, UpdateUser(user))
|
||||
assert.NoError(t, UpdateUser(user, false))
|
||||
user = AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||
assert.True(t, user.KeepActivityPrivate)
|
||||
|
||||
setting.Service.AllowedUserVisibilityModesSlice = []bool{true, false, false}
|
||||
user.KeepActivityPrivate = false
|
||||
user.Visibility = structs.VisibleTypePrivate
|
||||
assert.Error(t, UpdateUser(user))
|
||||
assert.Error(t, UpdateUser(user, false))
|
||||
user = AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||
assert.True(t, user.KeepActivityPrivate)
|
||||
|
||||
user.Email = "no mail@mail.org"
|
||||
assert.Error(t, UpdateUser(user))
|
||||
assert.Error(t, UpdateUser(user, true))
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build pam
|
||||
// +build pam
|
||||
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// +build !pam
|
||||
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !pam
|
||||
// +build !pam
|
||||
|
||||
package pam
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build pam
|
||||
// +build pam
|
||||
|
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
|
||||
@@ -58,6 +58,7 @@ type Repository struct {
|
||||
Commit *git.Commit
|
||||
Tag *git.Tag
|
||||
GitRepo *git.Repository
|
||||
RefName string
|
||||
BranchName string
|
||||
TagName string
|
||||
TreePath string
|
||||
@@ -190,9 +191,9 @@ func (r *Repository) BranchNameSubURL() string {
|
||||
case r.IsViewBranch:
|
||||
return "branch/" + r.BranchName
|
||||
case r.IsViewTag:
|
||||
return "tag/" + r.BranchName
|
||||
return "tag/" + r.TagName
|
||||
case r.IsViewCommit:
|
||||
return "commit/" + r.BranchName
|
||||
return "commit/" + r.CommitID
|
||||
}
|
||||
log.Error("Unknown view type for repo: %v", r)
|
||||
return ""
|
||||
@@ -562,8 +563,6 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
ctx.Data["Branches"] = brs
|
||||
ctx.Data["BranchesCount"] = len(brs)
|
||||
|
||||
ctx.Data["TagName"] = ctx.Repo.TagName
|
||||
|
||||
// If not branch selected, try default one.
|
||||
// If default branch doesn't exists, fall back to some other branch.
|
||||
if len(ctx.Repo.BranchName) == 0 {
|
||||
@@ -572,9 +571,9 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
} else if len(brs) > 0 {
|
||||
ctx.Repo.BranchName = brs[0]
|
||||
}
|
||||
ctx.Repo.RefName = ctx.Repo.BranchName
|
||||
}
|
||||
ctx.Data["BranchName"] = ctx.Repo.BranchName
|
||||
ctx.Data["CommitID"] = ctx.Repo.CommitID
|
||||
|
||||
// People who have push access or have forked repository can propose a new pull request.
|
||||
canPush := ctx.Repo.CanWrite(models.UnitTypeCode) || (ctx.IsSigned && ctx.User.HasForkedRepo(ctx.Repo.Repository.ID))
|
||||
@@ -759,7 +758,6 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
// Get default branch.
|
||||
if len(ctx.Params("*")) == 0 {
|
||||
refName = ctx.Repo.Repository.DefaultBranch
|
||||
ctx.Repo.BranchName = refName
|
||||
if !ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||
brs, _, err := ctx.Repo.GitRepo.GetBranches(0, 0)
|
||||
if err != nil {
|
||||
@@ -773,6 +771,8 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
}
|
||||
refName = brs[0]
|
||||
}
|
||||
ctx.Repo.RefName = refName
|
||||
ctx.Repo.BranchName = refName
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetBranchCommit", err)
|
||||
@@ -783,9 +783,10 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
|
||||
} else {
|
||||
refName = getRefName(ctx, refType)
|
||||
ctx.Repo.BranchName = refName
|
||||
ctx.Repo.RefName = refName
|
||||
if refType.RefTypeIncludesBranches() && ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||
ctx.Repo.IsViewBranch = true
|
||||
ctx.Repo.BranchName = refName
|
||||
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
|
||||
if err != nil {
|
||||
@@ -796,6 +797,8 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
|
||||
} else if refType.RefTypeIncludesTags() && ctx.Repo.GitRepo.IsTagExist(refName) {
|
||||
ctx.Repo.IsViewTag = true
|
||||
ctx.Repo.TagName = refName
|
||||
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetTagCommit(refName)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetTagCommit", err)
|
||||
@@ -837,6 +840,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
|
||||
ctx.Data["BranchName"] = ctx.Repo.BranchName
|
||||
ctx.Data["BranchNameSubURL"] = ctx.Repo.BranchNameSubURL()
|
||||
ctx.Data["TagName"] = ctx.Repo.TagName
|
||||
ctx.Data["CommitID"] = ctx.Repo.CommitID
|
||||
ctx.Data["TreePath"] = ctx.Repo.TreePath
|
||||
ctx.Data["IsViewBranch"] = ctx.Repo.IsViewBranch
|
||||
|
||||
@@ -147,8 +147,9 @@ func ToCommit(repo *models.Repository, commit *git.Commit, userCache map[string]
|
||||
|
||||
return &api.Commit{
|
||||
CommitMeta: &api.CommitMeta{
|
||||
URL: repo.APIURL() + "/git/commits/" + commit.ID.String(),
|
||||
SHA: commit.ID.String(),
|
||||
URL: repo.APIURL() + "/git/commits/" + commit.ID.String(),
|
||||
SHA: commit.ID.String(),
|
||||
Created: commit.Committer.When,
|
||||
},
|
||||
HTMLURL: repo.HTMLURL() + "/commit/" + commit.ID.String(),
|
||||
RepoCommit: &api.RepoCommit{
|
||||
@@ -169,8 +170,9 @@ func ToCommit(repo *models.Repository, commit *git.Commit, userCache map[string]
|
||||
},
|
||||
Message: commit.Message(),
|
||||
Tree: &api.CommitMeta{
|
||||
URL: repo.APIURL() + "/git/trees/" + commit.ID.String(),
|
||||
SHA: commit.ID.String(),
|
||||
URL: repo.APIURL() + "/git/trees/" + commit.ID.String(),
|
||||
SHA: commit.ID.String(),
|
||||
Created: commit.Committer.When,
|
||||
},
|
||||
},
|
||||
Author: apiAuthor,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build race
|
||||
// +build race
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package pipeline
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package pipeline
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -52,9 +52,7 @@ func getRefURL(refURL, urlPrefix, repoFullName, sshDomain string) string {
|
||||
urlPrefixHostname = prefixURL.Host
|
||||
}
|
||||
|
||||
if strings.HasSuffix(urlPrefix, "/") {
|
||||
urlPrefix = urlPrefix[:len(urlPrefix)-1]
|
||||
}
|
||||
urlPrefix = strings.TrimSuffix(urlPrefix, "/")
|
||||
|
||||
// FIXME: Need to consider branch - which will require changes in modules/git/commit.go:GetSubModules
|
||||
// Relative url prefix check (according to git submodule documentation)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package git
|
||||
|
||||
@@ -217,11 +217,9 @@ func newRefsFromRefNames(refNames []byte) []git.Reference {
|
||||
continue
|
||||
}
|
||||
refName := string(refNameBytes)
|
||||
if strings.HasPrefix(refName, "tag: ") {
|
||||
refName = strings.TrimPrefix(refName, "tag: ")
|
||||
} else if strings.HasPrefix(refName, "HEAD -> ") {
|
||||
refName = strings.TrimPrefix(refName, "HEAD -> ")
|
||||
}
|
||||
refName = strings.TrimPrefix(refName, "tag: ")
|
||||
refName = strings.TrimPrefix(refName, "HEAD -> ")
|
||||
|
||||
refs = append(refs, git.Reference{
|
||||
Name: refName,
|
||||
})
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// +build !windows
|
||||
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package graceful
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// +build windows
|
||||
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// This code is heavily inspired by the archived gofacebook/gracenet/net.go handler
|
||||
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package graceful
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// +build !windows
|
||||
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// This code is heavily inspired by the archived gofacebook/gracenet/net.go handler
|
||||
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package graceful
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// +build windows
|
||||
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// This code is heavily inspired by the archived gofacebook/gracenet/net.go handler
|
||||
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package graceful
|
||||
|
||||
import "net"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// +build !windows
|
||||
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// This code is heavily inspired by the archived gofacebook/gracenet/net.go handler
|
||||
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package graceful
|
||||
|
||||
import (
|
||||
|
||||
94
modules/hostmatcher/hostmatcher.go
Normal file
94
modules/hostmatcher/hostmatcher.go
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package hostmatcher
|
||||
|
||||
import (
|
||||
"net"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// HostMatchList is used to check if a host or IP is in a list.
|
||||
// If you only need to do wildcard matching, consider to use modules/matchlist
|
||||
type HostMatchList struct {
|
||||
hosts []string
|
||||
ipNets []*net.IPNet
|
||||
}
|
||||
|
||||
// MatchBuiltinAll all hosts are matched
|
||||
const MatchBuiltinAll = "*"
|
||||
|
||||
// MatchBuiltinExternal A valid non-private unicast IP, all hosts on public internet are matched
|
||||
const MatchBuiltinExternal = "external"
|
||||
|
||||
// MatchBuiltinPrivate RFC 1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and RFC 4193 (FC00::/7). Also called LAN/Intranet.
|
||||
const MatchBuiltinPrivate = "private"
|
||||
|
||||
// MatchBuiltinLoopback 127.0.0.0/8 for IPv4 and ::1/128 for IPv6, localhost is included.
|
||||
const MatchBuiltinLoopback = "loopback"
|
||||
|
||||
// ParseHostMatchList parses the host list HostMatchList
|
||||
func ParseHostMatchList(hostList string) *HostMatchList {
|
||||
hl := &HostMatchList{}
|
||||
for _, s := range strings.Split(hostList, ",") {
|
||||
s = strings.ToLower(strings.TrimSpace(s))
|
||||
if s == "" {
|
||||
continue
|
||||
}
|
||||
_, ipNet, err := net.ParseCIDR(s)
|
||||
if err == nil {
|
||||
hl.ipNets = append(hl.ipNets, ipNet)
|
||||
} else {
|
||||
hl.hosts = append(hl.hosts, s)
|
||||
}
|
||||
}
|
||||
return hl
|
||||
}
|
||||
|
||||
// MatchesHostOrIP checks if the host or IP matches an allow/deny(block) list
|
||||
func (hl *HostMatchList) MatchesHostOrIP(host string, ip net.IP) bool {
|
||||
var matched bool
|
||||
host = strings.ToLower(host)
|
||||
ipStr := ip.String()
|
||||
loop:
|
||||
for _, hostInList := range hl.hosts {
|
||||
switch hostInList {
|
||||
case "":
|
||||
continue
|
||||
case MatchBuiltinAll:
|
||||
matched = true
|
||||
break loop
|
||||
case MatchBuiltinExternal:
|
||||
if matched = ip.IsGlobalUnicast() && !util.IsIPPrivate(ip); matched {
|
||||
break loop
|
||||
}
|
||||
case MatchBuiltinPrivate:
|
||||
if matched = util.IsIPPrivate(ip); matched {
|
||||
break loop
|
||||
}
|
||||
case MatchBuiltinLoopback:
|
||||
if matched = ip.IsLoopback(); matched {
|
||||
break loop
|
||||
}
|
||||
default:
|
||||
if matched, _ = filepath.Match(hostInList, host); matched {
|
||||
break loop
|
||||
}
|
||||
if matched, _ = filepath.Match(hostInList, ipStr); matched {
|
||||
break loop
|
||||
}
|
||||
}
|
||||
}
|
||||
if !matched {
|
||||
for _, ipNet := range hl.ipNets {
|
||||
if matched = ipNet.Contains(ip); matched {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return matched
|
||||
}
|
||||
119
modules/hostmatcher/hostmatcher_test.go
Normal file
119
modules/hostmatcher/hostmatcher_test.go
Normal file
@@ -0,0 +1,119 @@
|
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package hostmatcher
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestHostOrIPMatchesList(t *testing.T) {
|
||||
type tc struct {
|
||||
host string
|
||||
ip net.IP
|
||||
expected bool
|
||||
}
|
||||
|
||||
// for IPv6: "::1" is loopback, "fd00::/8" is private
|
||||
|
||||
hl := ParseHostMatchList("private, External, *.myDomain.com, 169.254.1.0/24")
|
||||
cases := []tc{
|
||||
{"", net.IPv4zero, false},
|
||||
{"", net.IPv6zero, false},
|
||||
|
||||
{"", net.ParseIP("127.0.0.1"), false},
|
||||
{"", net.ParseIP("::1"), false},
|
||||
|
||||
{"", net.ParseIP("10.0.1.1"), true},
|
||||
{"", net.ParseIP("192.168.1.1"), true},
|
||||
{"", net.ParseIP("fd00::1"), true},
|
||||
|
||||
{"", net.ParseIP("8.8.8.8"), true},
|
||||
{"", net.ParseIP("1001::1"), true},
|
||||
|
||||
{"mydomain.com", net.IPv4zero, false},
|
||||
{"sub.mydomain.com", net.IPv4zero, true},
|
||||
|
||||
{"", net.ParseIP("169.254.1.1"), true},
|
||||
{"", net.ParseIP("169.254.2.2"), false},
|
||||
}
|
||||
for _, c := range cases {
|
||||
assert.Equalf(t, c.expected, hl.MatchesHostOrIP(c.host, c.ip), "case %s(%v)", c.host, c.ip)
|
||||
}
|
||||
|
||||
hl = ParseHostMatchList("loopback")
|
||||
cases = []tc{
|
||||
{"", net.IPv4zero, false},
|
||||
{"", net.ParseIP("127.0.0.1"), true},
|
||||
{"", net.ParseIP("10.0.1.1"), false},
|
||||
{"", net.ParseIP("192.168.1.1"), false},
|
||||
{"", net.ParseIP("8.8.8.8"), false},
|
||||
|
||||
{"", net.ParseIP("::1"), true},
|
||||
{"", net.ParseIP("fd00::1"), false},
|
||||
{"", net.ParseIP("1000::1"), false},
|
||||
|
||||
{"mydomain.com", net.IPv4zero, false},
|
||||
}
|
||||
for _, c := range cases {
|
||||
assert.Equalf(t, c.expected, hl.MatchesHostOrIP(c.host, c.ip), "case %s(%v)", c.host, c.ip)
|
||||
}
|
||||
|
||||
hl = ParseHostMatchList("private")
|
||||
cases = []tc{
|
||||
{"", net.IPv4zero, false},
|
||||
{"", net.ParseIP("127.0.0.1"), false},
|
||||
{"", net.ParseIP("10.0.1.1"), true},
|
||||
{"", net.ParseIP("192.168.1.1"), true},
|
||||
{"", net.ParseIP("8.8.8.8"), false},
|
||||
|
||||
{"", net.ParseIP("::1"), false},
|
||||
{"", net.ParseIP("fd00::1"), true},
|
||||
{"", net.ParseIP("1000::1"), false},
|
||||
|
||||
{"mydomain.com", net.IPv4zero, false},
|
||||
}
|
||||
for _, c := range cases {
|
||||
assert.Equalf(t, c.expected, hl.MatchesHostOrIP(c.host, c.ip), "case %s(%v)", c.host, c.ip)
|
||||
}
|
||||
|
||||
hl = ParseHostMatchList("external")
|
||||
cases = []tc{
|
||||
{"", net.IPv4zero, false},
|
||||
{"", net.ParseIP("127.0.0.1"), false},
|
||||
{"", net.ParseIP("10.0.1.1"), false},
|
||||
{"", net.ParseIP("192.168.1.1"), false},
|
||||
{"", net.ParseIP("8.8.8.8"), true},
|
||||
|
||||
{"", net.ParseIP("::1"), false},
|
||||
{"", net.ParseIP("fd00::1"), false},
|
||||
{"", net.ParseIP("1000::1"), true},
|
||||
|
||||
{"mydomain.com", net.IPv4zero, false},
|
||||
}
|
||||
for _, c := range cases {
|
||||
assert.Equalf(t, c.expected, hl.MatchesHostOrIP(c.host, c.ip), "case %s(%v)", c.host, c.ip)
|
||||
}
|
||||
|
||||
hl = ParseHostMatchList("*")
|
||||
cases = []tc{
|
||||
{"", net.IPv4zero, true},
|
||||
{"", net.ParseIP("127.0.0.1"), true},
|
||||
{"", net.ParseIP("10.0.1.1"), true},
|
||||
{"", net.ParseIP("192.168.1.1"), true},
|
||||
{"", net.ParseIP("8.8.8.8"), true},
|
||||
|
||||
{"", net.ParseIP("::1"), true},
|
||||
{"", net.ParseIP("fd00::1"), true},
|
||||
{"", net.ParseIP("1000::1"), true},
|
||||
|
||||
{"mydomain.com", net.IPv4zero, true},
|
||||
}
|
||||
for _, c := range cases {
|
||||
assert.Equalf(t, c.expected, hl.MatchesHostOrIP(c.host, c.ip), "case %s(%v)", c.host, c.ip)
|
||||
}
|
||||
}
|
||||
@@ -174,6 +174,10 @@ func NewBleveIndexer(indexDir string) (*BleveIndexer, bool, error) {
|
||||
indexDir: indexDir,
|
||||
}
|
||||
created, err := indexer.init()
|
||||
if err != nil {
|
||||
indexer.Close()
|
||||
return nil, false, err
|
||||
}
|
||||
return indexer, created, err
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,10 @@ func NewElasticSearchIndexer(url, indexerName string) (*ElasticSearchIndexer, bo
|
||||
indexerAliasName: indexerName,
|
||||
}
|
||||
exists, err := indexer.init()
|
||||
|
||||
if err != nil {
|
||||
indexer.Close()
|
||||
return nil, false, err
|
||||
}
|
||||
return indexer, !exists, err
|
||||
}
|
||||
|
||||
|
||||
@@ -188,9 +188,6 @@ func Init() {
|
||||
|
||||
rIndexer, populate, err = NewBleveIndexer(setting.Indexer.RepoPath)
|
||||
if err != nil {
|
||||
if rIndexer != nil {
|
||||
rIndexer.Close()
|
||||
}
|
||||
cancel()
|
||||
indexer.Close()
|
||||
close(waitChannel)
|
||||
@@ -208,9 +205,6 @@ func Init() {
|
||||
|
||||
rIndexer, populate, err = NewElasticSearchIndexer(setting.Indexer.RepoConnStr, setting.Indexer.RepoIndexerName)
|
||||
if err != nil {
|
||||
if rIndexer != nil {
|
||||
rIndexer.Close()
|
||||
}
|
||||
cancel()
|
||||
indexer.Close()
|
||||
close(waitChannel)
|
||||
|
||||
@@ -27,7 +27,7 @@ func handle(data ...queue.Data) {
|
||||
}
|
||||
|
||||
func initStatsQueue() error {
|
||||
statsQueue = queue.CreateUniqueQueue("repo_stats_update", handle, int64(0)).(queue.UniqueQueue)
|
||||
statsQueue = queue.CreateUniqueQueue("repo_stats_update", handle, int64(0))
|
||||
if statsQueue == nil {
|
||||
return fmt.Errorf("Unable to create repo_stats_update Queue")
|
||||
}
|
||||
|
||||
@@ -29,9 +29,7 @@ func endpointFromCloneURL(rawurl string) *url.URL {
|
||||
return ep
|
||||
}
|
||||
|
||||
if strings.HasSuffix(ep.Path, "/") {
|
||||
ep.Path = ep.Path[:len(ep.Path)-1]
|
||||
}
|
||||
ep.Path = strings.TrimSuffix(ep.Path, "/")
|
||||
|
||||
if ep.Scheme == "file" {
|
||||
return ep
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gogit
|
||||
// +build gogit
|
||||
|
||||
package lfs
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !gogit
|
||||
// +build !gogit
|
||||
|
||||
package lfs
|
||||
|
||||
@@ -126,7 +126,7 @@ type Footnote struct {
|
||||
func (n *Footnote) Dump(source []byte, level int) {
|
||||
m := map[string]string{}
|
||||
m["Index"] = fmt.Sprintf("%v", n.Index)
|
||||
m["Ref"] = fmt.Sprintf("%s", n.Ref)
|
||||
m["Ref"] = string(n.Ref)
|
||||
m["Name"] = fmt.Sprintf("%v", n.Name)
|
||||
ast.DumpHelper(n, source, level, m, nil)
|
||||
}
|
||||
|
||||
@@ -109,6 +109,7 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate
|
||||
return err
|
||||
}
|
||||
r.DefaultBranch = repo.DefaultBranch
|
||||
r.Description = repo.Description
|
||||
|
||||
r, err = repository.MigrateRepositoryGitData(g.ctx, owner, r, base.MigrateOptions{
|
||||
RepoName: g.repoName,
|
||||
|
||||
@@ -89,7 +89,7 @@ func IsMigrateURLAllowed(remoteURL string, doer *models.User) error {
|
||||
return &models.ErrInvalidCloneAddr{Host: u.Host, NotResolvedIP: true}
|
||||
}
|
||||
for _, addr := range addrList {
|
||||
if isIPPrivate(addr) || !addr.IsGlobalUnicast() {
|
||||
if util.IsIPPrivate(addr) || !addr.IsGlobalUnicast() {
|
||||
return &models.ErrInvalidCloneAddr{Host: u.Host, PrivateNet: addr.String(), IsPermissionDenied: true}
|
||||
}
|
||||
}
|
||||
@@ -486,16 +486,3 @@ func Init() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isIPPrivate reports whether ip is a private address, according to
|
||||
// RFC 1918 (IPv4 addresses) and RFC 4193 (IPv6 addresses).
|
||||
// from https://github.com/golang/go/pull/42793
|
||||
// TODO remove if https://github.com/golang/go/issues/29146 got resolved
|
||||
func isIPPrivate(ip net.IP) bool {
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
return ip4[0] == 10 ||
|
||||
(ip4[0] == 172 && ip4[1]&0xf0 == 16) ||
|
||||
(ip4[0] == 192 && ip4[1] == 168)
|
||||
}
|
||||
return len(ip) == net.IPv6len && ip[0]&0xfe == 0xfc
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(doer *models.User, issue *model
|
||||
},
|
||||
Issue: convert.ToAPIIssue(issue),
|
||||
Repository: convert.ToRepo(issue.Repo, mode),
|
||||
Sender: convert.ToUser(issue.Poster, nil),
|
||||
Sender: convert.ToUser(doer, nil),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -766,12 +766,12 @@ func sendReleaseHook(doer *models.User, rel *models.Release, action api.HookRele
|
||||
return
|
||||
}
|
||||
|
||||
mode, _ := models.AccessLevel(rel.Publisher, rel.Repo)
|
||||
mode, _ := models.AccessLevel(doer, rel.Repo)
|
||||
if err := webhook_services.PrepareWebhooks(rel.Repo, models.HookEventRelease, &api.ReleasePayload{
|
||||
Action: action,
|
||||
Release: convert.ToRelease(rel),
|
||||
Repository: convert.ToRepo(rel.Repo, mode),
|
||||
Sender: convert.ToUser(rel.Publisher, nil),
|
||||
Sender: convert.ToUser(doer, nil),
|
||||
}); err != nil {
|
||||
log.Error("PrepareWebhooks: %v", err)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// +build !bindata
|
||||
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !bindata
|
||||
// +build !bindata
|
||||
|
||||
package options
|
||||
|
||||
import (
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//+build bindata
|
||||
//go:build bindata
|
||||
// +build bindata
|
||||
|
||||
package options
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build bindata
|
||||
// +build bindata
|
||||
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// +build !bindata
|
||||
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !bindata
|
||||
// +build !bindata
|
||||
|
||||
package public
|
||||
|
||||
import (
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//+build bindata
|
||||
//go:build bindata
|
||||
// +build bindata
|
||||
|
||||
package public
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user