mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-15 12:33:45 +09:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa1d9ef6cb | ||
|
|
20a75f86a1 | ||
|
|
c1c5e00d20 | ||
|
|
3e279dfb0b | ||
|
|
e9346fc4a9 | ||
|
|
b62e13a001 | ||
|
|
470b195da1 | ||
|
|
09178300b0 | ||
|
|
23aae3274a | ||
|
|
a98bf03204 | ||
|
|
65aef7b35f | ||
|
|
65ef634d5c | ||
|
|
869fd17b88 | ||
|
|
d624e91c0c | ||
|
|
62a3c847cd | ||
|
|
3a02f0896e | ||
|
|
408db95dc1 | ||
|
|
6305f07fdc | ||
|
|
ff9d99f63d | ||
|
|
37572551d7 | ||
|
|
0ee823be0b | ||
|
|
062ea40a79 | ||
|
|
7a25441abe | ||
|
|
dc71d00393 | ||
|
|
0bb56a413d | ||
|
|
2806a312e1 |
27
CHANGELOG.md
27
CHANGELOG.md
@@ -4,6 +4,33 @@ 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
|
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).
|
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||||
|
|
||||||
|
## [1.12.5](https://github.com/go-gitea/gitea/releases/tag/v1.12.5) - 2020-10-01
|
||||||
|
|
||||||
|
* BUGFIXES
|
||||||
|
* Allow U2F with default settings for gitea in subpath (#12990) (#13001)
|
||||||
|
* Prevent empty div when editing comment (#12404) (#12991)
|
||||||
|
* On mirror update also update address in DB (#12964) (#12967)
|
||||||
|
* Allow extended config on cron settings (#12939) (#12943)
|
||||||
|
* Open transaction when adding Avatar email-hash pairs to the DB (#12577) (#12940)
|
||||||
|
* Fix internal server error from ListUserOrgs API (#12910) (#12915)
|
||||||
|
* Update only the repository columns that need updating (#12900) (#12912)
|
||||||
|
* Fix panic when adding long comment (#12892) (#12894)
|
||||||
|
* Add size limit for content of comment on action ui (#12881) (#12890)
|
||||||
|
* Convert User expose ID each time (#12855) (#12883)
|
||||||
|
* Support slashes in release tags (#12864) (#12882)
|
||||||
|
* Add missing information to CreateRepo API endpoint (#12848) (#12867)
|
||||||
|
* On Migration respect old DefaultBranch (#12843) (#12858)
|
||||||
|
* Fix notifications page links (#12838) (#12853)
|
||||||
|
* Stop cloning unnecessarily on PR update (#12839) (#12852)
|
||||||
|
* Escape more things that are passed through str2html (#12622) (#12850)
|
||||||
|
* Remove double escape on labels addition in comments (#12809) (#12810)
|
||||||
|
* Fix "only mail on mention" bug (#12775) (#12789)
|
||||||
|
* Fix yet another bug with diff file names (#12771) (#12776)
|
||||||
|
* RepoInit Respect AlternateDefaultBranch (#12746) (#12751)
|
||||||
|
* Fix Avatar Resize (resize algo NearestNeighbor -> Bilinear) (#12745) (#12750)
|
||||||
|
* ENHANCEMENTS
|
||||||
|
* gitea dump: include version & Check InstallLock (#12760) (#12762)
|
||||||
|
|
||||||
## [1.12.4](https://github.com/go-gitea/gitea/releases/tag/v1.12.4) - 2020-09-02
|
## [1.12.4](https://github.com/go-gitea/gitea/releases/tag/v1.12.4) - 2020-09-02
|
||||||
|
|
||||||
* SECURITY
|
* SECURITY
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ func fatal(format string, args ...interface{}) {
|
|||||||
|
|
||||||
func runDump(ctx *cli.Context) error {
|
func runDump(ctx *cli.Context) error {
|
||||||
setting.NewContext()
|
setting.NewContext()
|
||||||
|
if !setting.InstallLock {
|
||||||
|
log.Error("Is '%s' really the right config path?\n", setting.CustomConf)
|
||||||
|
return fmt.Errorf("gitea is not initialized")
|
||||||
|
}
|
||||||
setting.NewServices() // cannot access session settings otherwise
|
setting.NewServices() // cannot access session settings otherwise
|
||||||
|
|
||||||
err := models.SetEngine()
|
err := models.SetEngine()
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -75,7 +75,7 @@ require (
|
|||||||
github.com/microcosm-cc/bluemonday v1.0.3-0.20191119130333-0a75d7616912
|
github.com/microcosm-cc/bluemonday v1.0.3-0.20191119130333-0a75d7616912
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
|
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
|
||||||
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||||
github.com/niklasfasching/go-org v0.1.9
|
github.com/niklasfasching/go-org v0.1.9
|
||||||
github.com/oliamb/cutter v0.2.2
|
github.com/oliamb/cutter v0.2.2
|
||||||
github.com/olivere/elastic/v7 v7.0.9
|
github.com/olivere/elastic/v7 v7.0.9
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -483,8 +483,8 @@ github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOl
|
|||||||
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc h1:z1PgdCCmYYVL0BoJTUgmAq1p7ca8fzYIPsNyfsN3xAU=
|
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc h1:z1PgdCCmYYVL0BoJTUgmAq1p7ca8fzYIPsNyfsN3xAU=
|
||||||
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc/go.mod h1:np1wUFZ6tyoke22qDJZY40URn9Ae51gX7ljIWXN5TJs=
|
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc/go.mod h1:np1wUFZ6tyoke22qDJZY40URn9Ae51gX7ljIWXN5TJs=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/niklasfasching/go-org v0.1.9 h1:Toz8WMIt+qJb52uYEk1YD/muLuOOmRt1CfkV+bKVMkI=
|
github.com/niklasfasching/go-org v0.1.9 h1:Toz8WMIt+qJb52uYEk1YD/muLuOOmRt1CfkV+bKVMkI=
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func TestAPIPullReview(t *testing.T) {
|
|||||||
assert.EqualValues(t, 10, reviews[5].ID)
|
assert.EqualValues(t, 10, reviews[5].ID)
|
||||||
assert.EqualValues(t, "REQUEST_CHANGES", reviews[5].State)
|
assert.EqualValues(t, "REQUEST_CHANGES", reviews[5].State)
|
||||||
assert.EqualValues(t, 1, reviews[5].CodeCommentsCount)
|
assert.EqualValues(t, 1, reviews[5].CodeCommentsCount)
|
||||||
assert.EqualValues(t, 0, reviews[5].Reviewer.ID) // ghost user
|
assert.EqualValues(t, -1, reviews[5].Reviewer.ID) // ghost user
|
||||||
assert.EqualValues(t, false, reviews[5].Stale)
|
assert.EqualValues(t, false, reviews[5].Stale)
|
||||||
assert.EqualValues(t, true, reviews[5].Official)
|
assert.EqualValues(t, true, reviews[5].Official)
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,12 @@
|
|||||||
package integrations
|
package integrations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -45,8 +48,14 @@ func TestAPIUserSearchNotLoggedIn(t *testing.T) {
|
|||||||
var results SearchResults
|
var results SearchResults
|
||||||
DecodeJSON(t, resp, &results)
|
DecodeJSON(t, resp, &results)
|
||||||
assert.NotEmpty(t, results.Data)
|
assert.NotEmpty(t, results.Data)
|
||||||
|
var modelUser *models.User
|
||||||
for _, user := range results.Data {
|
for _, user := range results.Data {
|
||||||
assert.Contains(t, user.UserName, query)
|
assert.Contains(t, user.UserName, query)
|
||||||
assert.Empty(t, user.Email)
|
modelUser = models.AssertExistsAndLoadBean(t, &models.User{ID: user.ID}).(*models.User)
|
||||||
|
if modelUser.KeepEmailPrivate {
|
||||||
|
assert.EqualValues(t, fmt.Sprintf("%s@%s", modelUser.LowerName, setting.Service.NoReplyAddress), user.Email)
|
||||||
|
} else {
|
||||||
|
assert.EqualValues(t, modelUser.Email, user.Email)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ func restoreOldDB(t *testing.T, version string) bool {
|
|||||||
|
|
||||||
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name))
|
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
db.Close()
|
||||||
|
|
||||||
db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?multiStatements=true",
|
db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?multiStatements=true",
|
||||||
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name))
|
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name))
|
||||||
@@ -182,6 +183,8 @@ func restoreOldDB(t *testing.T, version string) bool {
|
|||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema))
|
schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema))
|
||||||
if !assert.NoError(t, err) || !assert.NotEmpty(t, schrows) {
|
if !assert.NoError(t, err) || !assert.NotEmpty(t, schrows) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -41,7 +41,18 @@ func AvatarLink(email string) string {
|
|||||||
Email: lowerEmail,
|
Email: lowerEmail,
|
||||||
Hash: sum,
|
Hash: sum,
|
||||||
}
|
}
|
||||||
_, _ = x.Insert(emailHash)
|
// OK we're going to open a session just because I think that that might hide away any problems with postgres reporting errors
|
||||||
|
sess := x.NewSession()
|
||||||
|
defer sess.Close()
|
||||||
|
if err := sess.Begin(); err != nil {
|
||||||
|
// we don't care about any DB problem just return the lowerEmail
|
||||||
|
return lowerEmail, nil
|
||||||
|
}
|
||||||
|
_, _ = sess.Insert(emailHash)
|
||||||
|
if err := sess.Commit(); err != nil {
|
||||||
|
// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time
|
||||||
|
return lowerEmail, nil
|
||||||
|
}
|
||||||
return lowerEmail, nil
|
return lowerEmail, nil
|
||||||
})
|
})
|
||||||
return setting.AppSubURL + "/avatar/" + url.PathEscape(sum)
|
return setting.AppSubURL + "/avatar/" + url.PathEscape(sum)
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func addBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
func addBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
||||||
|
|
||||||
type ProtectedBranch struct {
|
type ProtectedBranch struct {
|
||||||
CanPush bool `xorm:"NOT NULL DEFAULT false"`
|
CanPush bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
EnableApprovalsWhitelist bool `xorm:"NOT NULL DEFAULT false"`
|
EnableApprovalsWhitelist bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
@@ -23,29 +22,26 @@ func addBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
|||||||
Official bool `xorm:"NOT NULL DEFAULT false"`
|
Official bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := x.NewSession()
|
if err := x.Sync2(new(ProtectedBranch)); err != nil {
|
||||||
defer sess.Close()
|
|
||||||
|
|
||||||
if err := sess.Sync2(new(ProtectedBranch)); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sess.Sync2(new(Review)); err != nil {
|
if err := x.Sync2(new(Review)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := sess.Exec("UPDATE `protected_branch` SET `enable_whitelist` = ? WHERE enable_whitelist IS NULL", false); err != nil {
|
if _, err := x.Exec("UPDATE `protected_branch` SET `enable_whitelist` = ? WHERE enable_whitelist IS NULL", false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := sess.Exec("UPDATE `protected_branch` SET `can_push` = `enable_whitelist`"); err != nil {
|
if _, err := x.Exec("UPDATE `protected_branch` SET `can_push` = `enable_whitelist`"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := sess.Exec("UPDATE `protected_branch` SET `enable_approvals_whitelist` = ? WHERE `required_approvals` > ?", true, 0); err != nil {
|
if _, err := x.Exec("UPDATE `protected_branch` SET `enable_approvals_whitelist` = ? WHERE `required_approvals` > ?", true, 0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var pageSize int64 = 20
|
var pageSize int64 = 20
|
||||||
qresult, err := sess.QueryInterface("SELECT max(id) as max_id FROM issue")
|
qresult, err := x.QueryInterface("SELECT max(id) as max_id FROM issue")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -57,10 +53,19 @@ func addBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
|||||||
}
|
}
|
||||||
totalPages := totalIssues / pageSize
|
totalPages := totalIssues / pageSize
|
||||||
|
|
||||||
|
sess := x.NewSession()
|
||||||
|
defer sess.Close()
|
||||||
|
|
||||||
|
if err := sess.Begin(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Find latest review of each user in each pull request, and set official field if appropriate
|
// Find latest review of each user in each pull request, and set official field if appropriate
|
||||||
reviews := []*models.Review{}
|
|
||||||
var page int64
|
var page int64
|
||||||
|
var count int
|
||||||
for page = 0; page <= totalPages; page++ {
|
for page = 0; page <= totalPages; page++ {
|
||||||
|
reviews := []*models.Review{}
|
||||||
if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id > ? AND issue_id <= ? AND type in (?, ?) GROUP BY issue_id, reviewer_id)",
|
if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id > ? AND issue_id <= ? AND type in (?, ?) GROUP BY issue_id, reviewer_id)",
|
||||||
page*pageSize, (page+1)*pageSize, models.ReviewTypeApprove, models.ReviewTypeReject).
|
page*pageSize, (page+1)*pageSize, models.ReviewTypeApprove, models.ReviewTypeReject).
|
||||||
Find(&reviews); err != nil {
|
Find(&reviews); err != nil {
|
||||||
@@ -68,23 +73,37 @@ func addBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, review := range reviews {
|
for _, review := range reviews {
|
||||||
if err := review.LoadAttributes(); err != nil {
|
if err := review.LoadAttributesX(sess); err != nil {
|
||||||
// Error might occur if user or issue doesn't exist, ignore it.
|
// Error might occur if user or issue doesn't exist, ignore it.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
official, err := models.IsOfficialReviewer(review.Issue, review.Reviewer)
|
official, err := models.IsOfficialReviewerX(sess, review.Issue, review.Reviewer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Branch might not be proteced or other error, ignore it.
|
// Branch might not be proteced or other error, ignore it.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
review.Official = official
|
review.Official = official
|
||||||
|
|
||||||
|
count++
|
||||||
|
|
||||||
if _, err := sess.ID(review.ID).Cols("official").Update(review); err != nil {
|
if _, err := sess.ID(review.ID).Cols("official").Update(review); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if count == 100 {
|
||||||
|
if err := sess.Commit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
count = 0
|
||||||
|
if err := sess.Begin(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if count > 0 {
|
||||||
|
|
||||||
return sess.Commit()
|
return sess.Commit()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,6 +264,17 @@ func DumpDatabase(filePath string, dbType string) error {
|
|||||||
}
|
}
|
||||||
tbs = append(tbs, t)
|
tbs = append(tbs, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Version struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
Version int64
|
||||||
|
}
|
||||||
|
t, err := x.TableInfo(Version{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tbs = append(tbs, t)
|
||||||
|
|
||||||
if len(dbType) > 0 {
|
if len(dbType) > 0 {
|
||||||
return x.DumpTablesToFile(tbs, filePath, schemas.DBType(dbType))
|
return x.DumpTablesToFile(tbs, filePath, schemas.DBType(dbType))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ func TestDumpDatabase(t *testing.T) {
|
|||||||
dir, err := ioutil.TempDir(os.TempDir(), "dump")
|
dir, err := ioutil.TempDir(os.TempDir(), "dump")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
type Version struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
Version int64
|
||||||
|
}
|
||||||
|
assert.NoError(t, x.Sync2(Version{}))
|
||||||
|
|
||||||
for _, dbName := range setting.SupportedDatabases {
|
for _, dbName := range setting.SupportedDatabases {
|
||||||
dbType := setting.GetDBTypeByName(dbName)
|
dbType := setting.GetDBTypeByName(dbName)
|
||||||
assert.NoError(t, DumpDatabase(filepath.Join(dir, dbType+".sql"), dbType))
|
assert.NoError(t, DumpDatabase(filepath.Join(dir, dbType+".sql"), dbType))
|
||||||
|
|||||||
@@ -110,7 +110,8 @@ func (r *Review) LoadReviewer() error {
|
|||||||
return r.loadReviewer(x)
|
return r.loadReviewer(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Review) loadAttributes(e Engine) (err error) {
|
// LoadAttributesX loads all attributes except CodeComments with an Engine parameter
|
||||||
|
func (r *Review) LoadAttributesX(e Engine) (err error) {
|
||||||
if err = r.loadIssue(e); err != nil {
|
if err = r.loadIssue(e); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -125,7 +126,7 @@ func (r *Review) loadAttributes(e Engine) (err error) {
|
|||||||
|
|
||||||
// LoadAttributes loads all attributes except CodeComments
|
// LoadAttributes loads all attributes except CodeComments
|
||||||
func (r *Review) LoadAttributes() error {
|
func (r *Review) LoadAttributes() error {
|
||||||
return r.loadAttributes(x)
|
return r.LoadAttributesX(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getReviewByID(e Engine, id int64) (*Review, error) {
|
func getReviewByID(e Engine, id int64) (*Review, error) {
|
||||||
@@ -203,6 +204,12 @@ func IsOfficialReviewer(issue *Issue, reviewer *User) (bool, error) {
|
|||||||
return isOfficialReviewer(x, issue, reviewer)
|
return isOfficialReviewer(x, issue, reviewer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsOfficialReviewerX check if reviewer can make official reviews in issue (counts towards required approvals)
|
||||||
|
// with an Engine parameter
|
||||||
|
func IsOfficialReviewerX(e Engine, issue *Issue, reviewer *User) (bool, error) {
|
||||||
|
return isOfficialReviewer(x, issue, reviewer)
|
||||||
|
}
|
||||||
|
|
||||||
func isOfficialReviewer(e Engine, issue *Issue, reviewer *User) (bool, error) {
|
func isOfficialReviewer(e Engine, issue *Issue, reviewer *User) (bool, error) {
|
||||||
pr, err := getPullRequestByIssueID(e, issue.ID)
|
pr, err := getPullRequestByIssueID(e, issue.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1418,11 +1418,21 @@ func getUserEmailsByNames(e Engine, names []string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetMaileableUsersByIDs gets users from ids, but only if they can receive mails
|
// GetMaileableUsersByIDs gets users from ids, but only if they can receive mails
|
||||||
func GetMaileableUsersByIDs(ids []int64) ([]*User, error) {
|
func GetMaileableUsersByIDs(ids []int64, isMention bool) ([]*User, error) {
|
||||||
if len(ids) == 0 {
|
if len(ids) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
ous := make([]*User, 0, len(ids))
|
ous := make([]*User, 0, len(ids))
|
||||||
|
|
||||||
|
if isMention {
|
||||||
|
return ous, x.In("id", ids).
|
||||||
|
Where("`type` = ?", UserTypeIndividual).
|
||||||
|
And("`prohibit_login` = ?", false).
|
||||||
|
And("`is_active` = ?", true).
|
||||||
|
And("`email_notifications_preference` IN ( ?, ?)", EmailNotificationsEnabled, EmailNotificationsOnMention).
|
||||||
|
Find(&ous)
|
||||||
|
}
|
||||||
|
|
||||||
return ous, x.In("id", ids).
|
return ous, x.In("id", ids).
|
||||||
Where("`type` = ?", UserTypeIndividual).
|
Where("`type` = ?", UserTypeIndividual).
|
||||||
And("`prohibit_login` = ?", false).
|
And("`prohibit_login` = ?", false).
|
||||||
|
|||||||
@@ -389,3 +389,20 @@ func TestGetUserIDsByNames(t *testing.T) {
|
|||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, []int64(nil), IDs)
|
assert.Equal(t, []int64(nil), IDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetMaileableUsersByIDs(t *testing.T) {
|
||||||
|
results, err := GetMaileableUsersByIDs([]int64{1, 4}, false)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 1, len(results))
|
||||||
|
if len(results) > 1 {
|
||||||
|
assert.Equal(t, results[0].ID, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
results, err = GetMaileableUsersByIDs([]int64{1, 4}, true)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 2, len(results))
|
||||||
|
if len(results) > 2 {
|
||||||
|
assert.Equal(t, results[0].ID, 1)
|
||||||
|
assert.Equal(t, results[1].ID, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -89,6 +89,6 @@ func Prepare(data []byte) (*image.Image, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img = resize.Resize(AvatarSize, AvatarSize, img, resize.NearestNeighbor)
|
img = resize.Resize(AvatarSize, AvatarSize, img, resize.Bilinear)
|
||||||
return &img, nil
|
return &img, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
@@ -335,9 +336,11 @@ func ToTeam(team *models.Team) *api.Team {
|
|||||||
// signed shall only be set if requester is logged in. authed shall only be set if user is site admin or user himself
|
// signed shall only be set if requester is logged in. authed shall only be set if user is site admin or user himself
|
||||||
func ToUser(user *models.User, signed, authed bool) *api.User {
|
func ToUser(user *models.User, signed, authed bool) *api.User {
|
||||||
result := &api.User{
|
result := &api.User{
|
||||||
|
ID: user.ID,
|
||||||
UserName: user.Name,
|
UserName: user.Name,
|
||||||
AvatarURL: user.AvatarLink(),
|
|
||||||
FullName: markup.Sanitize(user.FullName),
|
FullName: markup.Sanitize(user.FullName),
|
||||||
|
Email: user.GetEmail(),
|
||||||
|
AvatarURL: user.AvatarLink(),
|
||||||
Created: user.CreatedUnix.AsTime(),
|
Created: user.CreatedUnix.AsTime(),
|
||||||
}
|
}
|
||||||
// hide primary email if API caller is anonymous or user keep email private
|
// hide primary email if API caller is anonymous or user keep email private
|
||||||
@@ -346,7 +349,6 @@ func ToUser(user *models.User, signed, authed bool) *api.User {
|
|||||||
}
|
}
|
||||||
// only site admin will get these information and possibly user himself
|
// only site admin will get these information and possibly user himself
|
||||||
if authed {
|
if authed {
|
||||||
result.ID = user.ID
|
|
||||||
result.IsAdmin = user.IsAdmin
|
result.IsAdmin = user.IsAdmin
|
||||||
result.LastLogin = user.LastLoginUnix.AsTime()
|
result.LastLogin = user.LastLoginUnix.AsTime()
|
||||||
result.Language = user.Language
|
result.Language = user.Language
|
||||||
|
|||||||
@@ -16,4 +16,5 @@ type Repository struct {
|
|||||||
AuthPassword string
|
AuthPassword string
|
||||||
CloneURL string
|
CloneURL string
|
||||||
OriginalURL string
|
OriginalURL string
|
||||||
|
DefaultBranch string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
r.DefaultBranch = repo.DefaultBranch
|
||||||
|
|
||||||
r, err = repository.MigrateRepositoryGitData(g.doer, owner, r, structs.MigrateRepoOption{
|
r, err = repository.MigrateRepositoryGitData(g.doer, owner, r, structs.MigrateRepoOption{
|
||||||
RepoName: g.repoName,
|
RepoName: g.repoName,
|
||||||
|
|||||||
@@ -154,6 +154,11 @@ func (g *GithubDownloaderV3) GetRepoInfo() (*base.Repository, error) {
|
|||||||
}
|
}
|
||||||
g.rate = &resp.Rate
|
g.rate = &resp.Rate
|
||||||
|
|
||||||
|
defaultBranch := ""
|
||||||
|
if gr.DefaultBranch != nil {
|
||||||
|
defaultBranch = *gr.DefaultBranch
|
||||||
|
}
|
||||||
|
|
||||||
// convert github repo to stand Repo
|
// convert github repo to stand Repo
|
||||||
return &base.Repository{
|
return &base.Repository{
|
||||||
Owner: g.repoOwner,
|
Owner: g.repoOwner,
|
||||||
@@ -162,6 +167,7 @@ func (g *GithubDownloaderV3) GetRepoInfo() (*base.Repository, error) {
|
|||||||
Description: gr.GetDescription(),
|
Description: gr.GetDescription(),
|
||||||
OriginalURL: gr.GetHTMLURL(),
|
OriginalURL: gr.GetHTMLURL(),
|
||||||
CloneURL: gr.GetCloneURL(),
|
CloneURL: gr.GetCloneURL(),
|
||||||
|
DefaultBranch: defaultBranch,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
|||||||
Description: "Test repository for testing migration from github to gitea",
|
Description: "Test repository for testing migration from github to gitea",
|
||||||
CloneURL: "https://github.com/go-gitea/test_repo.git",
|
CloneURL: "https://github.com/go-gitea/test_repo.git",
|
||||||
OriginalURL: "https://github.com/go-gitea/test_repo",
|
OriginalURL: "https://github.com/go-gitea/test_repo",
|
||||||
|
DefaultBranch: "master",
|
||||||
}, repo)
|
}, repo)
|
||||||
|
|
||||||
topics, err := downloader.GetTopics()
|
topics, err := downloader.GetTopics()
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ func (g *GitlabDownloader) GetRepoInfo() (*base.Repository, error) {
|
|||||||
Description: gr.Description,
|
Description: gr.Description,
|
||||||
OriginalURL: gr.WebURL,
|
OriginalURL: gr.WebURL,
|
||||||
CloneURL: gr.HTTPURLToRepo,
|
CloneURL: gr.HTTPURLToRepo,
|
||||||
|
DefaultBranch: gr.DefaultBranch,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ func TestGitlabDownloadRepo(t *testing.T) {
|
|||||||
Description: "Test repository for testing migration from gitlab to gitea",
|
Description: "Test repository for testing migration from gitlab to gitea",
|
||||||
CloneURL: "https://gitlab.com/gitea/test_repo.git",
|
CloneURL: "https://gitlab.com/gitea/test_repo.git",
|
||||||
OriginalURL: "https://gitlab.com/gitea/test_repo",
|
OriginalURL: "https://gitlab.com/gitea/test_repo",
|
||||||
|
DefaultBranch: "master",
|
||||||
}, repo)
|
}, repo)
|
||||||
|
|
||||||
topics, err := downloader.GetTopics()
|
topics, err := downloader.GetTopics()
|
||||||
|
|||||||
@@ -92,13 +92,22 @@ func (a *actionNotifier) NotifyCreateIssueComment(doer *models.User, repo *model
|
|||||||
act := &models.Action{
|
act := &models.Action{
|
||||||
ActUserID: doer.ID,
|
ActUserID: doer.ID,
|
||||||
ActUser: doer,
|
ActUser: doer,
|
||||||
Content: fmt.Sprintf("%d|%s", issue.Index, comment.Content),
|
|
||||||
RepoID: issue.Repo.ID,
|
RepoID: issue.Repo.ID,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
Comment: comment,
|
Comment: comment,
|
||||||
CommentID: comment.ID,
|
CommentID: comment.ID,
|
||||||
IsPrivate: issue.Repo.IsPrivate,
|
IsPrivate: issue.Repo.IsPrivate,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
content := ""
|
||||||
|
|
||||||
|
if len(comment.Content) > 200 {
|
||||||
|
content = comment.Content[:strings.LastIndex(comment.Content[0:200], " ")] + "…"
|
||||||
|
} else {
|
||||||
|
content = comment.Content
|
||||||
|
}
|
||||||
|
act.Content = fmt.Sprintf("%d|%s", issue.Index, content)
|
||||||
|
|
||||||
if issue.IsPull {
|
if issue.IsPull {
|
||||||
act.OpType = models.ActionCommentPull
|
act.OpType = models.ActionCommentPull
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package public
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
@@ -159,7 +160,7 @@ func (opts *Options) handle(ctx *macaron.Context, log *log.Logger, opt *Options)
|
|||||||
// Add an Expires header to the static content
|
// Add an Expires header to the static content
|
||||||
if opt.ExpiresAfter > 0 {
|
if opt.ExpiresAfter > 0 {
|
||||||
ctx.Resp.Header().Set("Expires", time.Now().Add(opt.ExpiresAfter).UTC().Format(http.TimeFormat))
|
ctx.Resp.Header().Set("Expires", time.Now().Add(opt.ExpiresAfter).UTC().Format(http.TimeFormat))
|
||||||
tag := GenerateETag(string(fi.Size()), fi.Name(), fi.ModTime().UTC().Format(http.TimeFormat))
|
tag := GenerateETag(fmt.Sprint(fi.Size()), fi.Name(), fi.ModTime().UTC().Format(http.TimeFormat))
|
||||||
ctx.Resp.Header().Set("ETag", tag)
|
ctx.Resp.Header().Set("ETag", tag)
|
||||||
if ctx.Req.Header.Get("If-None-Match") == tag {
|
if ctx.Req.Header.Get("If-None-Match") == tag {
|
||||||
ctx.Resp.WriteHeader(304)
|
ctx.Resp.WriteHeader(304)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
@@ -176,7 +177,7 @@ func CommitRepoAction(optsList ...*CommitRepoActionOptions) error {
|
|||||||
var err error
|
var err error
|
||||||
if repo != nil {
|
if repo != nil {
|
||||||
// Change repository empty status and update last updated time.
|
// Change repository empty status and update last updated time.
|
||||||
if err := models.UpdateRepository(repo, false); err != nil {
|
if err := models.UpdateRepositoryUpdatedTime(repo.ID, time.Now()); err != nil {
|
||||||
return fmt.Errorf("UpdateRepository: %v", err)
|
return fmt.Errorf("UpdateRepository: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,6 +205,10 @@ func CommitRepoAction(optsList ...*CommitRepoActionOptions) error {
|
|||||||
}
|
}
|
||||||
gitRepo.Close()
|
gitRepo.Close()
|
||||||
}
|
}
|
||||||
|
// Update the is empty and default_branch columns
|
||||||
|
if err := models.UpdateRepositoryCols(repo, "default_branch", "is_empty"); err != nil {
|
||||||
|
return fmt.Errorf("UpdateRepositoryCols: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opType := models.ActionCommitRepo
|
opType := models.ActionCommitRepo
|
||||||
@@ -274,7 +279,7 @@ func CommitRepoAction(optsList ...*CommitRepoActionOptions) error {
|
|||||||
|
|
||||||
if repo != nil {
|
if repo != nil {
|
||||||
// Change repository empty status and update last updated time.
|
// Change repository empty status and update last updated time.
|
||||||
if err := models.UpdateRepository(repo, false); err != nil {
|
if err := models.UpdateRepositoryUpdatedTime(repo.ID, time.Now()); err != nil {
|
||||||
return fmt.Errorf("UpdateRepository: %v", err)
|
return fmt.Errorf("UpdateRepository: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (_ *m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(opts.DefaultBranch) == 0 {
|
||||||
|
opts.DefaultBranch = setting.Repository.DefaultBranch
|
||||||
|
}
|
||||||
|
|
||||||
repo := &models.Repository{
|
repo := &models.Repository{
|
||||||
OwnerID: u.ID,
|
OwnerID: u.ID,
|
||||||
Owner: u,
|
Owner: u,
|
||||||
|
|||||||
@@ -102,7 +102,8 @@ func MigrateRepositoryGitData(doer, u *models.User, repo *models.Repository, opt
|
|||||||
return repo, fmt.Errorf("git.IsEmpty: %v", err)
|
return repo, fmt.Errorf("git.IsEmpty: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !opts.Releases && !repo.IsEmpty {
|
if !repo.IsEmpty {
|
||||||
|
if len(repo.DefaultBranch) == 0 {
|
||||||
// Try to get HEAD branch and set it as default branch.
|
// Try to get HEAD branch and set it as default branch.
|
||||||
headBranch, err := gitRepo.GetHEADBranch()
|
headBranch, err := gitRepo.GetHEADBranch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -111,11 +112,14 @@ func MigrateRepositoryGitData(doer, u *models.User, repo *models.Repository, opt
|
|||||||
if headBranch != nil {
|
if headBranch != nil {
|
||||||
repo.DefaultBranch = headBranch.Name
|
repo.DefaultBranch = headBranch.Name
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !opts.Releases {
|
||||||
if err = SyncReleasesWithTags(repo, gitRepo); err != nil {
|
if err = SyncReleasesWithTags(repo, gitRepo); err != nil {
|
||||||
log.Error("Failed to synchronize tags to releases for repository: %v", err)
|
log.Error("Failed to synchronize tags to releases for repository: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err = repo.UpdateSize(models.DefaultDBContext()); err != nil {
|
if err = repo.UpdateSize(models.DefaultDBContext()); err != nil {
|
||||||
log.Error("Failed to update size for repository: %v", err)
|
log.Error("Failed to update size for repository: %v", err)
|
||||||
|
|||||||
@@ -4,8 +4,26 @@
|
|||||||
|
|
||||||
package setting
|
package setting
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
// GetCronSettings maps the cron subsection to the provided config
|
// GetCronSettings maps the cron subsection to the provided config
|
||||||
func GetCronSettings(name string, config interface{}) (interface{}, error) {
|
func GetCronSettings(name string, config interface{}) (interface{}, error) {
|
||||||
err := Cfg.Section("cron." + name).MapTo(config)
|
if err := Cfg.Section("cron." + name).MapTo(config); err != nil {
|
||||||
return config, err
|
return config, err
|
||||||
|
}
|
||||||
|
|
||||||
|
typ := reflect.TypeOf(config).Elem()
|
||||||
|
val := reflect.ValueOf(config).Elem()
|
||||||
|
|
||||||
|
for i := 0; i < typ.NumField(); i++ {
|
||||||
|
field := val.Field(i)
|
||||||
|
tpField := typ.Field(i)
|
||||||
|
if tpField.Type.Kind() == reflect.Struct && tpField.Anonymous {
|
||||||
|
if err := Cfg.Section("cron." + name).MapTo(field.Addr().Interface()); err != nil {
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|||||||
47
modules/setting/cron_test.go
Normal file
47
modules/setting/cron_test.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2020 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 setting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
ini "gopkg.in/ini.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_GetCronSettings(t *testing.T) {
|
||||||
|
|
||||||
|
type BaseStruct struct {
|
||||||
|
Base bool
|
||||||
|
Second string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Extended struct {
|
||||||
|
BaseStruct
|
||||||
|
Extend bool
|
||||||
|
}
|
||||||
|
|
||||||
|
iniStr := `
|
||||||
|
[cron.test]
|
||||||
|
Base = true
|
||||||
|
Second = white rabbit
|
||||||
|
Extend = true
|
||||||
|
`
|
||||||
|
Cfg, _ = ini.Load([]byte(iniStr))
|
||||||
|
|
||||||
|
extended := &Extended{
|
||||||
|
BaseStruct: BaseStruct{
|
||||||
|
Second: "queen of hearts",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := GetCronSettings("test", extended)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, extended.Base)
|
||||||
|
assert.EqualValues(t, extended.Second, "white rabbit")
|
||||||
|
assert.True(t, extended.Extend)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1032,8 +1032,8 @@ func NewContext() {
|
|||||||
newMarkup()
|
newMarkup()
|
||||||
|
|
||||||
sec = Cfg.Section("U2F")
|
sec = Cfg.Section("U2F")
|
||||||
U2F.TrustedFacets, _ = shellquote.Split(sec.Key("TRUSTED_FACETS").MustString(strings.TrimRight(AppURL, "/")))
|
U2F.TrustedFacets, _ = shellquote.Split(sec.Key("TRUSTED_FACETS").MustString(strings.TrimSuffix(AppURL, AppSubURL+"/")))
|
||||||
U2F.AppID = sec.Key("APP_ID").MustString(strings.TrimRight(AppURL, "/"))
|
U2F.AppID = sec.Key("APP_ID").MustString(strings.TrimSuffix(AppURL, "/"))
|
||||||
|
|
||||||
zip.Verbose = false
|
zip.Verbose = false
|
||||||
|
|
||||||
|
|||||||
@@ -619,7 +619,7 @@ func ActionContent2Commits(act Actioner) *repository.PushCommits {
|
|||||||
// DiffTypeToStr returns diff type name
|
// DiffTypeToStr returns diff type name
|
||||||
func DiffTypeToStr(diffType int) string {
|
func DiffTypeToStr(diffType int) string {
|
||||||
diffTypes := map[int]string{
|
diffTypes := map[int]string{
|
||||||
1: "add", 2: "modify", 3: "del", 4: "rename",
|
1: "add", 2: "modify", 3: "del", 4: "rename", 5: "copy",
|
||||||
}
|
}
|
||||||
return diffTypes[diffType]
|
return diffTypes[diffType]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ func ListUserOrgs(ctx *context.APIContext) {
|
|||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
listUserOrgs(ctx, u, ctx.User.IsAdmin)
|
listUserOrgs(ctx, u, ctx.User != nil && (ctx.User.IsAdmin || ctx.User.ID == u.ID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAll return list of all public organizations
|
// GetAll return list of all public organizations
|
||||||
|
|||||||
@@ -256,6 +256,12 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reload repo from db to get a real state after creation
|
||||||
|
repo, err = models.GetRepositoryByID(repo.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetRepositoryByID", err)
|
||||||
|
}
|
||||||
|
|
||||||
ctx.JSON(http.StatusCreated, repo.APIFormat(models.AccessModeOwner))
|
ctx.JSON(http.StatusCreated, repo.APIFormat(models.AccessModeOwner))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1956,7 +1956,7 @@ func updateAttachments(item interface{}, files []string) error {
|
|||||||
case *models.Comment:
|
case *models.Comment:
|
||||||
attachments = content.Attachments
|
attachments = content.Attachments
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknow Type")
|
return fmt.Errorf("Unknown Type: %T", content)
|
||||||
}
|
}
|
||||||
for i := 0; i < len(attachments); i++ {
|
for i := 0; i < len(attachments); i++ {
|
||||||
if util.IsStringInSlice(attachments[i].UUID, files) {
|
if util.IsStringInSlice(attachments[i].UUID, files) {
|
||||||
@@ -1974,7 +1974,7 @@ func updateAttachments(item interface{}, files []string) error {
|
|||||||
case *models.Comment:
|
case *models.Comment:
|
||||||
err = content.UpdateAttachments(files)
|
err = content.UpdateAttachments(files)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknow Type")
|
return fmt.Errorf("Unknown Type: %T", content)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -1986,7 +1986,7 @@ func updateAttachments(item interface{}, files []string) error {
|
|||||||
case *models.Comment:
|
case *models.Comment:
|
||||||
content.Attachments, err = models.GetAttachmentsByCommentID(content.ID)
|
content.Attachments, err = models.GetAttachmentsByCommentID(content.ID)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknow Type")
|
return fmt.Errorf("Unknown Type: %T", content)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ func SingleRelease(ctx *context.Context) {
|
|||||||
writeAccess := ctx.Repo.CanWrite(models.UnitTypeReleases)
|
writeAccess := ctx.Repo.CanWrite(models.UnitTypeReleases)
|
||||||
ctx.Data["CanCreateRelease"] = writeAccess && !ctx.Repo.Repository.IsArchived
|
ctx.Data["CanCreateRelease"] = writeAccess && !ctx.Repo.Repository.IsArchived
|
||||||
|
|
||||||
release, err := models.GetRelease(ctx.Repo.Repository.ID, ctx.Params("tag"))
|
release, err := models.GetRelease(ctx.Repo.Repository.ID, ctx.Params("*"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrReleaseNotExist(err) {
|
if models.IsErrReleaseNotExist(err) {
|
||||||
ctx.NotFound("GetRelease", err)
|
ctx.NotFound("GetRelease", err)
|
||||||
|
|||||||
@@ -185,8 +185,8 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
|||||||
|
|
||||||
address = u.String()
|
address = u.String()
|
||||||
|
|
||||||
if err := mirror_service.SaveAddress(ctx.Repo.Mirror, address); err != nil {
|
if err := mirror_service.UpdateAddress(ctx.Repo.Mirror, address); err != nil {
|
||||||
ctx.ServerError("SaveAddress", err)
|
ctx.ServerError("UpdateAddress", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -814,9 +814,9 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||||||
m.Group("/:username/:reponame", func() {
|
m.Group("/:username/:reponame", func() {
|
||||||
m.Group("/releases", func() {
|
m.Group("/releases", func() {
|
||||||
m.Get("/", repo.Releases)
|
m.Get("/", repo.Releases)
|
||||||
m.Get("/tag/:tag", repo.SingleRelease)
|
m.Get("/tag/*", repo.SingleRelease)
|
||||||
m.Get("/latest", repo.LatestRelease)
|
m.Get("/latest", repo.LatestRelease)
|
||||||
}, repo.MustBeNotEmpty, context.RepoRef())
|
}, repo.MustBeNotEmpty, context.RepoRefByType(context.RepoRefTag))
|
||||||
m.Group("/releases", func() {
|
m.Group("/releases", func() {
|
||||||
m.Get("/new", repo.NewRelease)
|
m.Get("/new", repo.NewRelease)
|
||||||
m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost)
|
m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost)
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ func NotificationStatusPost(c *context.Context) {
|
|||||||
if c.Written() {
|
if c.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
c.Data["Link"] = fmt.Sprintf("%snotifications", setting.AppURL)
|
||||||
|
|
||||||
c.HTML(http.StatusOK, tplNotificationDiv)
|
c.HTML(http.StatusOK, tplNotificationDiv)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package user
|
|||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -271,8 +272,8 @@ func AuthorizeOAuth(ctx *context.Context, form auth.AuthorizationForm) {
|
|||||||
ctx.Data["Application"] = app
|
ctx.Data["Application"] = app
|
||||||
ctx.Data["RedirectURI"] = form.RedirectURI
|
ctx.Data["RedirectURI"] = form.RedirectURI
|
||||||
ctx.Data["State"] = form.State
|
ctx.Data["State"] = form.State
|
||||||
ctx.Data["ApplicationUserLink"] = "<a href=\"" + setting.AppURL + app.User.LowerName + "\">@" + app.User.Name + "</a>"
|
ctx.Data["ApplicationUserLink"] = "<a href=\"" + html.EscapeString(setting.AppURL) + html.EscapeString(url.PathEscape(app.User.LowerName)) + "\">@" + html.EscapeString(app.User.Name) + "</a>"
|
||||||
ctx.Data["ApplicationRedirectDomainHTML"] = "<strong>" + form.RedirectURI + "</strong>"
|
ctx.Data["ApplicationRedirectDomainHTML"] = "<strong>" + html.EscapeString(form.RedirectURI) + "</strong>"
|
||||||
// TODO document SESSION <=> FORM
|
// TODO document SESSION <=> FORM
|
||||||
err = ctx.Session.Set("client_id", app.ClientID)
|
err = ctx.Session.Set("client_id", app.ClientID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ const (
|
|||||||
DiffFileChange
|
DiffFileChange
|
||||||
DiffFileDel
|
DiffFileDel
|
||||||
DiffFileRename
|
DiffFileRename
|
||||||
|
DiffFileCopy
|
||||||
)
|
)
|
||||||
|
|
||||||
// DiffLineExpandDirection represents the DiffLineSection expand direction
|
// DiffLineExpandDirection represents the DiffLineSection expand direction
|
||||||
@@ -447,7 +448,46 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
|
|||||||
}
|
}
|
||||||
line := linebuf.String()
|
line := linebuf.String()
|
||||||
|
|
||||||
if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") || len(line) == 0 {
|
if strings.HasPrefix(line, "--- ") {
|
||||||
|
if line[4] == '"' {
|
||||||
|
fmt.Sscanf(line[4:], "%q", &curFile.OldName)
|
||||||
|
} else {
|
||||||
|
curFile.OldName = line[4:]
|
||||||
|
if strings.Contains(curFile.OldName, " ") {
|
||||||
|
// Git adds a terminal \t if there is a space in the name
|
||||||
|
curFile.OldName = curFile.OldName[:len(curFile.OldName)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if curFile.OldName[0:2] == "a/" {
|
||||||
|
curFile.OldName = curFile.OldName[2:]
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
} else if strings.HasPrefix(line, "+++ ") {
|
||||||
|
if line[4] == '"' {
|
||||||
|
fmt.Sscanf(line[4:], "%q", &curFile.Name)
|
||||||
|
} else {
|
||||||
|
curFile.Name = line[4:]
|
||||||
|
if strings.Contains(curFile.Name, " ") {
|
||||||
|
// Git adds a terminal \t if there is a space in the name
|
||||||
|
curFile.Name = curFile.Name[:len(curFile.Name)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if curFile.Name[0:2] == "b/" {
|
||||||
|
curFile.Name = curFile.Name[2:]
|
||||||
|
}
|
||||||
|
curFile.IsRenamed = (curFile.Name != curFile.OldName) && !(curFile.IsCreated || curFile.IsDeleted)
|
||||||
|
if curFile.IsDeleted {
|
||||||
|
curFile.Name = curFile.OldName
|
||||||
|
curFile.OldName = ""
|
||||||
|
} else if curFile.IsCreated {
|
||||||
|
curFile.OldName = ""
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
} else if len(line) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(line, "+++") || strings.HasPrefix(line, "---") || len(line) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,36 +571,10 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: In case file name is surrounded by double quotes (it happens only in git-shell).
|
|
||||||
// e.g. diff --git "a/xxx" "b/xxx"
|
|
||||||
var a string
|
|
||||||
var b string
|
|
||||||
|
|
||||||
rd := strings.NewReader(line[len(cmdDiffHead):])
|
|
||||||
char, _ := rd.ReadByte()
|
|
||||||
_ = rd.UnreadByte()
|
|
||||||
if char == '"' {
|
|
||||||
fmt.Fscanf(rd, "%q ", &a)
|
|
||||||
} else {
|
|
||||||
fmt.Fscanf(rd, "%s ", &a)
|
|
||||||
}
|
|
||||||
char, _ = rd.ReadByte()
|
|
||||||
_ = rd.UnreadByte()
|
|
||||||
if char == '"' {
|
|
||||||
fmt.Fscanf(rd, "%q", &b)
|
|
||||||
} else {
|
|
||||||
fmt.Fscanf(rd, "%s", &b)
|
|
||||||
}
|
|
||||||
a = a[2:]
|
|
||||||
b = b[2:]
|
|
||||||
|
|
||||||
curFile = &DiffFile{
|
curFile = &DiffFile{
|
||||||
Name: b,
|
|
||||||
OldName: a,
|
|
||||||
Index: len(diff.Files) + 1,
|
Index: len(diff.Files) + 1,
|
||||||
Type: DiffFileChange,
|
Type: DiffFileChange,
|
||||||
Sections: make([]*DiffSection, 0, 10),
|
Sections: make([]*DiffSection, 0, 10),
|
||||||
IsRenamed: a != b,
|
|
||||||
}
|
}
|
||||||
diff.Files = append(diff.Files, curFile)
|
diff.Files = append(diff.Files, curFile)
|
||||||
curFileLinesCount = 0
|
curFileLinesCount = 0
|
||||||
@@ -569,6 +583,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
|
|||||||
curFileLFSPrefix = false
|
curFileLFSPrefix = false
|
||||||
|
|
||||||
// Check file diff type and is submodule.
|
// Check file diff type and is submodule.
|
||||||
|
loop:
|
||||||
for {
|
for {
|
||||||
line, err := input.ReadString('\n')
|
line, err := input.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -579,6 +594,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if curFile.Type != DiffFileRename {
|
||||||
switch {
|
switch {
|
||||||
case strings.HasPrefix(line, "new file"):
|
case strings.HasPrefix(line, "new file"):
|
||||||
curFile.Type = DiffFileAdd
|
curFile.Type = DiffFileAdd
|
||||||
@@ -591,12 +607,55 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
|
|||||||
case strings.HasPrefix(line, "similarity index 100%"):
|
case strings.HasPrefix(line, "similarity index 100%"):
|
||||||
curFile.Type = DiffFileRename
|
curFile.Type = DiffFileRename
|
||||||
}
|
}
|
||||||
if curFile.Type > 0 {
|
if curFile.Type > 0 && curFile.Type != DiffFileRename {
|
||||||
if strings.HasSuffix(line, " 160000\n") {
|
if strings.HasSuffix(line, " 160000\n") {
|
||||||
curFile.IsSubmodule = true
|
curFile.IsSubmodule = true
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(line, "rename from "):
|
||||||
|
if line[12] == '"' {
|
||||||
|
fmt.Sscanf(line[12:], "%q", &curFile.OldName)
|
||||||
|
} else {
|
||||||
|
curFile.OldName = line[12:]
|
||||||
|
curFile.OldName = curFile.OldName[:len(curFile.OldName)-1]
|
||||||
|
}
|
||||||
|
case strings.HasPrefix(line, "rename to "):
|
||||||
|
if line[10] == '"' {
|
||||||
|
fmt.Sscanf(line[10:], "%q", &curFile.Name)
|
||||||
|
} else {
|
||||||
|
curFile.Name = line[10:]
|
||||||
|
curFile.Name = curFile.Name[:len(curFile.Name)-1]
|
||||||
|
}
|
||||||
|
curFile.IsRenamed = true
|
||||||
|
break loop
|
||||||
|
case strings.HasPrefix(line, "copy from "):
|
||||||
|
if line[10] == '"' {
|
||||||
|
fmt.Sscanf(line[10:], "%q", &curFile.OldName)
|
||||||
|
} else {
|
||||||
|
curFile.OldName = line[10:]
|
||||||
|
curFile.OldName = curFile.OldName[:len(curFile.OldName)-1]
|
||||||
|
}
|
||||||
|
case strings.HasPrefix(line, "copy to "):
|
||||||
|
if line[8] == '"' {
|
||||||
|
fmt.Sscanf(line[8:], "%q", &curFile.Name)
|
||||||
|
} else {
|
||||||
|
curFile.Name = line[8:]
|
||||||
|
curFile.Name = curFile.Name[:len(curFile.Name)-1]
|
||||||
|
}
|
||||||
|
curFile.IsRenamed = true
|
||||||
|
curFile.Type = DiffFileCopy
|
||||||
|
break loop
|
||||||
|
default:
|
||||||
|
if strings.HasSuffix(line, " 160000\n") {
|
||||||
|
curFile.IsSubmodule = true
|
||||||
|
} else {
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package gitdiff
|
package gitdiff
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -41,7 +42,145 @@ func TestDiffToHTML(t *testing.T) {
|
|||||||
}, DiffLineDel))
|
}, DiffLineDel))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParsePatch(t *testing.T) {
|
func TestParsePatch_singlefile(t *testing.T) {
|
||||||
|
type testcase struct {
|
||||||
|
name string
|
||||||
|
gitdiff string
|
||||||
|
wantErr bool
|
||||||
|
addition int
|
||||||
|
deletion int
|
||||||
|
oldFilename string
|
||||||
|
filename string
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []testcase{
|
||||||
|
{
|
||||||
|
name: "readme.md2readme.md",
|
||||||
|
gitdiff: `diff --git "a/README.md" "b/README.md"
|
||||||
|
--- a/README.md
|
||||||
|
+++ b/README.md
|
||||||
|
@@ -1,3 +1,6 @@
|
||||||
|
# gitea-github-migrator
|
||||||
|
+
|
||||||
|
+ Build Status
|
||||||
|
- Latest Release
|
||||||
|
Docker Pulls
|
||||||
|
+ cut off
|
||||||
|
+ cut off
|
||||||
|
`,
|
||||||
|
addition: 4,
|
||||||
|
deletion: 1,
|
||||||
|
filename: "README.md",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "A \\ B",
|
||||||
|
gitdiff: `diff --git "a/A \\ B" "b/A \\ B"
|
||||||
|
--- "a/A \\ B"
|
||||||
|
+++ "b/A \\ B"
|
||||||
|
@@ -1,3 +1,6 @@
|
||||||
|
# gitea-github-migrator
|
||||||
|
+
|
||||||
|
+ Build Status
|
||||||
|
- Latest Release
|
||||||
|
Docker Pulls
|
||||||
|
+ cut off
|
||||||
|
+ cut off`,
|
||||||
|
addition: 4,
|
||||||
|
deletion: 1,
|
||||||
|
filename: "A \\ B",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "really weird filename",
|
||||||
|
gitdiff: `diff --git a/a b/file b/a a/file b/a b/file b/a a/file
|
||||||
|
index d2186f1..f5c8ed2 100644
|
||||||
|
--- a/a b/file b/a a/file
|
||||||
|
+++ b/a b/file b/a a/file
|
||||||
|
@@ -1,3 +1,2 @@
|
||||||
|
Create a weird file.
|
||||||
|
|
||||||
|
-and what does diff do here?
|
||||||
|
\ No newline at end of file`,
|
||||||
|
addition: 0,
|
||||||
|
deletion: 1,
|
||||||
|
filename: "a b/file b/a a/file",
|
||||||
|
oldFilename: "a b/file b/a a/file",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "delete file with blanks",
|
||||||
|
gitdiff: `diff --git a/file with blanks b/file with blanks
|
||||||
|
deleted file mode 100644
|
||||||
|
index 898651a..0000000
|
||||||
|
--- a/file with blanks
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,5 +0,0 @@
|
||||||
|
-a blank file
|
||||||
|
-
|
||||||
|
-has a couple o line
|
||||||
|
-
|
||||||
|
-the 5th line is the last
|
||||||
|
`,
|
||||||
|
addition: 0,
|
||||||
|
deletion: 5,
|
||||||
|
filename: "file with blanks",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "rename a—as",
|
||||||
|
gitdiff: `diff --git "a/\360\243\220\265b\342\200\240vs" "b/a\342\200\224as"
|
||||||
|
similarity index 100%
|
||||||
|
rename from "\360\243\220\265b\342\200\240vs"
|
||||||
|
rename to "a\342\200\224as"
|
||||||
|
`,
|
||||||
|
addition: 0,
|
||||||
|
deletion: 0,
|
||||||
|
oldFilename: "𣐵b†vs",
|
||||||
|
filename: "a—as",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "rename with spaces",
|
||||||
|
gitdiff: `diff --git a/a b/file b/a a/file b/a b/a a/file b/b file
|
||||||
|
similarity index 100%
|
||||||
|
rename from a b/file b/a a/file
|
||||||
|
rename to a b/a a/file b/b file
|
||||||
|
`,
|
||||||
|
oldFilename: "a b/file b/a a/file",
|
||||||
|
filename: "a b/a a/file b/b file",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testcase := range tests {
|
||||||
|
t.Run(testcase.name, func(t *testing.T) {
|
||||||
|
got, err := ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff))
|
||||||
|
if (err != nil) != testcase.wantErr {
|
||||||
|
t.Errorf("ParsePatch() error = %v, wantErr %v", err, testcase.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
gotMarshaled, _ := json.MarshalIndent(got, " ", " ")
|
||||||
|
if got.NumFiles() != 1 {
|
||||||
|
t.Errorf("ParsePath() did not receive 1 file:\n%s", string(gotMarshaled))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got.TotalAddition != testcase.addition {
|
||||||
|
t.Errorf("ParsePath() does not have correct totalAddition %d, wanted %d", got.TotalAddition, testcase.addition)
|
||||||
|
}
|
||||||
|
if got.TotalDeletion != testcase.deletion {
|
||||||
|
t.Errorf("ParsePath() did not have correct totalDeletion %d, wanted %d", got.TotalDeletion, testcase.deletion)
|
||||||
|
}
|
||||||
|
file := got.Files[0]
|
||||||
|
if file.Addition != testcase.addition {
|
||||||
|
t.Errorf("ParsePath() does not have correct file addition %d, wanted %d", file.Addition, testcase.addition)
|
||||||
|
}
|
||||||
|
if file.Deletion != testcase.deletion {
|
||||||
|
t.Errorf("ParsePath() did not have correct file deletion %d, wanted %d", file.Deletion, testcase.deletion)
|
||||||
|
}
|
||||||
|
if file.OldName != testcase.oldFilename {
|
||||||
|
t.Errorf("ParsePath() did not have correct OldName %s, wanted %s", file.OldName, testcase.oldFilename)
|
||||||
|
}
|
||||||
|
if file.Name != testcase.filename {
|
||||||
|
t.Errorf("ParsePath() did not have correct Name %s, wanted %s", file.Name, testcase.filename)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
var diff = `diff --git "a/README.md" "b/README.md"
|
var diff = `diff --git "a/README.md" "b/README.md"
|
||||||
--- a/README.md
|
--- a/README.md
|
||||||
+++ b/README.md
|
+++ b/README.md
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ func mailIssueCommentBatch(ctx *mailCommentContext, ids []int64, visited map[int
|
|||||||
visited[id] = true
|
visited[id] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
recipients, err := models.GetMaileableUsersByIDs(unique)
|
recipients, err := models.GetMaileableUsersByIDs(unique, fromMention)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ func AddressNoCredentials(m *models.Mirror) string {
|
|||||||
return u.String()
|
return u.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveAddress writes new address to Git repository config.
|
// UpdateAddress writes new address to Git repository and database
|
||||||
func SaveAddress(m *models.Mirror, addr string) error {
|
func UpdateAddress(m *models.Mirror, addr string) error {
|
||||||
repoPath := m.Repo.RepoPath()
|
repoPath := m.Repo.RepoPath()
|
||||||
// Remove old origin
|
// Remove old origin
|
||||||
_, err := git.NewCommand("remote", "rm", "origin").RunInDir(repoPath)
|
_, err := git.NewCommand("remote", "rm", "origin").RunInDir(repoPath)
|
||||||
@@ -99,8 +99,12 @@ func SaveAddress(m *models.Mirror, addr string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = git.NewCommand("remote", "add", "origin", "--mirror=fetch", addr).RunInDir(repoPath)
|
if _, err = git.NewCommand("remote", "add", "origin", "--mirror=fetch", addr).RunInDir(repoPath); err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Repo.OriginalURL = addr
|
||||||
|
return models.UpdateRepositoryCols(m.Repo, "original_url")
|
||||||
}
|
}
|
||||||
|
|
||||||
// gitShortEmptySha Git short empty SHA
|
// gitShortEmptySha Git short empty SHA
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -177,18 +175,6 @@ func checkForInvalidation(requests models.PullRequestList, repoID int64, doer *m
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addHeadRepoTasks(prs []*models.PullRequest) {
|
|
||||||
for _, pr := range prs {
|
|
||||||
log.Trace("addHeadRepoTasks[%d]: composing new test task", pr.ID)
|
|
||||||
if err := PushToBaseRepo(pr); err != nil {
|
|
||||||
log.Error("PushToBaseRepo: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
AddToTaskQueue(pr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddTestPullRequestTask adds new test tasks by given head/base repository and head/base branch,
|
// AddTestPullRequestTask adds new test tasks by given head/base repository and head/base branch,
|
||||||
// and generate new patch for testing as needed.
|
// and generate new patch for testing as needed.
|
||||||
func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSync bool, oldCommitID, newCommitID string) {
|
func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSync bool, oldCommitID, newCommitID string) {
|
||||||
@@ -245,7 +231,15 @@ func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addHeadRepoTasks(prs)
|
for _, pr := range prs {
|
||||||
|
log.Trace("Updating PR[%d]: composing new test task", pr.ID)
|
||||||
|
if err := PushToBaseRepo(pr); err != nil {
|
||||||
|
log.Error("PushToBaseRepo: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
AddToTaskQueue(pr)
|
||||||
|
}
|
||||||
|
|
||||||
log.Trace("AddTestPullRequestTask [base_repo_id: %d, base_branch: %s]: finding pull requests", repoID, branch)
|
log.Trace("AddTestPullRequestTask [base_repo_id: %d, base_branch: %s]: finding pull requests", repoID, branch)
|
||||||
prs, err = models.GetUnmergedPullRequestsByBaseInfo(repoID, branch)
|
prs, err = models.GetUnmergedPullRequestsByBaseInfo(repoID, branch)
|
||||||
@@ -345,54 +339,17 @@ func checkIfPRContentChanged(pr *models.PullRequest, oldCommitID, newCommitID st
|
|||||||
func PushToBaseRepo(pr *models.PullRequest) (err error) {
|
func PushToBaseRepo(pr *models.PullRequest) (err error) {
|
||||||
log.Trace("PushToBaseRepo[%d]: pushing commits to base repo '%s'", pr.BaseRepoID, pr.GetGitRefName())
|
log.Trace("PushToBaseRepo[%d]: pushing commits to base repo '%s'", pr.BaseRepoID, pr.GetGitRefName())
|
||||||
|
|
||||||
// Clone base repo.
|
|
||||||
tmpBasePath, err := models.CreateTemporaryPath("pull")
|
|
||||||
if err != nil {
|
|
||||||
log.Error("CreateTemporaryPath: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
err := models.RemoveTemporaryPath(tmpBasePath)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Error whilst removing temporary path: %s Error: %v", tmpBasePath, err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err := pr.LoadHeadRepo(); err != nil {
|
if err := pr.LoadHeadRepo(); err != nil {
|
||||||
log.Error("Unable to load head repository for PR[%d] Error: %v", pr.ID, err)
|
log.Error("Unable to load head repository for PR[%d] Error: %v", pr.ID, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
headRepoPath := pr.HeadRepo.RepoPath()
|
headRepoPath := pr.HeadRepo.RepoPath()
|
||||||
|
|
||||||
if err := git.Clone(headRepoPath, tmpBasePath, git.CloneRepoOptions{
|
|
||||||
Bare: true,
|
|
||||||
Shared: true,
|
|
||||||
Branch: pr.HeadBranch,
|
|
||||||
Quiet: true,
|
|
||||||
}); err != nil {
|
|
||||||
log.Error("git clone tmpBasePath: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
gitRepo, err := git.OpenRepository(tmpBasePath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("OpenRepository: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := pr.LoadBaseRepo(); err != nil {
|
if err := pr.LoadBaseRepo(); err != nil {
|
||||||
log.Error("Unable to load base repository for PR[%d] Error: %v", pr.ID, err)
|
log.Error("Unable to load base repository for PR[%d] Error: %v", pr.ID, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := gitRepo.AddRemote("base", pr.BaseRepo.RepoPath(), false); err != nil {
|
baseRepoPath := pr.BaseRepo.RepoPath()
|
||||||
return fmt.Errorf("tmpGitRepo.AddRemote: %v", err)
|
|
||||||
}
|
|
||||||
defer gitRepo.Close()
|
|
||||||
|
|
||||||
headFile := pr.GetGitRefName()
|
|
||||||
|
|
||||||
// Remove head in case there is a conflict.
|
|
||||||
file := path.Join(pr.BaseRepo.RepoPath(), headFile)
|
|
||||||
|
|
||||||
_ = os.Remove(file)
|
|
||||||
|
|
||||||
if err = pr.LoadIssue(); err != nil {
|
if err = pr.LoadIssue(); err != nil {
|
||||||
return fmt.Errorf("unable to load issue %d for pr %d: %v", pr.IssueID, pr.ID, err)
|
return fmt.Errorf("unable to load issue %d for pr %d: %v", pr.IssueID, pr.ID, err)
|
||||||
@@ -401,24 +358,26 @@ func PushToBaseRepo(pr *models.PullRequest) (err error) {
|
|||||||
return fmt.Errorf("unable to load poster %d for pr %d: %v", pr.Issue.PosterID, pr.ID, err)
|
return fmt.Errorf("unable to load poster %d for pr %d: %v", pr.Issue.PosterID, pr.ID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = git.Push(tmpBasePath, git.PushOptions{
|
gitRefName := pr.GetGitRefName()
|
||||||
Remote: "base",
|
|
||||||
Branch: fmt.Sprintf("%s:%s", pr.HeadBranch, headFile),
|
if err := git.Push(headRepoPath, git.PushOptions{
|
||||||
|
Remote: baseRepoPath,
|
||||||
|
Branch: pr.HeadBranch + ":" + gitRefName,
|
||||||
Force: true,
|
Force: true,
|
||||||
// Use InternalPushingEnvironment here because we know that pre-receive and post-receive do not run on a refs/pulls/...
|
// Use InternalPushingEnvironment here because we know that pre-receive and post-receive do not run on a refs/pulls/...
|
||||||
Env: models.InternalPushingEnvironment(pr.Issue.Poster, pr.BaseRepo),
|
Env: models.InternalPushingEnvironment(pr.Issue.Poster, pr.BaseRepo),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
if git.IsErrPushOutOfDate(err) {
|
if git.IsErrPushOutOfDate(err) {
|
||||||
// This should not happen as we're using force!
|
// This should not happen as we're using force!
|
||||||
log.Error("Unable to push PR head for %s#%d (%-v:%s) due to ErrPushOfDate: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, headFile, err)
|
log.Error("Unable to push PR head for %s#%d (%-v:%s) due to ErrPushOfDate: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, err)
|
||||||
return err
|
return err
|
||||||
} else if git.IsErrPushRejected(err) {
|
} else if git.IsErrPushRejected(err) {
|
||||||
rejectErr := err.(*git.ErrPushRejected)
|
rejectErr := err.(*git.ErrPushRejected)
|
||||||
log.Info("Unable to push PR head for %s#%d (%-v:%s) due to rejection:\nStdout: %s\nStderr: %s\nError: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, headFile, rejectErr.StdOut, rejectErr.StdErr, rejectErr.Err)
|
log.Info("Unable to push PR head for %s#%d (%-v:%s) due to rejection:\nStdout: %s\nStderr: %s\nError: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, rejectErr.StdOut, rejectErr.StdErr, rejectErr.Err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Error("Unable to push PR head for %s#%d (%-v:%s) due to Error: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, headFile, err)
|
log.Error("Unable to push PR head for %s#%d (%-v:%s) due to Error: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, err)
|
||||||
return fmt.Errorf("Push: %s:%s %s:%s %v", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), headFile, err)
|
return fmt.Errorf("Push: %s:%s %s:%s %v", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), gitRefName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{{range .Attachments}}
|
{{- range .Attachments -}}
|
||||||
<div class="twelve wide column" style="padding: 6px;">
|
<div class="twelve wide column" style="padding: 6px;">
|
||||||
<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}" title='{{$.ctx.i18n.Tr "repo.issues.attachment.open_tab" .Name}}'>
|
<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}" title='{{$.ctx.i18n.Tr "repo.issues.attachment.open_tab" .Name}}'>
|
||||||
{{if FilenameIsImage .Name}}
|
{{if FilenameIsImage .Name}}
|
||||||
@@ -12,4 +12,4 @@
|
|||||||
<div class="four wide column" style="padding: 0px;">
|
<div class="four wide column" style="padding: 0px;">
|
||||||
<span class="ui text grey right">{{.Size | FileSize}}</span>
|
<span class="ui text grey right">{{.Size | FileSize}}</span>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end -}}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
<span class="text grey">
|
<span class="text grey">
|
||||||
<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a>
|
<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a>
|
||||||
{{$link := printf "%s/commit/%s" $.Repository.HTMLURL $.Issue.PullRequest.MergedCommitID}}
|
{{$link := printf "%s/commit/%s" $.Repository.HTMLURL $.Issue.PullRequest.MergedCommitID}}
|
||||||
{{$.i18n.Tr "repo.issues.pull_merged_at" $link (ShortSha $.Issue.PullRequest.MergedCommitID) $.BaseTarget $createdStr | Str2html}}
|
{{$.i18n.Tr "repo.issues.pull_merged_at" $link (ShortSha $.Issue.PullRequest.MergedCommitID) ($.BaseTarget|Escape) $createdStr | Str2html}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{{else if eq .Type 3 5 6}}
|
{{else if eq .Type 3 5 6}}
|
||||||
@@ -163,7 +163,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<span class="text grey">
|
<span class="text grey">
|
||||||
<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a>
|
<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a>
|
||||||
{{if .Content}}{{$.i18n.Tr "repo.issues.add_label_at" .Label.ForegroundColor .Label.Color (.Label.Name|Escape|RenderEmoji) $createdStr | Safe}}{{else}}{{$.i18n.Tr "repo.issues.remove_label_at" .Label.ForegroundColor .Label.Color (.Label.Name|Escape|RenderEmoji) $createdStr | Safe}}{{end}}
|
{{if .Content}}{{$.i18n.Tr "repo.issues.add_label_at" .Label.ForegroundColor .Label.Color (.Label.Name|RenderEmoji) $createdStr | Safe}}{{else}}{{$.i18n.Tr "repo.issues.remove_label_at" .Label.ForegroundColor .Label.Color (.Label.Name|RenderEmoji) $createdStr | Safe}}{{end}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@
|
|||||||
{{else if .IsPullWorkInProgress}}
|
{{else if .IsPullWorkInProgress}}
|
||||||
<div class="item text grey">
|
<div class="item text grey">
|
||||||
<i class="icon icon-octicon">{{svg "octicon-x" 16}}</i>
|
<i class="icon icon-octicon">{{svg "octicon-x" 16}}</i>
|
||||||
{{$.i18n.Tr "repo.pulls.cannot_merge_work_in_progress" .WorkInProgressPrefix | Str2html}}
|
{{$.i18n.Tr "repo.pulls.cannot_merge_work_in_progress" (.WorkInProgressPrefix|Escape) | Str2html}}
|
||||||
</div>
|
</div>
|
||||||
{{else if .Issue.PullRequest.IsChecking}}
|
{{else if .Issue.PullRequest.IsChecking}}
|
||||||
<div class="item text yellow">
|
<div class="item text yellow">
|
||||||
|
|||||||
@@ -31,18 +31,18 @@
|
|||||||
{{ $mergedStr:= TimeSinceUnix .Issue.PullRequest.MergedUnix $.Lang }}
|
{{ $mergedStr:= TimeSinceUnix .Issue.PullRequest.MergedUnix $.Lang }}
|
||||||
{{if .Issue.OriginalAuthor }}
|
{{if .Issue.OriginalAuthor }}
|
||||||
{{.Issue.OriginalAuthor}}
|
{{.Issue.OriginalAuthor}}
|
||||||
<span class="pull-desc">{{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits .HeadTarget .BaseTarget $mergedStr | Str2html}}</span>
|
<span class="pull-desc">{{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits (.HeadTarget|Escape) (.BaseTarget|Escape) $mergedStr | Str2html}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a {{if gt .Issue.PullRequest.Merger.ID 0}}href="{{.Issue.PullRequest.Merger.HomeLink}}"{{end}}>{{.Issue.PullRequest.Merger.GetDisplayName}}</a>
|
<a {{if gt .Issue.PullRequest.Merger.ID 0}}href="{{.Issue.PullRequest.Merger.HomeLink}}"{{end}}>{{.Issue.PullRequest.Merger.GetDisplayName}}</a>
|
||||||
<span class="pull-desc">{{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits .HeadTarget .BaseTarget $mergedStr | Str2html}}</span>
|
<span class="pull-desc">{{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits (.HeadTarget|Escape) (.BaseTarget|Escape) $mergedStr | Str2html}}</span>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{if .Issue.OriginalAuthor }}
|
{{if .Issue.OriginalAuthor }}
|
||||||
<span id="pull-desc" class="pull-desc">{{.Issue.OriginalAuthor}} {{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}}</span>
|
<span id="pull-desc" class="pull-desc">{{.Issue.OriginalAuthor}} {{$.i18n.Tr "repo.pulls.title_desc" .NumCommits (.HeadTarget|Escape) (.BaseTarget|Escape) | Str2html}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span id="pull-desc" class="pull-desc">
|
<span id="pull-desc" class="pull-desc">
|
||||||
<a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.GetDisplayName}}</a>
|
<a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.GetDisplayName}}</a>
|
||||||
{{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}}
|
{{$.i18n.Tr "repo.pulls.title_desc" .NumCommits (.HeadTarget|Escape) (.BaseTarget|Escape) | Str2html}}
|
||||||
</span>
|
</span>
|
||||||
{{end}}
|
{{end}}
|
||||||
<span id="pull-desc-edit" style="display: none">
|
<span id="pull-desc-edit" style="display: none">
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<h4 class="ui top attached header">
|
<h4 class="ui top attached header">
|
||||||
{{.i18n.Tr "repo.settings.branch_protection" .Branch.BranchName | Str2html}}
|
{{.i18n.Tr "repo.settings.branch_protection" (.Branch.BranchName|Escape) | Str2html}}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached segment branch-protection">
|
<div class="ui attached segment branch-protection">
|
||||||
<form class="ui form" action="{{.Link}}" method="post">
|
<form class="ui form" action="{{.Link}}" method="post">
|
||||||
|
|||||||
@@ -15,15 +15,15 @@
|
|||||||
{{else if .ResendLimited}}
|
{{else if .ResendLimited}}
|
||||||
<p class="center">{{.i18n.Tr "auth.resent_limit_prompt"}}</p>
|
<p class="center">{{.i18n.Tr "auth.resent_limit_prompt"}}</p>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" .SignedUser.Email .ActiveCodeLives | Str2html}}</p>
|
<p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" (.SignedUser.Email|Escape) .ActiveCodeLives | Str2html}}</p>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{if .IsSendRegisterMail}}
|
{{if .IsSendRegisterMail}}
|
||||||
<p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" .Email .ActiveCodeLives | Str2html}}</p>
|
<p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" (.Email|Escape) .ActiveCodeLives | Str2html}}</p>
|
||||||
{{else if .IsActivateFailed}}
|
{{else if .IsActivateFailed}}
|
||||||
<p>{{.i18n.Tr "auth.invalid_code"}}</p>
|
<p>{{.i18n.Tr "auth.invalid_code"}}</p>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p>{{.i18n.Tr "auth.has_unconfirmed_mail" .SignedUser.Name .SignedUser.Email | Str2html}}</p>
|
<p>{{.i18n.Tr "auth.has_unconfirmed_mail" (.SignedUser.Name|Escape) (.SignedUser.Email|Escape) | Str2html}}</p>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<div class="text right">
|
<div class="text right">
|
||||||
<button class="ui blue button">{{.i18n.Tr "auth.resend_mail"}}</button>
|
<button class="ui blue button">{{.i18n.Tr "auth.resend_mail"}}</button>
|
||||||
|
|||||||
@@ -50,17 +50,17 @@
|
|||||||
{{$.i18n.Tr "action.reopen_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
|
{{$.i18n.Tr "action.reopen_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
|
||||||
{{else if eq .GetOpType 16}}
|
{{else if eq .GetOpType 16}}
|
||||||
{{ $index := index .GetIssueInfos 0}}
|
{{ $index := index .GetIssueInfos 0}}
|
||||||
{{$.i18n.Tr "action.delete_tag" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
|
{{$.i18n.Tr "action.delete_tag" .GetRepoLink (.GetBranch|Escape) .ShortRepoPath | Str2html}}
|
||||||
{{else if eq .GetOpType 17}}
|
{{else if eq .GetOpType 17}}
|
||||||
{{ $index := index .GetIssueInfos 0}}
|
{{ $index := index .GetIssueInfos 0}}
|
||||||
{{$.i18n.Tr "action.delete_branch" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
|
{{$.i18n.Tr "action.delete_branch" .GetRepoLink (.GetBranch|Escape) .ShortRepoPath | Str2html}}
|
||||||
{{else if eq .GetOpType 18}}
|
{{else if eq .GetOpType 18}}
|
||||||
{{ $branchLink := .GetBranch | EscapePound}}
|
{{ $branchLink := .GetBranch | EscapePound}}
|
||||||
{{$.i18n.Tr "action.mirror_sync_push" .GetRepoLink $branchLink .GetBranch .ShortRepoPath | Str2html}}
|
{{$.i18n.Tr "action.mirror_sync_push" .GetRepoLink $branchLink (.GetBranch|Escape) .ShortRepoPath | Str2html}}
|
||||||
{{else if eq .GetOpType 19}}
|
{{else if eq .GetOpType 19}}
|
||||||
{{$.i18n.Tr "action.mirror_sync_create" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
|
{{$.i18n.Tr "action.mirror_sync_create" .GetRepoLink (.GetBranch|Escape) .ShortRepoPath | Str2html}}
|
||||||
{{else if eq .GetOpType 20}}
|
{{else if eq .GetOpType 20}}
|
||||||
{{$.i18n.Tr "action.mirror_sync_delete" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
|
{{$.i18n.Tr "action.mirror_sync_delete" .GetRepoLink (.GetBranch|Escape) .ShortRepoPath | Str2html}}
|
||||||
{{else if eq .GetOpType 21}}
|
{{else if eq .GetOpType 21}}
|
||||||
{{ $index := index .GetIssueInfos 0}}
|
{{ $index := index .GetIssueInfos 0}}
|
||||||
{{$.i18n.Tr "action.approve_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
|
{{$.i18n.Tr "action.approve_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
|
||||||
|
|||||||
8
vendor/github.com/nfnt/resize/.travis.yml
generated
vendored
8
vendor/github.com/nfnt/resize/.travis.yml
generated
vendored
@@ -1,7 +1,7 @@
|
|||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.1
|
- "1.x"
|
||||||
- 1.2
|
- "1.1"
|
||||||
- 1.3
|
- "1.4"
|
||||||
- tip
|
- "1.10"
|
||||||
|
|||||||
2
vendor/github.com/nfnt/resize/README.md
generated
vendored
2
vendor/github.com/nfnt/resize/README.md
generated
vendored
@@ -1,3 +1,5 @@
|
|||||||
|
# This package is no longer being updated! Please look for alternatives if that bothers you.
|
||||||
|
|
||||||
Resize
|
Resize
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|||||||
6
vendor/github.com/nfnt/resize/resize.go
generated
vendored
6
vendor/github.com/nfnt/resize/resize.go
generated
vendored
@@ -78,6 +78,7 @@ var blur = 1.0
|
|||||||
// If one of the parameters width or height is set to 0, its size will be calculated so that
|
// If one of the parameters width or height is set to 0, its size will be calculated so that
|
||||||
// the aspect ratio is that of the originating image.
|
// the aspect ratio is that of the originating image.
|
||||||
// The resizing algorithm uses channels for parallel computation.
|
// The resizing algorithm uses channels for parallel computation.
|
||||||
|
// If the input image has width or height of 0, it is returned unchanged.
|
||||||
func Resize(width, height uint, img image.Image, interp InterpolationFunction) image.Image {
|
func Resize(width, height uint, img image.Image, interp InterpolationFunction) image.Image {
|
||||||
scaleX, scaleY := calcFactors(width, height, float64(img.Bounds().Dx()), float64(img.Bounds().Dy()))
|
scaleX, scaleY := calcFactors(width, height, float64(img.Bounds().Dx()), float64(img.Bounds().Dy()))
|
||||||
if width == 0 {
|
if width == 0 {
|
||||||
@@ -92,6 +93,11 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||||||
return img
|
return img
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Input image has no pixels
|
||||||
|
if img.Bounds().Dx() <= 0 || img.Bounds().Dy() <= 0 {
|
||||||
|
return img
|
||||||
|
}
|
||||||
|
|
||||||
if interp == NearestNeighbor {
|
if interp == NearestNeighbor {
|
||||||
return resizeNearest(width, height, scaleX, scaleY, img, interp)
|
return resizeNearest(width, height, scaleX, scaleY, img, interp)
|
||||||
}
|
}
|
||||||
|
|||||||
402
vendor/github.com/nfnt/resize/ycc.go
generated
vendored
402
vendor/github.com/nfnt/resize/ycc.go
generated
vendored
@@ -88,70 +88,34 @@ func newYCC(r image.Rectangle, s image.YCbCrSubsampleRatio) *ycc {
|
|||||||
return &ycc{Pix: buf, Stride: 3 * w, Rect: r, SubsampleRatio: s}
|
return &ycc{Pix: buf, Stride: 3 * w, Rect: r, SubsampleRatio: s}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy of image.YCbCrSubsampleRatio constants - this allows us to support
|
||||||
|
// older versions of Go where these constants are not defined (i.e. Go 1.4)
|
||||||
|
const (
|
||||||
|
ycbcrSubsampleRatio444 image.YCbCrSubsampleRatio = iota
|
||||||
|
ycbcrSubsampleRatio422
|
||||||
|
ycbcrSubsampleRatio420
|
||||||
|
ycbcrSubsampleRatio440
|
||||||
|
ycbcrSubsampleRatio411
|
||||||
|
ycbcrSubsampleRatio410
|
||||||
|
)
|
||||||
|
|
||||||
// YCbCr converts ycc to a YCbCr image with the same subsample ratio
|
// YCbCr converts ycc to a YCbCr image with the same subsample ratio
|
||||||
// as the YCbCr image that ycc was generated from.
|
// as the YCbCr image that ycc was generated from.
|
||||||
func (p *ycc) YCbCr() *image.YCbCr {
|
func (p *ycc) YCbCr() *image.YCbCr {
|
||||||
ycbcr := image.NewYCbCr(p.Rect, p.SubsampleRatio)
|
ycbcr := image.NewYCbCr(p.Rect, p.SubsampleRatio)
|
||||||
var off int
|
|
||||||
|
|
||||||
switch ycbcr.SubsampleRatio {
|
switch ycbcr.SubsampleRatio {
|
||||||
case image.YCbCrSubsampleRatio422:
|
case ycbcrSubsampleRatio422:
|
||||||
for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ {
|
return p.ycbcr422(ycbcr)
|
||||||
yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride
|
case ycbcrSubsampleRatio420:
|
||||||
cy := (y - ycbcr.Rect.Min.Y) * ycbcr.CStride
|
return p.ycbcr420(ycbcr)
|
||||||
for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ {
|
case ycbcrSubsampleRatio440:
|
||||||
xx := (x - ycbcr.Rect.Min.X)
|
return p.ycbcr440(ycbcr)
|
||||||
yi := yy + xx
|
case ycbcrSubsampleRatio444:
|
||||||
ci := cy + xx/2
|
return p.ycbcr444(ycbcr)
|
||||||
ycbcr.Y[yi] = p.Pix[off+0]
|
case ycbcrSubsampleRatio411:
|
||||||
ycbcr.Cb[ci] = p.Pix[off+1]
|
return p.ycbcr411(ycbcr)
|
||||||
ycbcr.Cr[ci] = p.Pix[off+2]
|
case ycbcrSubsampleRatio410:
|
||||||
off += 3
|
return p.ycbcr410(ycbcr)
|
||||||
}
|
|
||||||
}
|
|
||||||
case image.YCbCrSubsampleRatio420:
|
|
||||||
for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ {
|
|
||||||
yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride
|
|
||||||
cy := (y/2 - ycbcr.Rect.Min.Y/2) * ycbcr.CStride
|
|
||||||
for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ {
|
|
||||||
xx := (x - ycbcr.Rect.Min.X)
|
|
||||||
yi := yy + xx
|
|
||||||
ci := cy + xx/2
|
|
||||||
ycbcr.Y[yi] = p.Pix[off+0]
|
|
||||||
ycbcr.Cb[ci] = p.Pix[off+1]
|
|
||||||
ycbcr.Cr[ci] = p.Pix[off+2]
|
|
||||||
off += 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case image.YCbCrSubsampleRatio440:
|
|
||||||
for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ {
|
|
||||||
yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride
|
|
||||||
cy := (y/2 - ycbcr.Rect.Min.Y/2) * ycbcr.CStride
|
|
||||||
for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ {
|
|
||||||
xx := (x - ycbcr.Rect.Min.X)
|
|
||||||
yi := yy + xx
|
|
||||||
ci := cy + xx
|
|
||||||
ycbcr.Y[yi] = p.Pix[off+0]
|
|
||||||
ycbcr.Cb[ci] = p.Pix[off+1]
|
|
||||||
ycbcr.Cr[ci] = p.Pix[off+2]
|
|
||||||
off += 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// Default to 4:4:4 subsampling.
|
|
||||||
for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ {
|
|
||||||
yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride
|
|
||||||
cy := (y - ycbcr.Rect.Min.Y) * ycbcr.CStride
|
|
||||||
for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ {
|
|
||||||
xx := (x - ycbcr.Rect.Min.X)
|
|
||||||
yi := yy + xx
|
|
||||||
ci := cy + xx
|
|
||||||
ycbcr.Y[yi] = p.Pix[off+0]
|
|
||||||
ycbcr.Cb[ci] = p.Pix[off+1]
|
|
||||||
ycbcr.Cr[ci] = p.Pix[off+2]
|
|
||||||
off += 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ycbcr
|
return ycbcr
|
||||||
}
|
}
|
||||||
@@ -159,69 +123,265 @@ func (p *ycc) YCbCr() *image.YCbCr {
|
|||||||
// imageYCbCrToYCC converts a YCbCr image to a ycc image for resizing.
|
// imageYCbCrToYCC converts a YCbCr image to a ycc image for resizing.
|
||||||
func imageYCbCrToYCC(in *image.YCbCr) *ycc {
|
func imageYCbCrToYCC(in *image.YCbCr) *ycc {
|
||||||
w, h := in.Rect.Dx(), in.Rect.Dy()
|
w, h := in.Rect.Dx(), in.Rect.Dy()
|
||||||
r := image.Rect(0, 0, w, h)
|
p := ycc{
|
||||||
buf := make([]uint8, 3*w*h)
|
Pix: make([]uint8, 3*w*h),
|
||||||
p := ycc{Pix: buf, Stride: 3 * w, Rect: r, SubsampleRatio: in.SubsampleRatio}
|
Stride: 3 * w,
|
||||||
var off int
|
Rect: image.Rect(0, 0, w, h),
|
||||||
|
SubsampleRatio: in.SubsampleRatio,
|
||||||
|
}
|
||||||
switch in.SubsampleRatio {
|
switch in.SubsampleRatio {
|
||||||
case image.YCbCrSubsampleRatio422:
|
case ycbcrSubsampleRatio422:
|
||||||
for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ {
|
return convertToYCC422(in, &p)
|
||||||
yy := (y - in.Rect.Min.Y) * in.YStride
|
case ycbcrSubsampleRatio420:
|
||||||
cy := (y - in.Rect.Min.Y) * in.CStride
|
return convertToYCC420(in, &p)
|
||||||
for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ {
|
case ycbcrSubsampleRatio440:
|
||||||
xx := (x - in.Rect.Min.X)
|
return convertToYCC440(in, &p)
|
||||||
yi := yy + xx
|
case ycbcrSubsampleRatio444:
|
||||||
ci := cy + xx/2
|
return convertToYCC444(in, &p)
|
||||||
p.Pix[off+0] = in.Y[yi]
|
case ycbcrSubsampleRatio411:
|
||||||
p.Pix[off+1] = in.Cb[ci]
|
return convertToYCC411(in, &p)
|
||||||
p.Pix[off+2] = in.Cr[ci]
|
case ycbcrSubsampleRatio410:
|
||||||
off += 3
|
return convertToYCC410(in, &p)
|
||||||
}
|
|
||||||
}
|
|
||||||
case image.YCbCrSubsampleRatio420:
|
|
||||||
for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ {
|
|
||||||
yy := (y - in.Rect.Min.Y) * in.YStride
|
|
||||||
cy := (y/2 - in.Rect.Min.Y/2) * in.CStride
|
|
||||||
for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ {
|
|
||||||
xx := (x - in.Rect.Min.X)
|
|
||||||
yi := yy + xx
|
|
||||||
ci := cy + xx/2
|
|
||||||
p.Pix[off+0] = in.Y[yi]
|
|
||||||
p.Pix[off+1] = in.Cb[ci]
|
|
||||||
p.Pix[off+2] = in.Cr[ci]
|
|
||||||
off += 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case image.YCbCrSubsampleRatio440:
|
|
||||||
for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ {
|
|
||||||
yy := (y - in.Rect.Min.Y) * in.YStride
|
|
||||||
cy := (y/2 - in.Rect.Min.Y/2) * in.CStride
|
|
||||||
for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ {
|
|
||||||
xx := (x - in.Rect.Min.X)
|
|
||||||
yi := yy + xx
|
|
||||||
ci := cy + xx
|
|
||||||
p.Pix[off+0] = in.Y[yi]
|
|
||||||
p.Pix[off+1] = in.Cb[ci]
|
|
||||||
p.Pix[off+2] = in.Cr[ci]
|
|
||||||
off += 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// Default to 4:4:4 subsampling.
|
|
||||||
for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ {
|
|
||||||
yy := (y - in.Rect.Min.Y) * in.YStride
|
|
||||||
cy := (y - in.Rect.Min.Y) * in.CStride
|
|
||||||
for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ {
|
|
||||||
xx := (x - in.Rect.Min.X)
|
|
||||||
yi := yy + xx
|
|
||||||
ci := cy + xx
|
|
||||||
p.Pix[off+0] = in.Y[yi]
|
|
||||||
p.Pix[off+1] = in.Cb[ci]
|
|
||||||
p.Pix[off+2] = in.Cr[ci]
|
|
||||||
off += 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return &p
|
return &p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *ycc) ycbcr422(ycbcr *image.YCbCr) *image.YCbCr {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := ycbcr.Y
|
||||||
|
Cb := ycbcr.Cb
|
||||||
|
Cr := ycbcr.Cr
|
||||||
|
for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
|
||||||
|
yy := y * ycbcr.YStride
|
||||||
|
cy := y * ycbcr.CStride
|
||||||
|
for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x/2
|
||||||
|
Y[yy+x] = Pix[off+0]
|
||||||
|
Cb[ci] = Pix[off+1]
|
||||||
|
Cr[ci] = Pix[off+2]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ycbcr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ycc) ycbcr420(ycbcr *image.YCbCr) *image.YCbCr {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := ycbcr.Y
|
||||||
|
Cb := ycbcr.Cb
|
||||||
|
Cr := ycbcr.Cr
|
||||||
|
for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
|
||||||
|
yy := y * ycbcr.YStride
|
||||||
|
cy := (y / 2) * ycbcr.CStride
|
||||||
|
for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x/2
|
||||||
|
Y[yy+x] = Pix[off+0]
|
||||||
|
Cb[ci] = Pix[off+1]
|
||||||
|
Cr[ci] = Pix[off+2]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ycbcr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ycc) ycbcr440(ycbcr *image.YCbCr) *image.YCbCr {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := ycbcr.Y
|
||||||
|
Cb := ycbcr.Cb
|
||||||
|
Cr := ycbcr.Cr
|
||||||
|
for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
|
||||||
|
yy := y * ycbcr.YStride
|
||||||
|
cy := (y / 2) * ycbcr.CStride
|
||||||
|
for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x
|
||||||
|
Y[yy+x] = Pix[off+0]
|
||||||
|
Cb[ci] = Pix[off+1]
|
||||||
|
Cr[ci] = Pix[off+2]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ycbcr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ycc) ycbcr444(ycbcr *image.YCbCr) *image.YCbCr {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := ycbcr.Y
|
||||||
|
Cb := ycbcr.Cb
|
||||||
|
Cr := ycbcr.Cr
|
||||||
|
for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
|
||||||
|
yy := y * ycbcr.YStride
|
||||||
|
cy := y * ycbcr.CStride
|
||||||
|
for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x
|
||||||
|
Y[yy+x] = Pix[off+0]
|
||||||
|
Cb[ci] = Pix[off+1]
|
||||||
|
Cr[ci] = Pix[off+2]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ycbcr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ycc) ycbcr411(ycbcr *image.YCbCr) *image.YCbCr {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := ycbcr.Y
|
||||||
|
Cb := ycbcr.Cb
|
||||||
|
Cr := ycbcr.Cr
|
||||||
|
for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
|
||||||
|
yy := y * ycbcr.YStride
|
||||||
|
cy := y * ycbcr.CStride
|
||||||
|
for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x/4
|
||||||
|
Y[yy+x] = Pix[off+0]
|
||||||
|
Cb[ci] = Pix[off+1]
|
||||||
|
Cr[ci] = Pix[off+2]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ycbcr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ycc) ycbcr410(ycbcr *image.YCbCr) *image.YCbCr {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := ycbcr.Y
|
||||||
|
Cb := ycbcr.Cb
|
||||||
|
Cr := ycbcr.Cr
|
||||||
|
for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
|
||||||
|
yy := y * ycbcr.YStride
|
||||||
|
cy := (y / 2) * ycbcr.CStride
|
||||||
|
for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x/4
|
||||||
|
Y[yy+x] = Pix[off+0]
|
||||||
|
Cb[ci] = Pix[off+1]
|
||||||
|
Cr[ci] = Pix[off+2]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ycbcr
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToYCC422(in *image.YCbCr, p *ycc) *ycc {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := in.Y
|
||||||
|
Cb := in.Cb
|
||||||
|
Cr := in.Cr
|
||||||
|
for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
|
||||||
|
yy := y * in.YStride
|
||||||
|
cy := y * in.CStride
|
||||||
|
for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x/2
|
||||||
|
Pix[off+0] = Y[yy+x]
|
||||||
|
Pix[off+1] = Cb[ci]
|
||||||
|
Pix[off+2] = Cr[ci]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToYCC420(in *image.YCbCr, p *ycc) *ycc {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := in.Y
|
||||||
|
Cb := in.Cb
|
||||||
|
Cr := in.Cr
|
||||||
|
for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
|
||||||
|
yy := y * in.YStride
|
||||||
|
cy := (y / 2) * in.CStride
|
||||||
|
for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x/2
|
||||||
|
Pix[off+0] = Y[yy+x]
|
||||||
|
Pix[off+1] = Cb[ci]
|
||||||
|
Pix[off+2] = Cr[ci]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToYCC440(in *image.YCbCr, p *ycc) *ycc {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := in.Y
|
||||||
|
Cb := in.Cb
|
||||||
|
Cr := in.Cr
|
||||||
|
for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
|
||||||
|
yy := y * in.YStride
|
||||||
|
cy := (y / 2) * in.CStride
|
||||||
|
for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x
|
||||||
|
Pix[off+0] = Y[yy+x]
|
||||||
|
Pix[off+1] = Cb[ci]
|
||||||
|
Pix[off+2] = Cr[ci]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToYCC444(in *image.YCbCr, p *ycc) *ycc {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := in.Y
|
||||||
|
Cb := in.Cb
|
||||||
|
Cr := in.Cr
|
||||||
|
for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
|
||||||
|
yy := y * in.YStride
|
||||||
|
cy := y * in.CStride
|
||||||
|
for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x
|
||||||
|
Pix[off+0] = Y[yy+x]
|
||||||
|
Pix[off+1] = Cb[ci]
|
||||||
|
Pix[off+2] = Cr[ci]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToYCC411(in *image.YCbCr, p *ycc) *ycc {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := in.Y
|
||||||
|
Cb := in.Cb
|
||||||
|
Cr := in.Cr
|
||||||
|
for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
|
||||||
|
yy := y * in.YStride
|
||||||
|
cy := y * in.CStride
|
||||||
|
for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x/4
|
||||||
|
Pix[off+0] = Y[yy+x]
|
||||||
|
Pix[off+1] = Cb[ci]
|
||||||
|
Pix[off+2] = Cr[ci]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToYCC410(in *image.YCbCr, p *ycc) *ycc {
|
||||||
|
var off int
|
||||||
|
Pix := p.Pix
|
||||||
|
Y := in.Y
|
||||||
|
Cb := in.Cb
|
||||||
|
Cr := in.Cr
|
||||||
|
for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
|
||||||
|
yy := y * in.YStride
|
||||||
|
cy := (y / 2) * in.CStride
|
||||||
|
for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
|
||||||
|
ci := cy + x/4
|
||||||
|
Pix[off+0] = Y[yy+x]
|
||||||
|
Pix[off+1] = Cb[ci]
|
||||||
|
Pix[off+2] = Cr[ci]
|
||||||
|
off += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|||||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -518,7 +518,7 @@ github.com/mschoch/smat
|
|||||||
# github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
|
# github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
|
||||||
## explicit
|
## explicit
|
||||||
github.com/msteinert/pam
|
github.com/msteinert/pam
|
||||||
# github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5
|
# github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||||
## explicit
|
## explicit
|
||||||
github.com/nfnt/resize
|
github.com/nfnt/resize
|
||||||
# github.com/niklasfasching/go-org v0.1.9
|
# github.com/niklasfasching/go-org v0.1.9
|
||||||
|
|||||||
Reference in New Issue
Block a user