mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-02 00:39:16 +00:00
Merge branch 'master' into enh/noid/commit-message-link-check-commit-hashes
This commit is contained in:
commit
663bc8e28b
23
.drone.yml
23
.drone.yml
|
@ -66,6 +66,7 @@ steps:
|
||||||
image: golang:1.11 # this step is kept as the lowest version of golang that we support
|
image: golang:1.11 # this step is kept as the lowest version of golang that we support
|
||||||
environment:
|
environment:
|
||||||
GO111MODULE: on
|
GO111MODULE: on
|
||||||
|
GOPROXY: off
|
||||||
commands:
|
commands:
|
||||||
- go build -mod=vendor -o gitea_no_gcc # test if build succeeds without the sqlite tag
|
- go build -mod=vendor -o gitea_no_gcc # test if build succeeds without the sqlite tag
|
||||||
|
|
||||||
|
@ -74,6 +75,7 @@ steps:
|
||||||
image: golang:1.12
|
image: golang:1.12
|
||||||
environment:
|
environment:
|
||||||
GO111MODULE: on
|
GO111MODULE: on
|
||||||
|
GOPROXY: off
|
||||||
GOOS: linux
|
GOOS: linux
|
||||||
GOARCH: 386
|
GOARCH: 386
|
||||||
commands:
|
commands:
|
||||||
|
@ -92,6 +94,7 @@ steps:
|
||||||
- make test-vendor
|
- make test-vendor
|
||||||
- make build
|
- make build
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
|
|
||||||
- name: unit-test
|
- name: unit-test
|
||||||
|
@ -100,6 +103,7 @@ steps:
|
||||||
commands:
|
commands:
|
||||||
- make unit-test-coverage
|
- make unit-test-coverage
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
depends_on:
|
depends_on:
|
||||||
- build
|
- build
|
||||||
|
@ -116,6 +120,7 @@ steps:
|
||||||
commands:
|
commands:
|
||||||
- make test
|
- make test
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
depends_on:
|
depends_on:
|
||||||
- build
|
- build
|
||||||
|
@ -143,6 +148,7 @@ steps:
|
||||||
commands:
|
commands:
|
||||||
- make test
|
- make test
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
depends_on:
|
depends_on:
|
||||||
- tag-pre-condition
|
- tag-pre-condition
|
||||||
|
@ -159,6 +165,7 @@ steps:
|
||||||
- timeout -s ABRT 20m make test-sqlite-migration
|
- timeout -s ABRT 20m make test-sqlite-migration
|
||||||
- timeout -s ABRT 20m make test-sqlite
|
- timeout -s ABRT 20m make test-sqlite
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
depends_on:
|
depends_on:
|
||||||
- build
|
- build
|
||||||
|
@ -172,6 +179,7 @@ steps:
|
||||||
- make test-mysql-migration
|
- make test-mysql-migration
|
||||||
- make integration-test-coverage
|
- make integration-test-coverage
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_LDAP: 1
|
TEST_LDAP: 1
|
||||||
depends_on:
|
depends_on:
|
||||||
|
@ -192,6 +200,7 @@ steps:
|
||||||
- timeout -s ABRT 20m make test-mysql-migration
|
- timeout -s ABRT 20m make test-mysql-migration
|
||||||
- timeout -s ABRT 20m make test-mysql
|
- timeout -s ABRT 20m make test-mysql
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_LDAP: 1
|
TEST_LDAP: 1
|
||||||
depends_on:
|
depends_on:
|
||||||
|
@ -209,6 +218,7 @@ steps:
|
||||||
- timeout -s ABRT 20m make test-mysql8-migration
|
- timeout -s ABRT 20m make test-mysql8-migration
|
||||||
- timeout -s ABRT 20m make test-mysql8
|
- timeout -s ABRT 20m make test-mysql8
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_LDAP: 1
|
TEST_LDAP: 1
|
||||||
depends_on:
|
depends_on:
|
||||||
|
@ -223,6 +233,7 @@ steps:
|
||||||
- timeout -s ABRT 20m make test-pgsql-migration
|
- timeout -s ABRT 20m make test-pgsql-migration
|
||||||
- timeout -s ABRT 20m make test-pgsql
|
- timeout -s ABRT 20m make test-pgsql
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_LDAP: 1
|
TEST_LDAP: 1
|
||||||
depends_on:
|
depends_on:
|
||||||
|
@ -237,6 +248,7 @@ steps:
|
||||||
- make test-mssql-migration
|
- make test-mssql-migration
|
||||||
- make test-mssql
|
- make test-mssql
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_LDAP: 1
|
TEST_LDAP: 1
|
||||||
depends_on:
|
depends_on:
|
||||||
|
@ -248,6 +260,7 @@ steps:
|
||||||
commands:
|
commands:
|
||||||
- make coverage
|
- make coverage
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
depends_on:
|
depends_on:
|
||||||
- unit-test
|
- unit-test
|
||||||
|
@ -380,6 +393,7 @@ steps:
|
||||||
- make generate
|
- make generate
|
||||||
- make release
|
- make release
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
|
|
||||||
- name: gpg-sign
|
- name: gpg-sign
|
||||||
|
@ -481,6 +495,7 @@ steps:
|
||||||
- make generate
|
- make generate
|
||||||
- make release
|
- make release
|
||||||
environment:
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
|
|
||||||
- name: gpg-sign
|
- name: gpg-sign
|
||||||
|
@ -607,6 +622,8 @@ steps:
|
||||||
dry_run: true
|
dry_run: true
|
||||||
repo: gitea/gitea
|
repo: gitea/gitea
|
||||||
tags: linux-amd64
|
tags: linux-amd64
|
||||||
|
build_args:
|
||||||
|
- GOPROXY=off
|
||||||
when:
|
when:
|
||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
@ -618,6 +635,8 @@ steps:
|
||||||
auto_tag: true
|
auto_tag: true
|
||||||
auto_tag_suffix: linux-amd64
|
auto_tag_suffix: linux-amd64
|
||||||
repo: gitea/gitea
|
repo: gitea/gitea
|
||||||
|
build_args:
|
||||||
|
- GOPROXY=off
|
||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
username:
|
username:
|
||||||
|
@ -668,6 +687,8 @@ steps:
|
||||||
dry_run: true
|
dry_run: true
|
||||||
repo: gitea/gitea
|
repo: gitea/gitea
|
||||||
tags: linux-arm64
|
tags: linux-arm64
|
||||||
|
build_args:
|
||||||
|
- GOPROXY=off
|
||||||
when:
|
when:
|
||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
@ -679,6 +700,8 @@ steps:
|
||||||
auto_tag: true
|
auto_tag: true
|
||||||
auto_tag_suffix: linux-arm64
|
auto_tag_suffix: linux-arm64
|
||||||
repo: gitea/gitea
|
repo: gitea/gitea
|
||||||
|
build_args:
|
||||||
|
- GOPROXY=off
|
||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
username:
|
username:
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
#Build stage
|
#Build stage
|
||||||
FROM golang:1.12-alpine3.10 AS build-env
|
FROM golang:1.12-alpine3.10 AS build-env
|
||||||
|
|
||||||
|
ARG GOPROXY
|
||||||
|
ENV GOPROXY ${GOPROXY:-direct}
|
||||||
|
|
||||||
ARG GITEA_VERSION
|
ARG GITEA_VERSION
|
||||||
ARG TAGS="sqlite sqlite_unlock_notify"
|
ARG TAGS="sqlite sqlite_unlock_notify"
|
||||||
ENV TAGS "bindata $TAGS"
|
ENV TAGS "bindata $TAGS"
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -115,7 +115,7 @@ require (
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 // indirect
|
gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 // indirect
|
||||||
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e // indirect
|
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e // indirect
|
||||||
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.2.0
|
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.3.0
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/ini.v1 v1.42.0
|
gopkg.in/ini.v1 v1.42.0
|
||||||
gopkg.in/ldap.v3 v3.0.2
|
gopkg.in/ldap.v3 v3.0.2
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -451,8 +451,8 @@ gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e/go.mod h1:xsQCaysVCudhrYTfz
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.2.0 h1:CO465/foR4+bY1xNYjZEl6l8By1g/iMsImoruxfEt84=
|
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.3.0 h1:oxOEwvhxLMpWpN+0pb2r9TWrM0DCFBHxbuIlS27tmFg=
|
||||||
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.2.0/go.mod h1:s2mQFI9McjArkyCwyEwU//+luQENTnD/Lfb/7Sj3/kQ=
|
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.3.0/go.mod h1:s2mQFI9McjArkyCwyEwU//+luQENTnD/Lfb/7Sj3/kQ=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||||
|
|
|
@ -39,3 +39,9 @@
|
||||||
uid: 20
|
uid: 20
|
||||||
org_id: 19
|
org_id: 19
|
||||||
is_public: true
|
is_public: true
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 8
|
||||||
|
uid: 24
|
||||||
|
org_id: 25
|
||||||
|
is_public: true
|
||||||
|
|
|
@ -77,4 +77,13 @@
|
||||||
name: review_team
|
name: review_team
|
||||||
authorize: 1 # read
|
authorize: 1 # read
|
||||||
num_repos: 1
|
num_repos: 1
|
||||||
num_members: 1
|
num_members: 1
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 10
|
||||||
|
org_id: 25
|
||||||
|
lower_name: notowners
|
||||||
|
name: NotOwners
|
||||||
|
authorize: 1 # owner
|
||||||
|
num_repos: 0
|
||||||
|
num_members: 1
|
||||||
|
|
|
@ -62,4 +62,10 @@
|
||||||
id: 11
|
id: 11
|
||||||
org_id: 17
|
org_id: 17
|
||||||
team_id: 9
|
team_id: 9
|
||||||
uid: 20
|
uid: 20
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 12
|
||||||
|
org_id: 25
|
||||||
|
team_id: 10
|
||||||
|
uid: 24
|
||||||
|
|
9
models/fixtures/two_factor.yml
Normal file
9
models/fixtures/two_factor.yml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
-
|
||||||
|
id: 1
|
||||||
|
uid: 24
|
||||||
|
secret: KlDporn6Ile4vFcKI8z7Z6sqK1Scj2Qp0ovtUzCZO6jVbRW2lAoT7UDxDPtrab8d2B9zKOocBRdBJnS8orsrUNrsyETY+jJHb79M82uZRioKbRUz15sfOpmJmEzkFeSg6S4LicUBQos=
|
||||||
|
scratch_salt: Qb5bq2DyR2
|
||||||
|
scratch_hash: 068eb9b8746e0bcfe332fac4457693df1bda55800eb0f6894d14ebb736ae6a24e0fc8fc5333c19f57f81599788f0b8e51ec1
|
||||||
|
last_used_passcode:
|
||||||
|
created_unix: 1564253724
|
||||||
|
updated_unix: 1564253724
|
|
@ -365,4 +365,39 @@
|
||||||
is_active: true
|
is_active: true
|
||||||
num_members: 0
|
num_members: 0
|
||||||
num_teams: 0
|
num_teams: 0
|
||||||
visibility: 2
|
visibility: 2
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 24
|
||||||
|
lower_name: user24
|
||||||
|
name: user24
|
||||||
|
full_name: "user24"
|
||||||
|
email: user24@example.com
|
||||||
|
keep_email_private: true
|
||||||
|
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password
|
||||||
|
type: 0 # individual
|
||||||
|
salt: ZogKvWdyEx
|
||||||
|
is_admin: false
|
||||||
|
avatar: avatar24
|
||||||
|
avatar_email: user24@example.com
|
||||||
|
num_repos: 0
|
||||||
|
num_stars: 0
|
||||||
|
num_followers: 0
|
||||||
|
num_following: 0
|
||||||
|
is_active: true
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 25
|
||||||
|
lower_name: org25
|
||||||
|
name: org25
|
||||||
|
full_name: "org25"
|
||||||
|
email: org25@example.com
|
||||||
|
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password
|
||||||
|
type: 1 # organization
|
||||||
|
salt: ZogKvWdyEx
|
||||||
|
is_admin: false
|
||||||
|
avatar: avatar25
|
||||||
|
avatar_email: org25@example.com
|
||||||
|
num_repos: 0
|
||||||
|
num_members: 1
|
||||||
|
num_teams: 1
|
||||||
|
|
|
@ -62,38 +62,50 @@ func insertIssue(sess *xorm.Session, issue *Issue) error {
|
||||||
if _, err := sess.Insert(issueLabels); err != nil {
|
if _, err := sess.Insert(issueLabels); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cols := make([]string, 0)
|
||||||
if !issue.IsPull {
|
if !issue.IsPull {
|
||||||
sess.ID(issue.RepoID).Incr("num_issues")
|
sess.ID(issue.RepoID).Incr("num_issues")
|
||||||
|
cols = append(cols, "num_issues")
|
||||||
if issue.IsClosed {
|
if issue.IsClosed {
|
||||||
sess.Incr("num_closed_issues")
|
sess.Incr("num_closed_issues")
|
||||||
|
cols = append(cols, "num_closed_issues")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sess.ID(issue.RepoID).Incr("num_pulls")
|
sess.ID(issue.RepoID).Incr("num_pulls")
|
||||||
|
cols = append(cols, "num_pulls")
|
||||||
if issue.IsClosed {
|
if issue.IsClosed {
|
||||||
sess.Incr("num_closed_pulls")
|
sess.Incr("num_closed_pulls")
|
||||||
|
cols = append(cols, "num_closed_pulls")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err := sess.NoAutoTime().Update(issue.Repo); err != nil {
|
if _, err := sess.NoAutoTime().Cols(cols...).Update(issue.Repo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cols = []string{"num_issues"}
|
||||||
sess.Incr("num_issues")
|
sess.Incr("num_issues")
|
||||||
if issue.IsClosed {
|
if issue.IsClosed {
|
||||||
sess.Incr("num_closed_issues")
|
sess.Incr("num_closed_issues")
|
||||||
|
cols = append(cols, "num_closed_issues")
|
||||||
}
|
}
|
||||||
if _, err := sess.In("id", labelIDs).NoAutoTime().Update(new(Label)); err != nil {
|
if _, err := sess.In("id", labelIDs).NoAutoTime().Cols(cols...).Update(new(Label)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if issue.MilestoneID > 0 {
|
if issue.MilestoneID > 0 {
|
||||||
|
cols = []string{"num_issues"}
|
||||||
sess.Incr("num_issues")
|
sess.Incr("num_issues")
|
||||||
|
cl := "num_closed_issues"
|
||||||
if issue.IsClosed {
|
if issue.IsClosed {
|
||||||
sess.Incr("num_closed_issues")
|
sess.Incr("num_closed_issues")
|
||||||
|
cols = append(cols, "num_closed_issues")
|
||||||
|
cl = "(num_closed_issues + 1)"
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := sess.ID(issue.MilestoneID).
|
if _, err := sess.ID(issue.MilestoneID).
|
||||||
SetExpr("completeness", "num_closed_issues * 100 / num_issues").
|
SetExpr("completeness", cl+" * 100 / (num_issues + 1)").
|
||||||
NoAutoTime().
|
NoAutoTime().Cols(cols...).
|
||||||
Update(new(Milestone)); err != nil {
|
Update(new(Milestone)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,9 +72,12 @@ func (org *User) GetMembers() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var ids = make([]int64, len(ous))
|
var ids = make([]int64, len(ous))
|
||||||
|
var idsIsPublic = make(map[int64]bool, len(ous))
|
||||||
for i, ou := range ous {
|
for i, ou := range ous {
|
||||||
ids[i] = ou.UID
|
ids[i] = ou.UID
|
||||||
|
idsIsPublic[ou.UID] = ou.IsPublic
|
||||||
}
|
}
|
||||||
|
org.MembersIsPublic = idsIsPublic
|
||||||
org.Members, err = GetUsersByIDs(ids)
|
org.Members, err = GetUsersByIDs(ids)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -298,15 +301,13 @@ type OrgUser struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func isOrganizationOwner(e Engine, orgID, uid int64) (bool, error) {
|
func isOrganizationOwner(e Engine, orgID, uid int64) (bool, error) {
|
||||||
ownerTeam := &Team{
|
ownerTeam, err := getOwnerTeam(e, orgID)
|
||||||
OrgID: orgID,
|
if err != nil {
|
||||||
Name: ownerTeamName,
|
if err == ErrTeamNotExist {
|
||||||
}
|
log.Error("Organization does not have owner team: %d", orgID)
|
||||||
if has, err := e.Get(ownerTeam); err != nil {
|
return false, nil
|
||||||
|
}
|
||||||
return false, err
|
return false, err
|
||||||
} else if !has {
|
|
||||||
log.Error("Organization does not have owner team: %d", orgID)
|
|
||||||
return false, nil
|
|
||||||
}
|
}
|
||||||
return isTeamMember(e, orgID, ownerTeam.ID, uid)
|
return isTeamMember(e, orgID, ownerTeam.ID, uid)
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,6 +362,11 @@ func GetTeam(orgID int64, name string) (*Team, error) {
|
||||||
return getTeam(x, orgID, name)
|
return getTeam(x, orgID, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getOwnerTeam returns team by given team name and organization.
|
||||||
|
func getOwnerTeam(e Engine, orgID int64) (*Team, error) {
|
||||||
|
return getTeam(e, orgID, ownerTeamName)
|
||||||
|
}
|
||||||
|
|
||||||
func getTeamByID(e Engine, teamID int64) (*Team, error) {
|
func getTeamByID(e Engine, teamID int64) (*Team, error) {
|
||||||
t := new(Team)
|
t := new(Team)
|
||||||
has, err := e.ID(teamID).Get(t)
|
has, err := e.ID(teamID).Get(t)
|
||||||
|
|
|
@ -1801,6 +1801,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
|
||||||
&HookTask{RepoID: repoID},
|
&HookTask{RepoID: repoID},
|
||||||
&Notification{RepoID: repoID},
|
&Notification{RepoID: repoID},
|
||||||
&CommitStatus{RepoID: repoID},
|
&CommitStatus{RepoID: repoID},
|
||||||
|
&RepoIndexerStatus{RepoID: repoID},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return fmt.Errorf("deleteBeans: %v", err)
|
return fmt.Errorf("deleteBeans: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ func addUpdate(update fileUpdate, repo *Repository, batch rupture.FlushingBatch)
|
||||||
if size, err := strconv.Atoi(strings.TrimSpace(stdout)); err != nil {
|
if size, err := strconv.Atoi(strings.TrimSpace(stdout)); err != nil {
|
||||||
return fmt.Errorf("Misformatted git cat-file output: %v", err)
|
return fmt.Errorf("Misformatted git cat-file output: %v", err)
|
||||||
} else if int64(size) > setting.Indexer.MaxIndexerFileSize {
|
} else if int64(size) > setting.Indexer.MaxIndexerFileSize {
|
||||||
return nil
|
return addDelete(update.Filename, repo, batch)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileContents, err := git.NewCommand("cat-file", "blob", update.BlobSha).
|
fileContents, err := git.NewCommand("cat-file", "blob", update.BlobSha).
|
||||||
|
@ -232,7 +232,7 @@ func addDelete(filename string, repo *Repository, batch rupture.FlushingBatch) e
|
||||||
}
|
}
|
||||||
|
|
||||||
func isIndexable(entry *git.TreeEntry) bool {
|
func isIndexable(entry *git.TreeEntry) bool {
|
||||||
return entry.IsRegular()
|
return entry.IsRegular() || entry.IsExecutable()
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseGitLsTreeOutput parses the output of a `git ls-tree -r --full-name` command
|
// parseGitLsTreeOutput parses the output of a `git ls-tree -r --full-name` command
|
||||||
|
|
|
@ -139,11 +139,12 @@ type User struct {
|
||||||
NumRepos int
|
NumRepos int
|
||||||
|
|
||||||
// For organization
|
// For organization
|
||||||
NumTeams int
|
NumTeams int
|
||||||
NumMembers int
|
NumMembers int
|
||||||
Teams []*Team `xorm:"-"`
|
Teams []*Team `xorm:"-"`
|
||||||
Members []*User `xorm:"-"`
|
Members UserList `xorm:"-"`
|
||||||
Visibility structs.VisibleType `xorm:"NOT NULL DEFAULT 0"`
|
MembersIsPublic map[int64]bool `xorm:"-"`
|
||||||
|
Visibility structs.VisibleType `xorm:"NOT NULL DEFAULT 0"`
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"`
|
DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"`
|
||||||
|
@ -1408,9 +1409,7 @@ type SearchUserOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (opts *SearchUserOptions) toConds() builder.Cond {
|
func (opts *SearchUserOptions) toConds() builder.Cond {
|
||||||
|
var cond builder.Cond = builder.Eq{"type": opts.Type}
|
||||||
var cond = builder.NewCond()
|
|
||||||
cond = cond.And(builder.Eq{"type": opts.Type})
|
|
||||||
|
|
||||||
if len(opts.Keyword) > 0 {
|
if len(opts.Keyword) > 0 {
|
||||||
lowerKeyword := strings.ToLower(opts.Keyword)
|
lowerKeyword := strings.ToLower(opts.Keyword)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -15,6 +16,58 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestUserIsPublicMember(t *testing.T) {
|
||||||
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
|
||||||
|
tt := []struct {
|
||||||
|
uid int64
|
||||||
|
orgid int64
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{2, 3, true},
|
||||||
|
{4, 3, false},
|
||||||
|
{5, 6, true},
|
||||||
|
{5, 7, false},
|
||||||
|
}
|
||||||
|
for _, v := range tt {
|
||||||
|
t.Run(fmt.Sprintf("UserId%dIsPublicMemberOf%d", v.uid, v.orgid), func(t *testing.T) {
|
||||||
|
testUserIsPublicMember(t, v.uid, v.orgid, v.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUserIsPublicMember(t *testing.T, uid int64, orgID int64, expected bool) {
|
||||||
|
user, err := GetUserByID(uid)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expected, user.IsPublicMember(orgID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsUserOrgOwner(t *testing.T) {
|
||||||
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
|
||||||
|
tt := []struct {
|
||||||
|
uid int64
|
||||||
|
orgid int64
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{2, 3, true},
|
||||||
|
{4, 3, false},
|
||||||
|
{5, 6, true},
|
||||||
|
{5, 7, true},
|
||||||
|
}
|
||||||
|
for _, v := range tt {
|
||||||
|
t.Run(fmt.Sprintf("UserId%dIsOrgOwnerOf%d", v.uid, v.orgid), func(t *testing.T) {
|
||||||
|
testIsUserOrgOwner(t, v.uid, v.orgid, v.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testIsUserOrgOwner(t *testing.T, uid int64, orgID int64, expected bool) {
|
||||||
|
user, err := GetUserByID(uid)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expected, user.IsUserOrgOwner(orgID))
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetUserEmailsByNames(t *testing.T) {
|
func TestGetUserEmailsByNames(t *testing.T) {
|
||||||
assert.NoError(t, PrepareTestDatabase())
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
|
||||||
|
@ -83,7 +136,7 @@ func TestSearchUsers(t *testing.T) {
|
||||||
[]int64{7, 17})
|
[]int64{7, 17})
|
||||||
|
|
||||||
testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 3, PageSize: 2},
|
testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 3, PageSize: 2},
|
||||||
[]int64{19})
|
[]int64{19, 25})
|
||||||
|
|
||||||
testOrgSuccess(&SearchUserOptions{Page: 4, PageSize: 2},
|
testOrgSuccess(&SearchUserOptions{Page: 4, PageSize: 2},
|
||||||
[]int64{})
|
[]int64{})
|
||||||
|
@ -95,13 +148,13 @@ func TestSearchUsers(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
testUserSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 1},
|
testUserSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 1},
|
||||||
[]int64{1, 2, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21})
|
[]int64{1, 2, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24})
|
||||||
|
|
||||||
testUserSuccess(&SearchUserOptions{Page: 1, IsActive: util.OptionalBoolFalse},
|
testUserSuccess(&SearchUserOptions{Page: 1, IsActive: util.OptionalBoolFalse},
|
||||||
[]int64{9})
|
[]int64{9})
|
||||||
|
|
||||||
testUserSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 1, IsActive: util.OptionalBoolTrue},
|
testUserSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 1, IsActive: util.OptionalBoolTrue},
|
||||||
[]int64{1, 2, 4, 5, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21})
|
[]int64{1, 2, 4, 5, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24})
|
||||||
|
|
||||||
testUserSuccess(&SearchUserOptions{Keyword: "user1", OrderBy: "id ASC", Page: 1, IsActive: util.OptionalBoolTrue},
|
testUserSuccess(&SearchUserOptions{Keyword: "user1", OrderBy: "id ASC", Page: 1, IsActive: util.OptionalBoolTrue},
|
||||||
[]int64{1, 10, 11, 12, 13, 14, 15, 16, 18})
|
[]int64{1, 10, 11, 12, 13, 14, 15, 16, 18})
|
||||||
|
|
95
models/userlist.go
Normal file
95
models/userlist.go
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
//UserList is a list of user.
|
||||||
|
// This type provide valuable methods to retrieve information for a group of users efficiently.
|
||||||
|
type UserList []*User
|
||||||
|
|
||||||
|
func (users UserList) getUserIDs() []int64 {
|
||||||
|
userIDs := make([]int64, len(users))
|
||||||
|
for _, user := range users {
|
||||||
|
userIDs = append(userIDs, user.ID) //Considering that user id are unique in the list
|
||||||
|
}
|
||||||
|
return userIDs
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUserOrgOwner returns true if user is in the owner team of given organization.
|
||||||
|
func (users UserList) IsUserOrgOwner(orgID int64) map[int64]bool {
|
||||||
|
results := make(map[int64]bool, len(users))
|
||||||
|
for _, user := range users {
|
||||||
|
results[user.ID] = false //Set default to false
|
||||||
|
}
|
||||||
|
ownerMaps, err := users.loadOrganizationOwners(x, orgID)
|
||||||
|
if err == nil {
|
||||||
|
for _, owner := range ownerMaps {
|
||||||
|
results[owner.UID] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func (users UserList) loadOrganizationOwners(e Engine, orgID int64) (map[int64]*TeamUser, error) {
|
||||||
|
if len(users) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
ownerTeam, err := getOwnerTeam(e, orgID)
|
||||||
|
if err != nil {
|
||||||
|
if err == ErrTeamNotExist {
|
||||||
|
log.Error("Organization does not have owner team: %d", orgID)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userIDs := users.getUserIDs()
|
||||||
|
ownerMaps := make(map[int64]*TeamUser)
|
||||||
|
err = e.In("uid", userIDs).
|
||||||
|
And("org_id=?", orgID).
|
||||||
|
And("team_id=?", ownerTeam.ID).
|
||||||
|
Find(&ownerMaps)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("find team users: %v", err)
|
||||||
|
}
|
||||||
|
return ownerMaps, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTwoFaStatus return state of 2FA enrollement
|
||||||
|
func (users UserList) GetTwoFaStatus() map[int64]bool {
|
||||||
|
results := make(map[int64]bool, len(users))
|
||||||
|
for _, user := range users {
|
||||||
|
results[user.ID] = false //Set default to false
|
||||||
|
}
|
||||||
|
tokenMaps, err := users.loadTwoFactorStatus(x)
|
||||||
|
if err == nil {
|
||||||
|
for _, token := range tokenMaps {
|
||||||
|
results[token.UID] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func (users UserList) loadTwoFactorStatus(e Engine) (map[int64]*TwoFactor, error) {
|
||||||
|
if len(users) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
userIDs := users.getUserIDs()
|
||||||
|
tokenMaps := make(map[int64]*TwoFactor, len(userIDs))
|
||||||
|
err := e.
|
||||||
|
In("uid", userIDs).
|
||||||
|
Find(&tokenMaps)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("find two factor: %v", err)
|
||||||
|
}
|
||||||
|
return tokenMaps, nil
|
||||||
|
}
|
90
models/userlist_test.go
Normal file
90
models/userlist_test.go
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUserListIsPublicMember(t *testing.T) {
|
||||||
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
tt := []struct {
|
||||||
|
orgid int64
|
||||||
|
expected map[int64]bool
|
||||||
|
}{
|
||||||
|
{3, map[int64]bool{2: true, 4: false}},
|
||||||
|
{6, map[int64]bool{5: true}},
|
||||||
|
{7, map[int64]bool{5: false}},
|
||||||
|
{25, map[int64]bool{24: true}},
|
||||||
|
{22, map[int64]bool{}},
|
||||||
|
}
|
||||||
|
for _, v := range tt {
|
||||||
|
t.Run(fmt.Sprintf("IsPublicMemberOfOrdIg%d", v.orgid), func(t *testing.T) {
|
||||||
|
testUserListIsPublicMember(t, v.orgid, v.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func testUserListIsPublicMember(t *testing.T, orgID int64, expected map[int64]bool) {
|
||||||
|
org, err := GetUserByID(orgID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, org.GetMembers())
|
||||||
|
assert.Equal(t, expected, org.MembersIsPublic)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUserListIsUserOrgOwner(t *testing.T) {
|
||||||
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
tt := []struct {
|
||||||
|
orgid int64
|
||||||
|
expected map[int64]bool
|
||||||
|
}{
|
||||||
|
{3, map[int64]bool{2: true, 4: false}},
|
||||||
|
{6, map[int64]bool{5: true}},
|
||||||
|
{7, map[int64]bool{5: true}},
|
||||||
|
{25, map[int64]bool{24: false}}, // ErrTeamNotExist
|
||||||
|
{22, map[int64]bool{}}, // No member
|
||||||
|
}
|
||||||
|
for _, v := range tt {
|
||||||
|
t.Run(fmt.Sprintf("IsUserOrgOwnerOfOrdIg%d", v.orgid), func(t *testing.T) {
|
||||||
|
testUserListIsUserOrgOwner(t, v.orgid, v.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUserListIsUserOrgOwner(t *testing.T, orgID int64, expected map[int64]bool) {
|
||||||
|
org, err := GetUserByID(orgID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, org.GetMembers())
|
||||||
|
assert.Equal(t, expected, org.Members.IsUserOrgOwner(orgID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUserListIsTwoFaEnrolled(t *testing.T) {
|
||||||
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
tt := []struct {
|
||||||
|
orgid int64
|
||||||
|
expected map[int64]bool
|
||||||
|
}{
|
||||||
|
{3, map[int64]bool{2: false, 4: false}},
|
||||||
|
{6, map[int64]bool{5: false}},
|
||||||
|
{7, map[int64]bool{5: false}},
|
||||||
|
{25, map[int64]bool{24: true}},
|
||||||
|
{22, map[int64]bool{}},
|
||||||
|
}
|
||||||
|
for _, v := range tt {
|
||||||
|
t.Run(fmt.Sprintf("IsTwoFaEnrolledOfOrdIg%d", v.orgid), func(t *testing.T) {
|
||||||
|
testUserListIsTwoFaEnrolled(t, v.orgid, v.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUserListIsTwoFaEnrolled(t *testing.T, orgID int64, expected map[int64]bool) {
|
||||||
|
org, err := GetUserByID(orgID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, org.GetMembers())
|
||||||
|
assert.Equal(t, expected, org.Members.GetTwoFaStatus())
|
||||||
|
}
|
|
@ -108,6 +108,11 @@ func (te *TreeEntry) IsRegular() bool {
|
||||||
return te.gogitTreeEntry.Mode == filemode.Regular
|
return te.gogitTreeEntry.Mode == filemode.Regular
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsExecutable if the entry is an executable file (not necessarily binary)
|
||||||
|
func (te *TreeEntry) IsExecutable() bool {
|
||||||
|
return te.gogitTreeEntry.Mode == filemode.Executable
|
||||||
|
}
|
||||||
|
|
||||||
// Blob returns the blob object the entry
|
// Blob returns the blob object the entry
|
||||||
func (te *TreeEntry) Blob() *Blob {
|
func (te *TreeEntry) Blob() *Blob {
|
||||||
encodedObj, err := te.ptree.repo.gogitRepo.Storer.EncodedObject(plumbing.AnyObject, te.gogitTreeEntry.Hash)
|
encodedObj, err := te.ptree.repo.gogitRepo.Storer.EncodedObject(plumbing.AnyObject, te.gogitTreeEntry.Hash)
|
||||||
|
|
|
@ -19,9 +19,11 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
// File names that are representing highlight classes.
|
// File names that are representing highlight classes.
|
||||||
highlightFileNames = map[string]bool{
|
highlightFileNames = map[string]string{
|
||||||
"dockerfile": true,
|
"dockerfile": "dockerfile",
|
||||||
"makefile": true,
|
"makefile": "makefile",
|
||||||
|
"gnumakefile": "makefile",
|
||||||
|
"cmakelists.txt": "cmake",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extensions that are same as highlight classes.
|
// Extensions that are same as highlight classes.
|
||||||
|
@ -87,8 +89,8 @@ func FileNameToHighlightClass(fname string) string {
|
||||||
return "nohighlight"
|
return "nohighlight"
|
||||||
}
|
}
|
||||||
|
|
||||||
if highlightFileNames[fname] {
|
if name, ok := highlightFileNames[fname]; ok {
|
||||||
return fname
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
ext := path.Ext(fname)
|
ext := path.Ext(fname)
|
||||||
|
|
|
@ -633,10 +633,11 @@ footer .ui.left,footer .ui.right{line-height:40px}
|
||||||
.repository #commits-table thead .shatd{text-align:center}
|
.repository #commits-table thead .shatd{text-align:center}
|
||||||
.repository #commits-table td.sha .sha.label{margin:0}
|
.repository #commits-table td.sha .sha.label{margin:0}
|
||||||
.repository #commits-table.ui.basic.striped.table tbody tr:nth-child(2n){background-color:rgba(0,0,0,.02)!important}
|
.repository #commits-table.ui.basic.striped.table tbody tr:nth-child(2n){background-color:rgba(0,0,0,.02)!important}
|
||||||
.repository #commits-table td.sha .sha.label.isSigned,.repository #repo-files-table .sha.label.isSigned{border:1px solid #bbb}
|
.repository #commits-table td.sha .sha.label,.repository #repo-files-table .sha.label{border:1px solid #bbb}
|
||||||
.repository #commits-table td.sha .sha.label.isSigned .detail.icon,.repository #repo-files-table .sha.label.isSigned .detail.icon{background:#fafafa;margin:-6px -10px -4px 0;padding:5px 3px 5px 6px;border-left:1px solid #bbb;border-top-left-radius:0;border-bottom-left-radius:0}
|
.repository #commits-table td.sha .sha.label .detail.icon,.repository #repo-files-table .sha.label .detail.icon{background:#fafafa;margin:-6px -10px -4px 0;padding:5px 3px 5px 6px;border-left:1px solid #bbb;border-top-left-radius:0;border-bottom-left-radius:0}
|
||||||
.repository #commits-table td.sha .sha.label.isSigned.isVerified,.repository #repo-files-table .sha.label.isSigned.isVerified{border:1px solid #21ba45;background:rgba(33,186,69,.1)}
|
.repository #commits-table td.sha .sha.label.isSigned.isVerified,.repository #repo-files-table .sha.label.isSigned.isVerified{border:1px solid #21ba45;background:rgba(33,186,69,.1)}
|
||||||
.repository #commits-table td.sha .sha.label.isSigned.isVerified .detail.icon,.repository #repo-files-table .sha.label.isSigned.isVerified .detail.icon{border-left:1px solid rgba(33,186,69,.5)}
|
.repository #commits-table td.sha .sha.label.isSigned.isVerified .detail.icon,.repository #repo-files-table .sha.label.isSigned.isVerified .detail.icon{border-left:1px solid #21ba45}
|
||||||
|
.repository #commits-table td.sha .sha.label.isSigned.isVerified:hover,.repository #repo-files-table .sha.label.isSigned.isVerified:hover{background:rgba(33,186,69,.3)!important}
|
||||||
.repository .diff-detail-box{padding:7px 0;background:#fff;line-height:30px}
|
.repository .diff-detail-box{padding:7px 0;background:#fff;line-height:30px}
|
||||||
.repository .diff-detail-box>div:after{clear:both;content:"";display:block}
|
.repository .diff-detail-box>div:after{clear:both;content:"";display:block}
|
||||||
.repository .diff-detail-box ol{clear:both;padding-left:0;margin-top:5px;margin-bottom:28px}
|
.repository .diff-detail-box ol{clear:both;padding-left:0;margin-top:5px;margin-bottom:28px}
|
||||||
|
|
|
@ -211,7 +211,9 @@ input{background:#2e323e}
|
||||||
.ui.basic.blue.button:hover,.ui.basic.blue.buttons .button:hover{box-shadow:0 0 0 1px #87ab63 inset!important;color:#87ab63!important}
|
.ui.basic.blue.button:hover,.ui.basic.blue.buttons .button:hover{box-shadow:0 0 0 1px #87ab63 inset!important;color:#87ab63!important}
|
||||||
.ui.basic.blue.button:focus,.ui.basic.blue.buttons .button:focus{box-shadow:0 0 0 1px #87ab63 inset!important;color:#87ab63!important}
|
.ui.basic.blue.button:focus,.ui.basic.blue.buttons .button:focus{box-shadow:0 0 0 1px #87ab63 inset!important;color:#87ab63!important}
|
||||||
.repository.file.list #file-content .code-view .lines-code .hljs,.repository.file.list #file-content .code-view .lines-code ol,.repository.file.list #file-content .code-view .lines-code pre,.repository.file.list #file-content .code-view .lines-num .hljs,.repository.file.list #file-content .code-view .lines-num ol,.repository.file.list #file-content .code-view .lines-num pre{background-color:#2a2e3a}
|
.repository.file.list #file-content .code-view .lines-code .hljs,.repository.file.list #file-content .code-view .lines-code ol,.repository.file.list #file-content .code-view .lines-code pre,.repository.file.list #file-content .code-view .lines-num .hljs,.repository.file.list #file-content .code-view .lines-num ol,.repository.file.list #file-content .code-view .lines-num pre{background-color:#2a2e3a}
|
||||||
a.ui.label:hover,a.ui.labels .label:hover{background-color:#505667;color:#dbdbdb}
|
a.ui.label:hover,a.ui.labels .label:hover{background-color:#505667!important;color:#dbdbdb!important}
|
||||||
|
.repository #commits-table td.sha .sha.label,.repository #repo-files-table .sha.label{border-color:#888}
|
||||||
|
.repository #commits-table td.sha .sha.label.isSigned .detail.icon,.repository #repo-files-table .sha.label.isSigned .detail.icon{background:0 0;border-left-color:#888}
|
||||||
.repository .label.list .item{border-bottom:1px dashed #4c505c}
|
.repository .label.list .item{border-bottom:1px dashed #4c505c}
|
||||||
.ui.basic.blue.button,.ui.basic.blue.buttons .button{box-shadow:0 0 0 1px #87ab63 inset!important;color:#87ab63!important}
|
.ui.basic.blue.button,.ui.basic.blue.buttons .button{box-shadow:0 0 0 1px #87ab63 inset!important;color:#87ab63!important}
|
||||||
.repository.file.list #file-content .code-view .hljs,.repository.file.list #file-content .code-view .lines-code ol,.repository.file.list #file-content .code-view .lines-code pre,.repository.file.list #file-content .code-view .lines-num .hljs,.repository.file.list #file-content .code-view .lines-num ol,.repository.file.list #file-content .code-view .lines-num pre{background-color:#2a2e3a}
|
.repository.file.list #file-content .code-view .hljs,.repository.file.list #file-content .code-view .lines-code ol,.repository.file.list #file-content .code-view .lines-code pre,.repository.file.list #file-content .code-view .lines-num .hljs,.repository.file.list #file-content .code-view .lines-num ol,.repository.file.list #file-content .code-view .lines-num pre{background-color:#2a2e3a}
|
||||||
|
|
|
@ -1272,17 +1272,15 @@
|
||||||
|
|
||||||
#commits-table td.sha .sha.label,
|
#commits-table td.sha .sha.label,
|
||||||
#repo-files-table .sha.label {
|
#repo-files-table .sha.label {
|
||||||
&.isSigned {
|
border: 1px solid #bbbbbb;
|
||||||
border: 1px solid #bbbbbb;
|
|
||||||
|
|
||||||
.detail.icon {
|
.detail.icon {
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
margin: -6px -10px -4px 0;
|
margin: -6px -10px -4px 0;
|
||||||
padding: 5px 3px 5px 6px;
|
padding: 5px 3px 5px 6px;
|
||||||
border-left: 1px solid #bbbbbb;
|
border-left: 1px solid #bbbbbb;
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.isSigned.isVerified {
|
&.isSigned.isVerified {
|
||||||
|
@ -1290,7 +1288,11 @@
|
||||||
background: fade(#21ba45, 10%);
|
background: fade(#21ba45, 10%);
|
||||||
|
|
||||||
.detail.icon {
|
.detail.icon {
|
||||||
border-left: 1px solid fade(#21ba45, 50%);
|
border-left: 1px solid #21ba45;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: fade(#21ba45, 30%) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1091,8 +1091,19 @@ input {
|
||||||
|
|
||||||
a.ui.label:hover,
|
a.ui.label:hover,
|
||||||
a.ui.labels .label:hover {
|
a.ui.labels .label:hover {
|
||||||
background-color: #505667;
|
background-color: #505667 !important;
|
||||||
color: #dbdbdb;
|
color: #dbdbdb !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.repository #commits-table td.sha .sha.label,
|
||||||
|
.repository #repo-files-table .sha.label {
|
||||||
|
border-color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.repository #commits-table td.sha .sha.label.isSigned .detail.icon,
|
||||||
|
.repository #repo-files-table .sha.label.isSigned .detail.icon {
|
||||||
|
background: none;
|
||||||
|
border-left-color: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
.repository .label.list .item {
|
.repository .label.list .item {
|
||||||
|
|
|
@ -82,6 +82,15 @@ func GetAllOrgs(ctx *context.APIContext) {
|
||||||
// summary: List all organizations
|
// summary: List all organizations
|
||||||
// produces:
|
// produces:
|
||||||
// - application/json
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: page
|
||||||
|
// in: query
|
||||||
|
// description: page number of results to return (1-based)
|
||||||
|
// type: integer
|
||||||
|
// - name: limit
|
||||||
|
// in: query
|
||||||
|
// description: page size of results, maximum page size is 50
|
||||||
|
// type: integer
|
||||||
// responses:
|
// responses:
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/OrganizationList"
|
// "$ref": "#/responses/OrganizationList"
|
||||||
|
@ -90,7 +99,9 @@ func GetAllOrgs(ctx *context.APIContext) {
|
||||||
users, _, err := models.SearchUsers(&models.SearchUserOptions{
|
users, _, err := models.SearchUsers(&models.SearchUserOptions{
|
||||||
Type: models.UserTypeOrganization,
|
Type: models.UserTypeOrganization,
|
||||||
OrderBy: models.SearchOrderByAlphabetically,
|
OrderBy: models.SearchOrderByAlphabetically,
|
||||||
PageSize: -1,
|
Page: ctx.QueryInt("page"),
|
||||||
|
PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")),
|
||||||
|
Private: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(500, "SearchOrganizations", err)
|
ctx.Error(500, "SearchOrganizations", err)
|
||||||
|
|
|
@ -54,7 +54,7 @@ func initDBEngine() (err error) {
|
||||||
} else if i == setting.DBConnectRetries-1 {
|
} else if i == setting.DBConnectRetries-1 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Debug("ORM engine initialization attempt #%d/%d failed. Error: %v", i+1, setting.DBConnectRetries, err)
|
log.Error("ORM engine initialization attempt #%d/%d failed. Error: %v", i+1, setting.DBConnectRetries, err)
|
||||||
log.Info("Backing off for %d seconds", int64(setting.DBConnectBackoff/time.Second))
|
log.Info("Backing off for %d seconds", int64(setting.DBConnectBackoff/time.Second))
|
||||||
time.Sleep(setting.DBConnectBackoff)
|
time.Sleep(setting.DBConnectBackoff)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ const (
|
||||||
tplMembers base.TplName = "org/member/members"
|
tplMembers base.TplName = "org/member/members"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Members render orgnization users page
|
// Members render organization users page
|
||||||
func Members(ctx *context.Context) {
|
func Members(ctx *context.Context) {
|
||||||
org := ctx.Org.Organization
|
org := ctx.Org.Organization
|
||||||
ctx.Data["Title"] = org.FullName
|
ctx.Data["Title"] = org.FullName
|
||||||
|
@ -30,11 +30,14 @@ func Members(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Members"] = org.Members
|
ctx.Data["Members"] = org.Members
|
||||||
|
ctx.Data["MembersIsPublicMember"] = org.MembersIsPublic
|
||||||
|
ctx.Data["MembersIsUserOrgOwner"] = org.Members.IsUserOrgOwner(org.ID)
|
||||||
|
ctx.Data["MembersTwoFaStatus"] = org.Members.GetTwoFaStatus()
|
||||||
|
|
||||||
ctx.HTML(200, tplMembers)
|
ctx.HTML(200, tplMembers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MembersAction response for operation to a member of orgnization
|
// MembersAction response for operation to a member of organization
|
||||||
func MembersAction(ctx *context.Context) {
|
func MembersAction(ctx *context.Context) {
|
||||||
uid := com.StrTo(ctx.Query("uid")).MustInt64()
|
uid := com.StrTo(ctx.Query("uid")).MustInt64()
|
||||||
if uid == 0 {
|
if uid == 0 {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
|
|
||||||
<div class="list">
|
<div class="list">
|
||||||
{{range .Members}}
|
{{ range .Members}}
|
||||||
<div class="item ui grid">
|
<div class="item ui grid">
|
||||||
<div class="ui one wide column">
|
<div class="ui one wide column">
|
||||||
<img class="ui avatar" src="{{.SizedRelAvatarLink 48}}">
|
<img class="ui avatar" src="{{.SizedRelAvatarLink 48}}">
|
||||||
|
@ -14,12 +14,12 @@
|
||||||
<div class="meta"><a href="{{.HomeLink}}">{{.Name}}</a></div>
|
<div class="meta"><a href="{{.HomeLink}}">{{.Name}}</a></div>
|
||||||
<div class="meta">{{.FullName}}</div>
|
<div class="meta">{{.FullName}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui five wide column center">
|
<div class="ui four wide column center">
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
{{$.i18n.Tr "org.members.membership_visibility"}}
|
{{$.i18n.Tr "org.members.membership_visibility"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
{{ $isPublic := .IsPublicMember $.Org.ID}}
|
{{ $isPublic := index $.MembersIsPublicMember .ID}}
|
||||||
{{if $isPublic}}
|
{{if $isPublic}}
|
||||||
<strong>{{$.i18n.Tr "org.members.public"}}</strong>
|
<strong>{{$.i18n.Tr "org.members.public"}}</strong>
|
||||||
{{if or (eq $.SignedUser.ID .ID) $.IsOrganizationOwner}}(<a href="{{$.OrgLink}}/members/action/private?uid={{.ID}}">{{$.i18n.Tr "org.members.public_helper"}}</a>){{end}}
|
{{if or (eq $.SignedUser.ID .ID) $.IsOrganizationOwner}}(<a href="{{$.OrgLink}}/members/action/private?uid={{.ID}}">{{$.i18n.Tr "org.members.public_helper"}}</a>){{end}}
|
||||||
|
@ -34,7 +34,15 @@
|
||||||
{{$.i18n.Tr "org.members.member_role"}}
|
{{$.i18n.Tr "org.members.member_role"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<strong>{{if .IsUserOrgOwner $.Org.ID}}<span class="octicon octicon-shield"></span> {{$.i18n.Tr "org.members.owner"}}{{else}}{{$.i18n.Tr "org.members.member"}}{{end}}</strong>
|
<strong>{{if index $.MembersIsUserOrgOwner .ID}}<span class="octicon octicon-shield"></span> {{$.i18n.Tr "org.members.owner"}}{{else}}{{$.i18n.Tr "org.members.member"}}{{end}}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui one wide column center">
|
||||||
|
<div class="meta">
|
||||||
|
2FA
|
||||||
|
</div>
|
||||||
|
<div class="meta">
|
||||||
|
<strong><span class="octicon {{if index $.MembersTwoFaStatus .ID}}octicon-check text green{{else}}octicon-x{{end}}"></span></strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui four wide column">
|
<div class="ui four wide column">
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<a href="{{AppSubUrl}}/{{$.Username}}/{{$.Reponame}}/commit/{{.Rev}}">{{ .ShortRev}}</a>
|
<a href="{{AppSubUrl}}/{{$.Username}}/{{$.Reponame}}/commit/{{.Rev}}">{{ .ShortRev}}</a>
|
||||||
</code>
|
</code>
|
||||||
<strong> {{.Branch}}</strong>
|
<strong> {{.Branch}}</strong>
|
||||||
<em>{{RenderCommitMessage .Subject $.RepoLink $.Repository.ComposeMetas}}</em> by
|
<span class="has-emoji">{{RenderCommitMessage .Subject $.RepoLink $.Repository.ComposeMetas}}</span> by
|
||||||
<span class="author">
|
<span class="author">
|
||||||
{{.Author}}
|
{{.Author}}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -33,6 +33,20 @@
|
||||||
],
|
],
|
||||||
"summary": "List all organizations",
|
"summary": "List all organizations",
|
||||||
"operationId": "adminGetAllOrgs",
|
"operationId": "adminGetAllOrgs",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "page number of results to return (1-based)",
|
||||||
|
"name": "page",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "page size of results, maximum page size is 50",
|
||||||
|
"name": "limit",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"$ref": "#/responses/OrganizationList"
|
"$ref": "#/responses/OrganizationList"
|
||||||
|
|
2
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/.editorconfig
generated
vendored
2
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/.editorconfig
generated
vendored
|
@ -10,4 +10,4 @@ trim_trailing_whitespace = true
|
||||||
|
|
||||||
[*.go]
|
[*.go]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
indent_size = 4
|
indent_size = 8
|
||||||
|
|
3
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/.gitignore
generated
vendored
3
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/.gitignore
generated
vendored
|
@ -24,3 +24,6 @@ _testmain.go
|
||||||
*.test
|
*.test
|
||||||
*.prof
|
*.prof
|
||||||
|
|
||||||
|
# EditorConfig
|
||||||
|
|
||||||
|
/editorconfig
|
||||||
|
|
3
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/.gitmodules
generated
vendored
Normal file
3
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/.gitmodules
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "core-test"]
|
||||||
|
path = core-test
|
||||||
|
url = https://github.com/editorconfig/editorconfig-core-test.git
|
14
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/.travis.yml
generated
vendored
Normal file
14
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
language: go
|
||||||
|
sudo: false
|
||||||
|
go:
|
||||||
|
- '1.8'
|
||||||
|
- '1.9'
|
||||||
|
- '1.10'
|
||||||
|
go_import_path: gopkg.in/editorconfig/editorconfig-core-go.v1
|
||||||
|
|
||||||
|
install:
|
||||||
|
- make installdeps
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make test
|
25
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/Makefile
generated
vendored
Normal file
25
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/Makefile
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
PROJECT_ROOT_DIR := $(CURDIR)
|
||||||
|
SRC := editorconfig.go cmd/editorconfig/main.go
|
||||||
|
|
||||||
|
.PHONY: bin test test-go test-core submodule installdeps
|
||||||
|
|
||||||
|
test: test-go test-core
|
||||||
|
|
||||||
|
submodule:
|
||||||
|
git submodule update --init
|
||||||
|
|
||||||
|
installdeps:
|
||||||
|
go get -t ./...
|
||||||
|
|
||||||
|
editorconfig: $(SRC)
|
||||||
|
go build ./cmd/editorconfig
|
||||||
|
|
||||||
|
test-go:
|
||||||
|
go test -v
|
||||||
|
|
||||||
|
test-core: editorconfig
|
||||||
|
cd $(PROJECT_ROOT_DIR)/core-test && \
|
||||||
|
cmake -DEDITORCONFIG_CMD="$(PROJECT_ROOT_DIR)/editorconfig" .
|
||||||
|
# Temporarily disable core-test
|
||||||
|
# cd $(PROJECT_ROOT_DIR)/core-test && \
|
||||||
|
# ctest --output-on-failure .
|
3
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/README.md
generated
vendored
3
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/README.md
generated
vendored
|
@ -1,3 +1,4 @@
|
||||||
|
[![Build Status](https://travis-ci.org/editorconfig/editorconfig-core-go.svg?branch=master)](https://travis-ci.org/editorconfig/editorconfig-core-go)
|
||||||
[![GoDoc](https://godoc.org/gopkg.in/editorconfig/editorconfig-core-go.v1?status.svg)](https://godoc.org/gopkg.in/editorconfig/editorconfig-core-go.v1)
|
[![GoDoc](https://godoc.org/gopkg.in/editorconfig/editorconfig-core-go.v1?status.svg)](https://godoc.org/gopkg.in/editorconfig/editorconfig-core-go.v1)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/gopkg.in/editorconfig/editorconfig-core-go.v1)](https://goreportcard.com/report/gopkg.in/editorconfig/editorconfig-core-go.v1)
|
[![Go Report Card](https://goreportcard.com/badge/gopkg.in/editorconfig/editorconfig-core-go.v1)](https://goreportcard.com/report/gopkg.in/editorconfig/editorconfig-core-go.v1)
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ We recommend the use of [gopkg.in][gopkg] for this package:
|
||||||
go get -u gopkg.in/editorconfig/editorconfig-core-go.v1
|
go get -u gopkg.in/editorconfig/editorconfig-core-go.v1
|
||||||
```
|
```
|
||||||
|
|
||||||
Import by the same path. Tha package name you will use to access it is
|
Import by the same path. The package name you will use to access it is
|
||||||
`editorconfig`.
|
`editorconfig`.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
|
57
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/editorconfig.go
generated
vendored
57
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/editorconfig.go
generated
vendored
|
@ -14,6 +14,10 @@ import (
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ConfigNameDefault = ".editorconfig"
|
||||||
|
)
|
||||||
|
|
||||||
// IndentStyle possible values
|
// IndentStyle possible values
|
||||||
const (
|
const (
|
||||||
IndentStyleTab = "tab"
|
IndentStyleTab = "tab"
|
||||||
|
@ -49,6 +53,8 @@ type Definition struct {
|
||||||
EndOfLine string `ini:"end_of_line" json:"end_of_line,omitempty"`
|
EndOfLine string `ini:"end_of_line" json:"end_of_line,omitempty"`
|
||||||
TrimTrailingWhitespace bool `ini:"trim_trailing_whitespace" json:"trim_trailing_whitespace,omitempty"`
|
TrimTrailingWhitespace bool `ini:"trim_trailing_whitespace" json:"trim_trailing_whitespace,omitempty"`
|
||||||
InsertFinalNewline bool `ini:"insert_final_newline" json:"insert_final_newline,omitempty"`
|
InsertFinalNewline bool `ini:"insert_final_newline" json:"insert_final_newline,omitempty"`
|
||||||
|
|
||||||
|
Raw map[string]string `ini:"-" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Editorconfig represents a .editorconfig file.
|
// Editorconfig represents a .editorconfig file.
|
||||||
|
@ -75,6 +81,7 @@ func ParseBytes(data []byte) (*Editorconfig, error) {
|
||||||
var (
|
var (
|
||||||
iniSection = iniFile.Section(sectionStr)
|
iniSection = iniFile.Section(sectionStr)
|
||||||
definition = &Definition{}
|
definition = &Definition{}
|
||||||
|
raw = make(map[string]string)
|
||||||
)
|
)
|
||||||
err := iniSection.MapTo(&definition)
|
err := iniSection.MapTo(&definition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -89,7 +96,13 @@ func ParseBytes(data []byte) (*Editorconfig, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shallow copy all properties
|
||||||
|
for k, v := range iniSection.KeysHash() {
|
||||||
|
raw[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
definition.Selector = sectionStr
|
definition.Selector = sectionStr
|
||||||
|
definition.Raw = raw
|
||||||
editorConfig.Definitions = append(editorConfig.Definitions, definition)
|
editorConfig.Definitions = append(editorConfig.Definitions, definition)
|
||||||
}
|
}
|
||||||
return editorConfig, nil
|
return editorConfig, nil
|
||||||
|
@ -171,6 +184,19 @@ func (d *Definition) merge(md *Definition) {
|
||||||
if !d.InsertFinalNewline {
|
if !d.InsertFinalNewline {
|
||||||
d.InsertFinalNewline = md.InsertFinalNewline
|
d.InsertFinalNewline = md.InsertFinalNewline
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for k, v := range md.Raw {
|
||||||
|
if _, ok := d.Raw[k]; !ok {
|
||||||
|
d.Raw[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Definition) InsertToIniFile(iniFile *ini.File) {
|
||||||
|
iniSec := iniFile.Section(d.Selector)
|
||||||
|
for k, v := range d.Raw {
|
||||||
|
iniSec.Key(k).SetValue(v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDefinitionForFilename returns a definition for the given filename.
|
// GetDefinitionForFilename returns a definition for the given filename.
|
||||||
|
@ -178,6 +204,7 @@ func (d *Definition) merge(md *Definition) {
|
||||||
// The last section has preference over the priors.
|
// The last section has preference over the priors.
|
||||||
func (e *Editorconfig) GetDefinitionForFilename(name string) *Definition {
|
func (e *Editorconfig) GetDefinitionForFilename(name string) *Definition {
|
||||||
def := &Definition{}
|
def := &Definition{}
|
||||||
|
def.Raw = make(map[string]string)
|
||||||
for i := len(e.Definitions) - 1; i >= 0; i-- {
|
for i := len(e.Definitions) - 1; i >= 0; i-- {
|
||||||
actualDef := e.Definitions[i]
|
actualDef := e.Definitions[i]
|
||||||
if filenameMatches(actualDef.Selector, name) {
|
if filenameMatches(actualDef.Selector, name) {
|
||||||
|
@ -206,28 +233,7 @@ func (e *Editorconfig) Serialize() ([]byte, error) {
|
||||||
iniFile.Section(ini.DEFAULT_SECTION).Key("root").SetValue(boolToString(e.Root))
|
iniFile.Section(ini.DEFAULT_SECTION).Key("root").SetValue(boolToString(e.Root))
|
||||||
}
|
}
|
||||||
for _, d := range e.Definitions {
|
for _, d := range e.Definitions {
|
||||||
iniSec := iniFile.Section(d.Selector)
|
d.InsertToIniFile(iniFile)
|
||||||
if len(d.Charset) > 0 {
|
|
||||||
iniSec.Key("charset").SetValue(d.Charset)
|
|
||||||
}
|
|
||||||
if len(d.IndentStyle) > 0 {
|
|
||||||
iniSec.Key("indent_style").SetValue(d.IndentStyle)
|
|
||||||
}
|
|
||||||
if len(d.IndentSize) > 0 {
|
|
||||||
iniSec.Key("indent_size").SetValue(d.IndentSize)
|
|
||||||
}
|
|
||||||
if d.TabWidth > 0 && strconv.Itoa(d.TabWidth) != d.IndentSize {
|
|
||||||
iniSec.Key("tab_width").SetValue(strconv.Itoa(d.TabWidth))
|
|
||||||
}
|
|
||||||
if len(d.EndOfLine) > 0 {
|
|
||||||
iniSec.Key("end_of_line").SetValue(d.EndOfLine)
|
|
||||||
}
|
|
||||||
if d.TrimTrailingWhitespace {
|
|
||||||
iniSec.Key("trim_trailing_whitespace").SetValue(boolToString(d.TrimTrailingWhitespace))
|
|
||||||
}
|
|
||||||
if d.InsertFinalNewline {
|
|
||||||
iniSec.Key("insert_final_newline").SetValue(boolToString(d.InsertFinalNewline))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_, err := iniFile.WriteTo(buffer)
|
_, err := iniFile.WriteTo(buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -251,16 +257,21 @@ func (e *Editorconfig) Save(filename string) error {
|
||||||
// folder with `root = true`, and returns the right editorconfig
|
// folder with `root = true`, and returns the right editorconfig
|
||||||
// definition for the given file.
|
// definition for the given file.
|
||||||
func GetDefinitionForFilename(filename string) (*Definition, error) {
|
func GetDefinitionForFilename(filename string) (*Definition, error) {
|
||||||
|
return GetDefinitionForFilenameWithConfigname(filename, ConfigNameDefault)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDefinitionForFilenameWithConfigname(filename string, configname string) (*Definition, error) {
|
||||||
abs, err := filepath.Abs(filename)
|
abs, err := filepath.Abs(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
definition := &Definition{}
|
definition := &Definition{}
|
||||||
|
definition.Raw = make(map[string]string)
|
||||||
|
|
||||||
dir := abs
|
dir := abs
|
||||||
for dir != filepath.Dir(dir) {
|
for dir != filepath.Dir(dir) {
|
||||||
dir = filepath.Dir(dir)
|
dir = filepath.Dir(dir)
|
||||||
ecFile := filepath.Join(dir, ".editorconfig")
|
ecFile := filepath.Join(dir, configname)
|
||||||
if _, err := os.Stat(ecFile); os.IsNotExist(err) {
|
if _, err := os.Stat(ecFile); os.IsNotExist(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
|
@ -414,7 +414,7 @@ gopkg.in/alexcesaro/quotedprintable.v3
|
||||||
gopkg.in/asn1-ber.v1
|
gopkg.in/asn1-ber.v1
|
||||||
# gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e
|
# gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e
|
||||||
gopkg.in/bufio.v1
|
gopkg.in/bufio.v1
|
||||||
# gopkg.in/editorconfig/editorconfig-core-go.v1 v1.2.0
|
# gopkg.in/editorconfig/editorconfig-core-go.v1 v1.3.0
|
||||||
gopkg.in/editorconfig/editorconfig-core-go.v1
|
gopkg.in/editorconfig/editorconfig-core-go.v1
|
||||||
# gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
# gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/gomail.v2
|
gopkg.in/gomail.v2
|
||||||
|
|
Loading…
Reference in a new issue